diff --git a/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_dark.xml b/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_dark.xml
new file mode 100644
index 0000000000..eff45a9496
--- /dev/null
+++ b/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_dark.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_light.xml b/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_light.xml
new file mode 100644
index 0000000000..56b0695473
--- /dev/null
+++ b/OsmAnd/res/drawable/bg_bottom_sheet_sides_landscape_light.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_dark.xml b/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_dark.xml
new file mode 100644
index 0000000000..8e8827fc1d
--- /dev/null
+++ b/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_dark.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_light.xml b/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_light.xml
new file mode 100644
index 0000000000..d35d49da33
--- /dev/null
+++ b/OsmAnd/res/drawable/bg_bottom_sheet_topsides_landscape_light.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/drawable/btn_round_border_dark.xml b/OsmAnd/res/drawable/btn_round_border_dark.xml
new file mode 100644
index 0000000000..2298693b61
--- /dev/null
+++ b/OsmAnd/res/drawable/btn_round_border_dark.xml
@@ -0,0 +1,26 @@
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/drawable/btn_round_border_light.xml b/OsmAnd/res/drawable/btn_round_border_light.xml
new file mode 100644
index 0000000000..409be98cc2
--- /dev/null
+++ b/OsmAnd/res/drawable/btn_round_border_light.xml
@@ -0,0 +1,26 @@
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout-land/empty_state_favourites.xml b/OsmAnd/res/layout-land/empty_state_favourites.xml
new file mode 100644
index 0000000000..e3a77b04ab
--- /dev/null
+++ b/OsmAnd/res/layout-land/empty_state_favourites.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout-land/empty_state_my_tracks.xml b/OsmAnd/res/layout-land/empty_state_my_tracks.xml
new file mode 100644
index 0000000000..80863986be
--- /dev/null
+++ b/OsmAnd/res/layout-land/empty_state_my_tracks.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout-land/fragment_measurement_tool.xml b/OsmAnd/res/layout-land/fragment_measurement_tool.xml
new file mode 100644
index 0000000000..c67868f0a9
--- /dev/null
+++ b/OsmAnd/res/layout-land/fragment_measurement_tool.xml
@@ -0,0 +1,345 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout-land/map_hud_bottom.xml b/OsmAnd/res/layout-land/map_hud_bottom.xml
index 8a496b8496..28441e0016 100644
--- a/OsmAnd/res/layout-land/map_hud_bottom.xml
+++ b/OsmAnd/res/layout-land/map_hud_bottom.xml
@@ -94,6 +94,15 @@
android:background="@drawable/btn_round"
android:contentDescription="@string/layer_route"
tools:src="@drawable/ic_action_test_light"/>
+
+
@@ -268,4 +277,9 @@
android:layout_gravity="bottom|left"
tools:visibility="visible"/>
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout-land/map_hud_top.xml b/OsmAnd/res/layout-land/map_hud_top.xml
index e651de0368..1772881368 100644
--- a/OsmAnd/res/layout-land/map_hud_top.xml
+++ b/OsmAnd/res/layout-land/map_hud_top.xml
@@ -3,6 +3,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:orientation="vertical">
+
+
+
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/ctx_menu_info_view_bg"
+ android:orientation="vertical">
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/empty_state_favourites.xml b/OsmAnd/res/layout/empty_state_favourites.xml
new file mode 100644
index 0000000000..ca57095bbc
--- /dev/null
+++ b/OsmAnd/res/layout/empty_state_favourites.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/empty_state_my_tracks.xml b/OsmAnd/res/layout/empty_state_my_tracks.xml
new file mode 100644
index 0000000000..2e9a969609
--- /dev/null
+++ b/OsmAnd/res/layout/empty_state_my_tracks.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/favorites_tree.xml b/OsmAnd/res/layout/favorites_tree.xml
index 22324a0e79..8c95ff1e50 100644
--- a/OsmAnd/res/layout/favorites_tree.xml
+++ b/OsmAnd/res/layout/favorites_tree.xml
@@ -1,9 +1,10 @@
+ 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">
+ android:groupIndicator="@android:color/transparent"/>
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml
index 9b2d999161..0e0feba970 100644
--- a/OsmAnd/res/layout/fragment_measurement_tool.xml
+++ b/OsmAnd/res/layout/fragment_measurement_tool.xml
@@ -1,6 +1,7 @@
-
+
+
-
@@ -68,12 +82,68 @@
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/measurement_distance_text_view"
- android:layout_toLeftOf="@id/up_down_button"
android:layout_toRightOf="@id/measurement_distance_text_view"
- android:layout_toStartOf="@id/up_down_button"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="points: 3"/>
+
+
+
+
+
+
+
+
-
+
+
-
-
-
+
-
+ android:layout_height="52dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml
new file mode 100644
index 0000000000..44173d60c8
--- /dev/null
+++ b/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/fragment_save_as_new_track_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_save_as_new_track_bottom_sheet_dialog.xml
new file mode 100644
index 0000000000..81619c88c7
--- /dev/null
+++ b/OsmAnd/res/layout/fragment_save_as_new_track_bottom_sheet_dialog.xml
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/fragment_selected_menu_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_selected_menu_bottom_sheet_dialog.xml
new file mode 100644
index 0000000000..03138ed207
--- /dev/null
+++ b/OsmAnd/res/layout/fragment_selected_menu_bottom_sheet_dialog.xml
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/fragment_snap_to_road_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_snap_to_road_bottom_sheet_dialog.xml
new file mode 100644
index 0000000000..2092dea9a5
--- /dev/null
+++ b/OsmAnd/res/layout/fragment_snap_to_road_bottom_sheet_dialog.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/gpx_item_altitude.xml b/OsmAnd/res/layout/gpx_item_altitude.xml
index ed7f0eda6b..db3e7d8029 100644
--- a/OsmAnd/res/layout/gpx_item_altitude.xml
+++ b/OsmAnd/res/layout/gpx_item_altitude.xml
@@ -264,6 +264,17 @@
android:orientation="horizontal"
android:gravity="center">
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/map_hud_bottom.xml b/OsmAnd/res/layout/map_hud_bottom.xml
index 8daa8371cb..2a8bf1d2f5 100644
--- a/OsmAnd/res/layout/map_hud_bottom.xml
+++ b/OsmAnd/res/layout/map_hud_bottom.xml
@@ -126,6 +126,15 @@
android:contentDescription="@string/layer_route"
tools:src="@drawable/ic_action_test_light"/>
+
+
@@ -234,6 +235,35 @@
android:contentDescription="@string/shared_string_close"
android:src="@drawable/ic_action_remove_dark"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/points_tree.xml b/OsmAnd/res/layout/my_places_fabs.xml
similarity index 51%
rename from OsmAnd/res/layout/points_tree.xml
rename to OsmAnd/res/layout/my_places_fabs.xml
index 1b1e97e048..46abc9966e 100644
--- a/OsmAnd/res/layout/points_tree.xml
+++ b/OsmAnd/res/layout/my_places_fabs.xml
@@ -1,72 +1,66 @@
-
-
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:osmand="http://schemas.android.com/apk/res-auto">
+ app:fabSize="normal"
+ app:useCompatPadding="true"/>
+ android:padding="8dp"
+ android:text="@string/add_waypoint"
+ android:textColor="?android:attr/textColorPrimary"
+ osmand:typeface="@string/font_roboto_medium"/>
@@ -75,38 +69,89 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/waypoint_fab"
+ android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
- android:layout_marginBottom="16dp"
- android:layout_marginRight="24dp"
+ android:layout_marginBottom="-16dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginRight="8dp"
android:contentDescription="@string/quick_action_new_action"
android:src="@drawable/ic_action_markers_dark"
android:visibility="gone"
- app:backgroundTint="@color/dashboard_blue"
+ app:backgroundTint="@color/fab_green"
app:fabSize="mini"
+ app:useCompatPadding="true"
tools:visibility="visible"/>
+ android:padding="8dp"
+ android:text="@string/add_route_points"
+ android:textColor="?android:attr/textColorPrimary"
+ osmand:typeface="@string/font_roboto_medium"/>
+
+
+
+
+
+
+
+
diff --git a/OsmAnd/res/layout/save_gpx_dialog.xml b/OsmAnd/res/layout/save_gpx_dialog.xml
index 7ae9fc7579..947b21db17 100644
--- a/OsmAnd/res/layout/save_gpx_dialog.xml
+++ b/OsmAnd/res/layout/save_gpx_dialog.xml
@@ -10,6 +10,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:inputType="text"/>
@@ -19,6 +21,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:gravity="center_horizontal"
android:text="@string/file_with_name_already_exists"
diff --git a/OsmAnd/res/layout/track_points_tree.xml b/OsmAnd/res/layout/track_points_tree.xml
new file mode 100644
index 0000000000..83a44d7fc9
--- /dev/null
+++ b/OsmAnd/res/layout/track_points_tree.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/track_segments_tree.xml b/OsmAnd/res/layout/track_segments_tree.xml
new file mode 100644
index 0000000000..a50fae2855
--- /dev/null
+++ b/OsmAnd/res/layout/track_segments_tree.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/menu/measurement_tool_menu.xml b/OsmAnd/res/menu/measurement_tool_menu.xml
deleted file mode 100644
index c39cdaa767..0000000000
--- a/OsmAnd/res/menu/measurement_tool_menu.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
\ No newline at end of file
diff --git a/OsmAnd/res/menu/track_segment_menu.xml b/OsmAnd/res/menu/track_segment_menu.xml
new file mode 100644
index 0000000000..196bb49b2f
--- /dev/null
+++ b/OsmAnd/res/menu/track_segment_menu.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/values-land/sizes.xml b/OsmAnd/res/values-land/sizes.xml
index 7cf56d5d90..4e116e39e1 100644
--- a/OsmAnd/res/values-land/sizes.xml
+++ b/OsmAnd/res/values-land/sizes.xml
@@ -4,4 +4,7 @@
24dp
48dp
+
+ 39dp
+ 39dp
\ No newline at end of file
diff --git a/OsmAnd/res/values-large-land/sizes.xml b/OsmAnd/res/values-large-land/sizes.xml
new file mode 100644
index 0000000000..2d48ca5083
--- /dev/null
+++ b/OsmAnd/res/values-large-land/sizes.xml
@@ -0,0 +1,5 @@
+
+
+ 59dp
+ 59dp
+
\ No newline at end of file
diff --git a/OsmAnd/res/values-large/sizes.xml b/OsmAnd/res/values-large/sizes.xml
index 375e91283d..2de1e4ff3d 100644
--- a/OsmAnd/res/values-large/sizes.xml
+++ b/OsmAnd/res/values-large/sizes.xml
@@ -78,5 +78,17 @@
15sp
15sp
12sp
+
+ 63dp
+ 45dp
+ 12dp
+ 30dp
+ 20sp
+ 18sp
+ 68dp
+ 138dp
+ 72dp
+ 90dp
+ 96dp
\ No newline at end of file
diff --git a/OsmAnd/res/values-sw600dp-port/sizes.xml b/OsmAnd/res/values-sw600dp/sizes.xml
similarity index 73%
rename from OsmAnd/res/values-sw600dp-port/sizes.xml
rename to OsmAnd/res/values-sw600dp/sizes.xml
index e4cf1852c8..5b2f539723 100644
--- a/OsmAnd/res/values-sw600dp-port/sizes.xml
+++ b/OsmAnd/res/values-sw600dp/sizes.xml
@@ -2,4 +2,6 @@
300dp
200dp
+
+ 48dp
\ No newline at end of file
diff --git a/OsmAnd/res/values/attrs.xml b/OsmAnd/res/values/attrs.xml
index f768775e3a..607dd9269b 100644
--- a/OsmAnd/res/values/attrs.xml
+++ b/OsmAnd/res/values/attrs.xml
@@ -16,6 +16,7 @@
+
diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml
index 4264d3cf00..12872af5b5 100644
--- a/OsmAnd/res/values/colors.xml
+++ b/OsmAnd/res/values/colors.xml
@@ -257,4 +257,6 @@
#fafafa
#101821
+ #46bd2a
+
\ No newline at end of file
diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml
index 5860d32a21..b9169ed80e 100644
--- a/OsmAnd/res/values/sizes.xml
+++ b/OsmAnd/res/values/sizes.xml
@@ -143,4 +143,21 @@
150dp
128dp
+
+ 42dp
+ 30dp
+ 8dp
+ 20dp
+ 18sp
+ 16sp
+ 45dp
+ 92dp
+ 48dp
+ 60dp
+ 64dp
+
+ 48dp
+ 360dp
+
+ 20dp
\ No newline at end of file
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index a2eb625e3e..86f300448b 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -9,6 +9,19 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
+ Altitude: %1$s
+ Speed: %1$s
+ Line
+ Save as Route Point
+ Save as line
+ Route point
+ Edit Line
+ Add point before
+ Add point after
+ Options
+ OsmAnd will add additional points, depending on the navigation type.
+ You can save points either as route points or as a line.
+ Choose navigation type
Please add at least one point.
GPX file name:
Show on map after saving
@@ -790,7 +803,7 @@
Clear
Clear all
Save
- Save as GPX track
+ Save as new Track
Rename
Delete
Delete all
@@ -2663,10 +2676,19 @@
Action name
You need internet to view photos from Mapillary
Retry
- Add Route Point
+ Add Route Points
Add Waypoint
+ Add Line
Save GPX Waypoint
Save Route Point
Waypoint 1
Route Point 1
+ Add and Record Tracks
+ Record or import tracks to view
+ Add Favorites
+ Add favorites on map or import them from filesystem
+ Import track
+ File %1$s does not contain waypoints, import it as a track?
+ Move Point
+ Add to a track
diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml
index a4a983d4bf..816136016b 100644
--- a/OsmAnd/res/values/styles.xml
+++ b/OsmAnd/res/values/styles.xml
@@ -109,6 +109,7 @@
- @color/actionbar_light_color
- @style/Widget.Styled.ActionBarLight
- @color/bg_color_light
+ - @drawable/btn_round_border_light
- @drawable/bg_card_light
- @drawable/context_menu_card_light
- @drawable/bg_map_context_menu_light
@@ -282,6 +283,7 @@
- @color/actionbar_dark_color
- @style/Widget.Styled.ActionBarDark
- @color/bg_color_dark
+ - @drawable/btn_round_border_dark
- @drawable/bg_card_dark
- @drawable/context_menu_card_dark
- @drawable/bg_map_context_menu_dark
diff --git a/OsmAnd/src/net/osmand/AndroidUtils.java b/OsmAnd/src/net/osmand/AndroidUtils.java
index 1aebe7c028..1bece94017 100644
--- a/OsmAnd/src/net/osmand/AndroidUtils.java
+++ b/OsmAnd/src/net/osmand/AndroidUtils.java
@@ -172,6 +172,27 @@ public class AndroidUtils {
return result;
}
+ public static int getNavBarHeight(Context ctx) {
+ if (!hasNavBar(ctx)) {
+ return 0;
+ }
+ boolean landscape = ctx.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+ boolean isSmartphone = ctx.getResources().getConfiguration().smallestScreenWidthDp < 600;
+ if (isSmartphone && landscape) {
+ return 0;
+ }
+ int id = ctx.getResources().getIdentifier(landscape ? "navigation_bar_height_landscape" : "navigation_bar_height", "dimen", "android");
+ if (id > 0) {
+ return ctx.getResources().getDimensionPixelSize(id);
+ }
+ return 0;
+ }
+
+ public static boolean hasNavBar(Context ctx) {
+ int id = ctx.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
+ return id > 0 && ctx.getResources().getBoolean(id);
+ }
+
public static int getScreenHeight(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
diff --git a/OsmAnd/src/net/osmand/plus/GPXUtilities.java b/OsmAnd/src/net/osmand/plus/GPXUtilities.java
index add5920fad..4cd24455c3 100644
--- a/OsmAnd/src/net/osmand/plus/GPXUtilities.java
+++ b/OsmAnd/src/net/osmand/plus/GPXUtilities.java
@@ -6,6 +6,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.ColorInt;
+import android.text.TextUtils;
import net.osmand.Location;
import net.osmand.PlatformUtil;
@@ -247,6 +248,7 @@ public class GPXUtilities {
public String name = null;
public String desc = null;
public List segments = new ArrayList<>();
+ public boolean generalTrack = false;
}
@@ -772,6 +774,7 @@ public class GPXUtilities {
track.segments = new ArrayList<>();
track.segments.add(generalSegment);
generalTrack = track;
+ track.generalTrack = true;
}
return generalTrack;
}
@@ -823,6 +826,14 @@ public class GPXUtilities {
return g;
}
+ public List getRoutePoints() {
+ List points = new ArrayList<>();
+ for (int i = 0; i < routes.size(); i++) {
+ Route rt = routes.get(i);
+ points.addAll(rt.points);
+ }
+ return points;
+ }
public boolean hasRtePt() {
for (Route r : routes) {
@@ -880,7 +891,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 +899,64 @@ public class GPXUtilities {
return pt;
}
+ public void addTrkSegment(List points) {
+ removeGeneralTrackIfExists();
+
+ 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 boolean replaceSegment(TrkSegment oldSegment, TrkSegment newSegment) {
+ removeGeneralTrackIfExists();
+
+ for (int i = 0; i < tracks.size(); i++) {
+ Track currentTrack = tracks.get(i);
+ for (int j = 0; j < currentTrack.segments.size(); j++) {
+ int segmentIndex = currentTrack.segments.indexOf(oldSegment);
+ if (segmentIndex != -1) {
+ currentTrack.segments.remove(segmentIndex);
+ currentTrack.segments.add(segmentIndex, newSegment);
+ addGeneralTrack();
+ modifiedTime = System.currentTimeMillis();
+ return true;
+ }
+ }
+ }
+
+ addGeneralTrack();
+ return false;
+ }
+
+ public void addRoutePoints(List points) {
+ if (routes.size() == 0) {
+ Route route = new Route();
+ routes.add(route);
+ }
+
+ Route lastRoute = routes.get(routes.size() - 1);
+
+ lastRoute.points.addAll(points);
+
+ modifiedTime = System.currentTimeMillis();
+ }
+
+ public void replaceRoutePoints(List points) {
+ routes.clear();
+ routes.add(new Route());
+ Route currentRoute = routes.get(routes.size() - 1);
+ currentRoute.points.addAll(points);
+
+ 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);
@@ -910,6 +979,32 @@ public class GPXUtilities {
modifiedTime = System.currentTimeMillis();
}
+ private void removeGeneralTrackIfExists() {
+ Track generalTrack = getGeneralTrack();
+ if (generalTrack != null) {
+ tracks.remove(generalTrack);
+ this.generalTrack = null;
+ this.generalSegment = null;
+ }
+ }
+
+ public boolean removeTrkSegment(TrkSegment segment) {
+ removeGeneralTrackIfExists();
+
+ for (int i = 0; i < tracks.size(); i++) {
+ Track currentTrack = tracks.get(i);
+ for (int j = 0; j < currentTrack.segments.size(); j++) {
+ if (currentTrack.segments.remove(segment)) {
+ addGeneralTrack();
+ modifiedTime = System.currentTimeMillis();
+ return true;
+ }
+ }
+ }
+ addGeneralTrack();
+ return false;
+ }
+
public boolean deleteWptPt(WptPt pt) {
modifiedTime = System.currentTimeMillis();
return points.remove(pt);
@@ -1014,6 +1109,19 @@ public class GPXUtilities {
}
return count;
}
+
+ public List getWaypointCategories() {
+ List categories = new ArrayList<>();
+ for (WptPt pt : points) {
+ String category = pt.category;
+ if (!TextUtils.isEmpty(category)) {
+ if (!categories.contains(category)) {
+ categories.add(category);
+ }
+ }
+ }
+ return categories;
+ }
}
public static String asString(GPXFile file, OsmandApplication ctx) {
diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
index 93b7f97da9..d7f0a3d237 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
@@ -1244,7 +1244,9 @@ 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 static final int LANDSCAPE_MIDDLE_RIGHT_CONSTANT = 4;
public final CommonPreference CENTER_POSITION_ON_MAP = new BooleanPreference("center_position_on_map", false).makeProfile();
// this value string is synchronized with settings_pref.xml preference name
diff --git a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java
index 9d305cb72c..d038d93105 100644
--- a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java
+++ b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java
@@ -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 favoritesSelected = new LinkedHashSet<>();
private Set 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 exportTask = new AsyncTask() {
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
index 897c35e7d1..4574a0892e 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
@@ -96,6 +96,7 @@ import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenu;
import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenuFragment;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
+import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routing.RoutingHelper;
@@ -501,13 +502,16 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
}
if (getMeasurementToolFragment() != null) {
- getMeasurementToolFragment().showQuitDialog();
+ getMeasurementToolFragment().quit(true);
return;
}
if (mapContextMenu.isVisible() && mapContextMenu.isClosable()) {
mapContextMenu.close();
return;
}
+ if (getMapLayers().getContextMenuLayer().isInAddGpxPointMode()) {
+ quitAddGpxPointMode();
+ }
if (prevActivityIntent != null && getSupportFragmentManager().getBackStackEntryCount() == 0) {
prevActivityIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
LatLon loc = getMapLocation();
@@ -527,6 +531,11 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
+ private void quitAddGpxPointMode() {
+ getMapLayers().getContextMenuLayer().getAddGpxPointBottomSheetHelper().hide();
+ getMapLayers().getContextMenuLayer().quitAddGpxPoint();
+ }
+
@Override
protected void onRestart() {
super.onRestart();
@@ -928,7 +937,14 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
} else if (toShow instanceof NewGpxPoint) {
NewGpxPoint newGpxPoint = (NewGpxPoint) toShow;
+ QuadRect qr = newGpxPoint.getRect();
+ mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
getMapLayers().getContextMenuLayer().enterAddGpxPointMode(newGpxPoint);
+ } else if (toShow instanceof NewGpxData) {
+ NewGpxData newGpxData = (NewGpxData) toShow;
+ QuadRect qr = newGpxData.getRect();
+ mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
+ MeasurementToolFragment.showInstance(getSupportFragmentManager(), newGpxData);
} else {
mapContextMenu.show(latLonToShow, mapLabelToShow, toShow);
}
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
index 31d29d860b..094a7d1179 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
@@ -764,12 +764,7 @@ public class MapActivityActions implements DialogProvider {
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter adapter, int itemId, int position, boolean isChecked) {
- MeasurementToolFragment fragment = new MeasurementToolFragment();
- mapActivity.getSupportFragmentManager()
- .beginTransaction()
- .add(R.id.bottomFragmentContainer, fragment, MeasurementToolFragment.TAG)
- .addToBackStack(MeasurementToolFragment.TAG)
- .commitAllowingStateLoss();
+ MeasurementToolFragment.showInstance(mapActivity.getSupportFragmentManager(), null);
return true;
}
}).createItem());
diff --git a/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java b/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java
index 3c27ce8e25..66d8822c71 100644
--- a/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java
@@ -13,19 +13,27 @@ 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.TrkSegment;
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.measurementtool.NewGpxData;
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.NewGpxPoint;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import java.io.File;
@@ -37,8 +45,10 @@ public class TrackActivity extends TabActivity {
public static final String TRACK_FILE_NAME = "TRACK_FILE_NAME";
public static final String OPEN_POINTS_TAB = "OPEN_POINTS_TAB";
+ public static final String OPEN_TRACKS_LIST = "OPEN_TRACKS_LIST";
public static final String CURRENT_RECORDING = "CURRENT_RECORDING";
protected List> fragList = new ArrayList<>();
+ private OsmandApplication app;
protected PagerSlidingTabStrip slidingTabLayout;
private File file = null;
private GPXFile gpxFile;
@@ -48,7 +58,8 @@ public class TrackActivity extends TabActivity {
private List displayGroups;
private List originalGroups = new ArrayList<>();
private boolean stopped = false;
- public boolean openPointsTab = false;
+ private boolean openPointsTab = false;
+ private boolean openTracksList = false;
public PagerSlidingTabStrip getSlidingTabLayout() {
return slidingTabLayout;
@@ -56,7 +67,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) &&
@@ -80,9 +92,109 @@ public class TrackActivity extends TabActivity {
if (intent.hasExtra(OPEN_POINTS_TAB)) {
openPointsTab = true;
}
+ if (intent.hasExtra(OPEN_TRACKS_LIST)) {
+ openTracksList = true;
+ }
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();
+ QuadRect rect = getRect();
+ NewGpxPoint newGpxPoint = new NewGpxPoint(gpx, pointDescription, rect);
+ if (gpx != null && location != null) {
+ settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
+ settings.getLastKnownMapZoom(),
+ pointDescription,
+ false,
+ newGpxPoint);
+
+ MapActivity.launchMapActivityMoveToTop(this);
+ }
+ }
+
+ public void addNewGpxData(NewGpxData.ActionType actionType) {
+ addNewGpxData(actionType, null);
+ }
+
+ public void addNewGpxData(NewGpxData.ActionType actionType, TrkSegment segment) {
+ GPXFile gpxFile = getGpx();
+ QuadRect rect = getRect();
+ NewGpxData newGpxData = new NewGpxData(gpxFile, rect, actionType, segment);
+ 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,
+ newGpxData
+ );
+
+ 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;
}
@@ -253,7 +365,7 @@ public class TrackActivity extends TabActivity {
return true;
}
}
- if (getIntent().hasExtra(MapActivity.INTENT_KEY_PARENT_MAP_ACTIVITY)) {
+ if (getIntent().hasExtra(MapActivity.INTENT_KEY_PARENT_MAP_ACTIVITY) || openTracksList) {
OsmAndAppCustomization appCustomization = getMyApplication().getAppCustomization();
final Intent favorites = new Intent(this, appCustomization.getFavoritesActivity());
getMyApplication().getSettings().FAVORITES_TAB.set(FavoritesActivity.GPX_TAB);
@@ -286,6 +398,13 @@ public class TrackActivity extends TabActivity {
return;
}
}
+ if (openTracksList) {
+ OsmAndAppCustomization appCustomization = getMyApplication().getAppCustomization();
+ final Intent favorites = new Intent(this, appCustomization.getFavoritesActivity());
+ getMyApplication().getSettings().FAVORITES_TAB.set(FavoritesActivity.GPX_TAB);
+ favorites.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+ startActivity(favorites);
+ }
super.onBackPressed();
}
diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java
index 26c75ebd4b..1cae32b6bc 100644
--- a/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java
+++ b/OsmAnd/src/net/osmand/plus/helpers/GpxImportHelper.java
@@ -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() {
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() {
ProgressDialog progress = null;
@@ -209,7 +225,7 @@ public class GpxImportHelper {
@Override
protected GPXFile doInBackground(Void... nothing) {
- final List favourites = asFavourites(gpxFile.points);
+ final List 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 asFavourites(final List wptPts) {
+ private List asFavourites(final List wptPts, String fileName, boolean forceImportFavourites) {
final List 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);
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/dialogs/ContextMenuCardDialog.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/dialogs/ContextMenuCardDialog.java
index 29fc6b6395..1474b371d7 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/dialogs/ContextMenuCardDialog.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/dialogs/ContextMenuCardDialog.java
@@ -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);
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java
index 15f9925d72..0c532d421d 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragment.java
@@ -118,7 +118,7 @@ public abstract class PointEditorFragment extends Fragment {
public boolean onTouch(final View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
DialogFragment dialogFragment =
- SelectCategoryDialogFragment.createInstance(getEditor().getFragmentTag());
+ createSelectCategoryDialog();
dialogFragment.show(getChildFragmentManager(), SelectCategoryDialogFragment.TAG);
return true;
}
@@ -176,6 +176,10 @@ public abstract class PointEditorFragment extends Fragment {
return view;
}
+ protected DialogFragment createSelectCategoryDialog() {
+ return SelectCategoryDialogFragment.createInstance(getEditor().getFragmentTag());
+ }
+
public Drawable getRowIcon(int iconId) {
IconsCache iconsCache = getMyApplication().getIconsCache();
return iconsCache.getIcon(iconId,
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/RtePtEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/RtePtEditorFragment.java
index 250faf4d24..97ead03fae 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/RtePtEditorFragment.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/RtePtEditorFragment.java
@@ -1,5 +1,7 @@
package net.osmand.plus.mapcontextmenu.editors;
+import android.support.v4.app.DialogFragment;
+
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
@@ -16,6 +18,11 @@ public class RtePtEditorFragment extends WptPtEditorFragment {
return getMapActivity().getResources().getString(R.string.save_route_point);
}
+ @Override
+ protected DialogFragment createSelectCategoryDialog() {
+ return SelectCategoryDialogFragment.createInstance(getEditor().getFragmentTag());
+ }
+
public static void showInstance(final MapActivity mapActivity) {
RtePtEditor editor = mapActivity.getContextMenu().getRtePtPointEditor();
//int slideInAnim = editor.getSlideInAnimation();
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/SelectCategoryDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/SelectCategoryDialogFragment.java
index 6a0587cfd2..87ed37f512 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/SelectCategoryDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/SelectCategoryDialogFragment.java
@@ -15,6 +15,7 @@ import android.widget.Button;
import android.widget.LinearLayout;
import net.osmand.plus.FavouritesDbHelper;
+import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.IconsCache;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@@ -40,6 +41,15 @@ public class SelectCategoryDialogFragment extends DialogFragment {
private String editorTag;
private CategorySelectionListener selectionListener;
+ private GPXFile gpxFile;
+
+ public void setGpxFile(GPXFile gpxFile) {
+ this.gpxFile = gpxFile;
+ }
+
+ public GPXFile getGpxFile() {
+ return gpxFile;
+ }
@NonNull
@Override
@@ -58,36 +68,16 @@ public class SelectCategoryDialogFragment extends DialogFragment {
LinearLayout ll = (LinearLayout) v.findViewById(R.id.list_container);
final FavouritesDbHelper helper = ((OsmandApplication) getActivity().getApplication()).getFavorites();
- List gs = helper.getFavoriteGroups();
- for (final FavouritesDbHelper.FavoriteGroup category : gs) {
- View itemView = getActivity().getLayoutInflater().inflate(R.layout.favorite_category_dialog_item, null);
- Button button = (Button)itemView.findViewById(R.id.button);
- if (category.color != 0) {
- button.setCompoundDrawablesWithIntrinsicBounds(getIcon(getActivity(), R.drawable.ic_action_folder, category.color), null, null, null);
- } else {
- button.setCompoundDrawablesWithIntrinsicBounds(getIcon(getActivity(), R.drawable.ic_action_folder, getResources().getColor(R.color.color_favorite)), null, null, null);
+ if (gpxFile != null) {
+ List categories = gpxFile.getWaypointCategories();
+ for (final String category : categories) {
+ addCategory(ll, category, 0);
+ }
+ } else {
+ List gs = helper.getFavoriteGroups();
+ for (final FavouritesDbHelper.FavoriteGroup category : gs) {
+ addCategory(ll, category.name, category.color);
}
- button.setCompoundDrawablePadding(dpToPx(15f));
- String name = category.name.length() == 0 ? getString(R.string.shared_string_favorites) : category.name;
- button.setText(name);
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-
- PointEditor editor = ((MapActivity) getActivity()).getContextMenu().getPointEditor(editorTag);
-
- if (editor != null) {
- editor.setCategory(category.name);
- }
-
- if (selectionListener != null) {
- selectionListener.onCategorySelected(category.name, category.color);
- }
-
- dismiss();
- }
- });
- ll.addView(itemView);
}
View itemView = getActivity().getLayoutInflater().inflate(R.layout.favorite_category_dialog_item, null);
Button button = (Button)itemView.findViewById(R.id.button);
@@ -111,6 +101,40 @@ public class SelectCategoryDialogFragment extends DialogFragment {
return builder.create();
}
+ private void addCategory(LinearLayout ll, final String categoryName, final int categoryColor) {
+ View itemView = getActivity().getLayoutInflater().inflate(R.layout.favorite_category_dialog_item, null);
+ Button button = (Button)itemView.findViewById(R.id.button);
+ if (categoryColor != 0) {
+ button.setCompoundDrawablesWithIntrinsicBounds(getIcon(getActivity(), R.drawable.ic_action_folder, categoryColor), null, null, null);
+ } else {
+ button.setCompoundDrawablesWithIntrinsicBounds(getIcon(getActivity(), R.drawable.ic_action_folder, getResources().getColor(R.color.color_favorite)), null, null, null);
+ }
+ button.setCompoundDrawablePadding(dpToPx(15f));
+ String name = categoryName.length() == 0 ? getString(R.string.shared_string_favorites) : categoryName;
+ button.setText(name);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ PointEditor editor = ((MapActivity) getActivity()).getContextMenu().getPointEditor(editorTag);
+
+ if (editor != null) {
+ editor.setCategory(categoryName);
+ if (gpxFile != null && editor instanceof WptPtEditor) {
+ ((WptPtEditor) editor).getWptPt().category = categoryName;
+ }
+ }
+
+ if (selectionListener != null) {
+ selectionListener.onCategorySelected(categoryName, categoryColor);
+ }
+
+ dismiss();
+ }
+ });
+ ll.addView(itemView);
+ }
+
public static SelectCategoryDialogFragment createInstance(String editorTag) {
SelectCategoryDialogFragment fragment = new SelectCategoryDialogFragment();
Bundle bundle = new Bundle();
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java
index 9bc3edb6b7..770213aa8f 100644
--- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java
+++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragment.java
@@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
+import android.support.v4.app.DialogFragment;
import android.view.View;
import net.osmand.data.LatLon;
@@ -47,6 +48,16 @@ public class WptPtEditorFragment extends PointEditorFragment {
defaultColor = getResources().getColor(R.color.gpx_color_point);
}
+ @Override
+ protected DialogFragment createSelectCategoryDialog() {
+ SelectCategoryDialogFragment selectCategoryDialogFragment = SelectCategoryDialogFragment.createInstance(getEditor().getFragmentTag());
+ GPXFile gpx = editor.getGpxFile();
+ if (gpx != null) {
+ selectCategoryDialogFragment.setGpxFile(gpx);
+ }
+ return selectCategoryDialogFragment;
+ }
+
protected void assignEditor() {
editor = getMapActivity().getContextMenu().getWptPtPointEditor();
}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurePointsListFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurePointsListFragment.java
new file mode 100644
index 0000000000..9cc331bf13
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurePointsListFragment.java
@@ -0,0 +1,86 @@
+package net.osmand.plus.measurementtool;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout.LayoutParams;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.R;
+import net.osmand.plus.activities.MapActivity;
+
+public class MeasurePointsListFragment extends Fragment {
+
+ public static final String TAG = "MeasurePointsListFragment";
+
+ private RecyclerView rv;
+ private int height;
+ private int width;
+ private FrameLayout parent;
+ private FrameLayout mainView;
+
+ public void setRecyclerView(RecyclerView rv) {
+ this.rv = rv;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ final MapActivity mapActivity = (MapActivity) getActivity();
+ if (rv == null) {
+ return null;
+ }
+ final boolean nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ final int backgroundColor = ContextCompat.getColor(getActivity(),
+ nightMode ? R.color.ctx_menu_info_view_bg_dark : R.color.ctx_menu_info_view_bg_light);
+ final TypedValue typedValueAttr = new TypedValue();
+ getActivity().getTheme().resolveAttribute(R.attr.left_menu_view_bg, typedValueAttr, true);
+
+ parent = new FrameLayout(mapActivity);
+ parent.setLayoutParams(new LayoutParams(width + AndroidUtils.dpToPx(getActivity(), 16), height));
+ parent.setBackgroundResource(typedValueAttr.resourceId);
+
+ mainView = new FrameLayout(mapActivity);
+ mainView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ mainView.setBackgroundColor(backgroundColor);
+
+ ImageView shadow = new ImageView(mapActivity);
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.gravity = Gravity.BOTTOM;
+ shadow.setLayoutParams(params);
+ shadow.setScaleType(ImageView.ScaleType.FIT_XY);
+ shadow.setImageResource(R.drawable.bg_shadow_onmap);
+
+ mainView.addView(rv);
+ mainView.addView(shadow);
+ parent.addView(mainView);
+
+ return parent;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (parent != null && mainView != null) {
+ parent.removeAllViews();
+ mainView.removeAllViews();
+ }
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
index 1e1375926e..dfb3878c7f 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
@@ -2,129 +2,345 @@ 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;
+import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
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;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.AndroidUtils;
+import net.osmand.CallbackWithObject;
import net.osmand.IndexConstants;
+import net.osmand.Location;
+import net.osmand.data.LatLon;
+import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GPXUtilities;
+import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.Route;
+import net.osmand.plus.GPXUtilities.Track;
+import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.IconsCache;
+import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.plus.helpers.GpxUiHelper;
+import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
+import net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener;
+import net.osmand.plus.measurementtool.SelectedPointBottomSheetDialogFragment.SelectedPointFragmentListener;
+import net.osmand.plus.measurementtool.SnapToRoadBottomSheetDialogFragment.SnapToRoadFragmentListener;
+import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter;
+import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter.MeasurementAdapterListener;
+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.MeasurementCommandManager;
+import net.osmand.plus.measurementtool.command.MeasurementModeCommand.MeasurementCommandType;
+import net.osmand.plus.measurementtool.command.MovePointCommand;
+import net.osmand.plus.measurementtool.command.RemovePointCommand;
+import net.osmand.plus.measurementtool.command.ReorderPointCommand;
+import net.osmand.plus.measurementtool.command.SnapToRoadCommand;
+import net.osmand.plus.routing.RouteProvider.SnapToRoadParams;
+import net.osmand.plus.routing.RoutingHelper;
+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.router.RouteCalculationProgress;
import java.io.File;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
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.LANDSCAPE_MIDDLE_RIGHT_CONSTANT;
+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 MeasurementCommandManager commandManager = new MeasurementCommandManager();
+ private List measurementPoints = new LinkedList<>();
+ private List snappedToRoadPoints = new LinkedList<>();
+ private IconsCache iconsCache;
+ private RecyclerView pointsRv;
+ private String previousToolBarTitle = "";
private MeasurementToolBarController toolBarController;
+ private MeasurementToolAdapter adapter;
private TextView distanceTv;
private TextView pointsTv;
+ private TextView distanceToCenterTv;
private String pointsSt;
+ private Drawable upIcon;
+ private Drawable downIcon;
+ private View pointsListContainer;
+ private View upDownRow;
+ private View mainView;
+ private ImageView upDownBtn;
+ private ImageView undoBtn;
+ private ImageView redoBtn;
+ private ImageView mainIcon;
+ private ProgressBar snapToRoadProgressBar;
+ private RouteCalculationProgress calculationProgress;
private boolean wasCollapseButtonVisible;
- private boolean pointsDetailsOpened;
+ private boolean pointsListOpened;
+ private Boolean saved;
+ private boolean portrait;
+ private boolean nightMode;
+ private int previousMapPosition;
+ private NewGpxData newGpxData;
+ private boolean gpxPointsAdded;
+ private ApplicationMode snapToRoadAppMode;
+
+ private boolean inMovePointMode;
+ private boolean inAddPointAfterMode;
+ private boolean inAddPointBeforeMode;
+ private boolean isInSnapToRoadMode;
+
+ private int selectedPointPos = -1;
+ private WptPt selectedCachedPoint;
+
+ private int positionToAddPoint = -1;
+
+ private enum SaveType {
+ ROUTE_POINT,
+ LINE
+ }
+
+ public void setNewGpxData(NewGpxData newGpxData) {
+ this.newGpxData = newGpxData;
+ }
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final MapActivity mapActivity = (MapActivity) getActivity();
final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
- final IconsCache iconsCache = mapActivity.getMyApplication().getIconsCache();
- final boolean nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
+
+ measurementLayer.setMeasurementPoints(measurementPoints);
+ measurementLayer.setSnappedToRoadPoints(snappedToRoadPoints);
+ if (selectedPointPos != -1 && selectedCachedPoint != null) {
+ measurementLayer.setSelectedPointPos(selectedPointPos);
+ measurementLayer.setSelectedCachedPoint(selectedCachedPoint);
+ }
+
+ // Handling screen rotation
+ FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
+ Fragment selectedPointFragment = fragmentManager.findFragmentByTag(SelectedPointBottomSheetDialogFragment.TAG);
+ if (selectedPointFragment != null) {
+ SelectedPointBottomSheetDialogFragment fragment = (SelectedPointBottomSheetDialogFragment) selectedPointFragment;
+ fragment.setActionType(newGpxData != null ? newGpxData.getActionType() : null);
+ fragment.setListener(createSelectedPointFragmentListener());
+ }
+ Fragment optionsFragment = fragmentManager.findFragmentByTag(OptionsBottomSheetDialogFragment.TAG);
+ if (optionsFragment != null) {
+ ((OptionsBottomSheetDialogFragment) optionsFragment).setListener(createOptionsFragmentListener());
+ }
+ Fragment snapToRoadFragment = fragmentManager.findFragmentByTag(SnapToRoadBottomSheetDialogFragment.TAG);
+ if (snapToRoadFragment != null) {
+ ((SnapToRoadBottomSheetDialogFragment) snapToRoadFragment).setListener(createSnapToRoadFragmentListener());
+ }
+ Fragment saveAsNewTrackFragment = mapActivity.getSupportFragmentManager().findFragmentByTag(SaveAsNewTrackBottomSheetDialogFragment.TAG);
+ if (saveAsNewTrackFragment != null) {
+ ((SaveAsNewTrackBottomSheetDialogFragment) saveAsNewTrackFragment).setListener(createSaveAsNewTrackFragmentListener());
+ }
+ // If rotate the screen from landscape to portrait when the list of points is displayed then
+ // the PointsListFragment will exist without view. This is necessary to remove it.
+ if (portrait) {
+ hidePointsListFragment();
+ }
+
+ commandManager.resetMeasurementLayer(measurementLayer);
+ iconsCache = mapActivity.getMyApplication().getIconsCache();
+ nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
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);
+ portrait = AndroidUiHelper.isOrientationPortrait(getActivity());
+ upIcon = getContentIcon(R.drawable.ic_action_arrow_up);
+ downIcon = getContentIcon(R.drawable.ic_action_arrow_down);
pointsSt = getString(R.string.points).toLowerCase();
View view = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_measurement_tool, null);
- final View mainView = view.findViewById(R.id.main_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);
+ if (portrait && pointsListContainer != null) {
+ pointsListContainer.setBackgroundColor(backgroundColor);
+ }
distanceTv = (TextView) mainView.findViewById(R.id.measurement_distance_text_view);
pointsTv = (TextView) mainView.findViewById(R.id.measurement_points_text_view);
+ distanceToCenterTv = (TextView) mainView.findViewById(R.id.distance_to_center_text_view);
- ((ImageView) mainView.findViewById(R.id.ruler_icon))
- .setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_ruler, R.color.color_myloc_distance));
+ mainIcon = (ImageView) mainView.findViewById(R.id.main_icon);
+ if (newGpxData != null) {
+ NewGpxData.ActionType actionType = newGpxData.getActionType();
+ if (actionType == NewGpxData.ActionType.ADD_SEGMENT || actionType == NewGpxData.ActionType.EDIT_SEGMENT) {
+ mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_polygom_dark));
+ } else {
+ mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_markers_dark));
+ }
+ } else {
+ mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
+ }
- final ImageButton upDownBtn = ((ImageButton) mainView.findViewById(R.id.up_down_button));
- upDownBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up));
- upDownBtn.setOnClickListener(new View.OnClickListener() {
+ upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
+ upDownBtn.setImageDrawable(upIcon);
+
+ mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if (!pointsDetailsOpened) {
- upBtnOnClick(mainView, iconsCache.getThemedIcon(R.drawable.ic_action_arrow_down));
- } else {
- downBtnOnClick(mainView, iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up));
+ if (inMovePointMode) {
+ cancelMovePointMode();
}
}
});
- final ImageButton undoBtn = ((ImageButton) mainView.findViewById(R.id.undo_point_button));
- final ImageButton redoBtn = ((ImageButton) mainView.findViewById(R.id.redo_point_button));
+ mainView.findViewById(R.id.cancel_point_before_after_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (inAddPointAfterMode) {
+ cancelAddPointAfterMode();
+ } else if (inAddPointBeforeMode) {
+ cancelAddPointBeforeMode();
+ }
+ }
+ });
- undoBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_undo_dark));
+ upDownRow = mainView.findViewById(R.id.up_down_row);
+ upDownRow.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (!pointsListOpened
+ && measurementPoints.size() > 0
+ && !measurementLayer.isInMovePointMode()
+ && !measurementLayer.isInAddPointAfterMode()
+ && !measurementLayer.isInAddPointBeforeMode()) {
+ showPointsList();
+ } else {
+ hidePointsList();
+ }
+ }
+ });
+
+ mainView.findViewById(R.id.apply_move_point_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (inMovePointMode) {
+ applyMovePointMode();
+ }
+ }
+ });
+
+ mainView.findViewById(R.id.apply_point_before_after_point_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (inAddPointAfterMode) {
+ applyAddPointAfterMode();
+ } else if (inAddPointBeforeMode) {
+ applyAddPointBeforeMode();
+ }
+ }
+ });
+
+ mainView.findViewById(R.id.add_point_before_after_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (inAddPointAfterMode) {
+ addPointAfter();
+ } else if (inAddPointBeforeMode) {
+ addPointBefore();
+ }
+ }
+ });
+
+ mainView.findViewById(R.id.options_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ OptionsBottomSheetDialogFragment fragment = new OptionsBottomSheetDialogFragment();
+ fragment.setSnapToRoadEnabled(isInSnapToRoadMode);
+ fragment.setListener(createOptionsFragmentListener());
+ fragment.setAddLineMode(newGpxData != null);
+ fragment.show(mapActivity.getSupportFragmentManager(), OptionsBottomSheetDialogFragment.TAG);
+ }
+ });
+
+ undoBtn = ((ImageButton) mainView.findViewById(R.id.undo_point_button));
+ redoBtn = ((ImageButton) mainView.findViewById(R.id.redo_point_button));
+
+ undoBtn.setImageDrawable(getContentIcon(R.drawable.ic_action_undo_dark));
undoBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if (measurementLayer.undoPointOnClick()) {
+ MeasurementCommandType type = commandManager.undo();
+ if (type != null && type != MeasurementCommandType.SNAP_TO_ROAD) {
+ recalculateSnapToRoadIfNedeed();
+ }
+ if (commandManager.canUndo()) {
enable(undoBtn);
} else {
disable(undoBtn);
}
+ hidePointsListIfNoPoints();
+ if (measurementPoints.size() > 0) {
+ enable(upDownBtn);
+ }
+ adapter.notifyDataSetChanged();
enable(redoBtn);
updateText();
}
});
- redoBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_redo_dark));
+ redoBtn.setImageDrawable(getContentIcon(R.drawable.ic_action_redo_dark));
redoBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if (measurementLayer.redoPointOnClick()) {
+ commandManager.redo();
+ recalculateSnapToRoadIfNedeed();
+ if (commandManager.canRedo()) {
enable(redoBtn);
} else {
disable(redoBtn);
}
+ hidePointsListIfNoPoints();
+ if (measurementPoints.size() > 0) {
+ enable(upDownBtn);
+ }
+ adapter.notifyDataSetChanged();
enable(undoBtn);
updateText();
}
@@ -133,143 +349,987 @@ public class MeasurementToolFragment extends Fragment {
mainView.findViewById(R.id.add_point_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- measurementLayer.addPointOnClick();
- enable(undoBtn, upDownBtn);
- disable(redoBtn);
- updateText();
+ addCenterPoint();
}
});
- disable(undoBtn, redoBtn, upDownBtn);
+ measurementLayer.setOnSingleTapListener(new MeasurementToolLayer.OnSingleTapListener() {
+ @Override
+ public void onAddPoint() {
+ addPoint();
+ }
+
+ @Override
+ public void onSelectPoint(int selectedPointPos, WptPt selectedCachedPoint) {
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ MeasurementToolFragment.this.selectedPointPos = selectedPointPos;
+ MeasurementToolFragment.this.selectedCachedPoint = selectedCachedPoint;
+ if (selectedPointPos != -1 && selectedCachedPoint != null) {
+ openSelectedPointMenu(mapActivity);
+ }
+ }
+ });
+
+ measurementLayer.setOnMeasureDistanceToCenterListener(new MeasurementToolLayer.OnMeasureDistanceToCenter() {
+ @Override
+ public void onMeasure(float distance) {
+ String distStr = OsmAndFormatter.getFormattedDistance(distance, mapActivity.getMyApplication());
+ distanceToCenterTv.setText(" – " + distStr);
+ }
+ });
+
+ measurementLayer.setOnEnterMovePointModeListener(new MeasurementToolLayer.OnEnterMovePointModeListener() {
+ @Override
+ public void onEnterMovePointMode() {
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ switchMovePointMode(true);
+ }
+ });
+
+ if (!commandManager.canUndo()) {
+ disable(undoBtn);
+ }
+ if (!commandManager.canRedo()) {
+ disable(redoBtn);
+ }
+ if (measurementPoints.size() < 1) {
+ disable(upDownBtn);
+ }
+
+ toolBarController = new MeasurementToolBarController(newGpxData);
+ if (inMovePointMode || inAddPointAfterMode || inAddPointBeforeMode) {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_mode_back, R.drawable.ic_action_mode_back);
+ } else {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_remove_dark, R.drawable.ic_action_remove_dark);
+ }
+ if (newGpxData != null) {
+ NewGpxData.ActionType actionType = newGpxData.getActionType();
+ if (actionType == NewGpxData.ActionType.ADD_ROUTE_POINTS) {
+ toolBarController.setTitle(getString(R.string.add_route_points));
+ } else if (actionType == NewGpxData.ActionType.ADD_SEGMENT) {
+ toolBarController.setTitle(getString(R.string.add_line));
+ } else if (actionType == NewGpxData.ActionType.EDIT_SEGMENT) {
+ toolBarController.setTitle(getString(R.string.edit_line));
+ }
+ } else {
+ toolBarController.setTitle(getString(R.string.measurement_tool_action_bar));
+ }
+ toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ quit(false);
+ }
+ });
+ toolBarController.setOnSaveViewClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (measurementPoints.size() > 0) {
+ addToGpx(mapActivity);
+ } else {
+ Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ toolBarController.setOnSwitchCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ if (!checked) {
+ disableSnapToRoadMode();
+ }
+ }
+ });
+ mapActivity.showTopToolbar(toolBarController);
+
+ adapter = new MeasurementToolAdapter(getMapActivity(), measurementLayer.getMeasurementPoints(),
+ newGpxData != null ? newGpxData.getActionType() : null);
+ if (portrait) {
+ pointsRv = mainView.findViewById(R.id.measure_points_recycler_view);
+ } else {
+ pointsRv = new RecyclerView(getActivity());
+ }
+ final ItemTouchHelper touchHelper = new ItemTouchHelper(new MeasurementToolItemTouchHelperCallback(adapter));
+ touchHelper.attachToRecyclerView(pointsRv);
+ adapter.setAdapterListener(createMeasurementAdapterListener(touchHelper));
+ pointsRv.setLayoutManager(new LinearLayoutManager(getContext()));
+ pointsRv.setAdapter(adapter);
enterMeasurementMode();
- if (portrait) {
- toolBarController = new MeasurementToolBarController();
- toolBarController.setTitle(getString(R.string.measurement_tool_action_bar));
- toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showQuitDialog();
- }
- });
- toolBarController.setOnCloseButtonClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- IconPopupMenu popup = new IconPopupMenu(mapActivity, mapActivity.findViewById(R.id.widget_top_bar_close_button));
- 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));
- 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_gpx:
- if (measurementLayer.getPointsCount() > 0) {
- saveAsGpxOnClick(mapActivity);
- } else {
- Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
- }
- return true;
- case R.id.action_clear_all:
- measurementLayer.clearPoints();
- disable(undoBtn, redoBtn, upDownBtn);
- updateText();
- return true;
- }
- return false;
- }
- });
- popup.show();
- }
- });
- mapActivity.showTopToolbar(toolBarController);
+ if (isInSnapToRoadMode) {
+ enableSnapToRoadMode(true);
+ }
+
+ if (newGpxData != null && !gpxPointsAdded) {
+ NewGpxData.ActionType actionType = newGpxData.getActionType();
+ if (actionType == NewGpxData.ActionType.ADD_ROUTE_POINTS) {
+ displayRoutePoints();
+ gpxPointsAdded = true;
+ } else if (actionType == NewGpxData.ActionType.EDIT_SEGMENT) {
+ displaySegmentPoints();
+ gpxPointsAdded = true;
+ }
+ }
+
+ if (saved == null) {
+ saved = newGpxData != null && (newGpxData.getActionType() == NewGpxData.ActionType.ADD_ROUTE_POINTS || newGpxData.getActionType() == NewGpxData.ActionType.EDIT_SEGMENT);
}
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 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 saveAsGpxOnClick(MapActivity mapActivity) {
- final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
- final LayoutInflater inflater = mapActivity.getLayoutInflater();
- final View view = inflater.inflate(R.layout.save_gpx_dialog, null);
- final EditText nameEt = (EditText) view.findViewById(R.id.gpx_name_et);
- final TextView fileExistsTv = (TextView) view.findViewById(R.id.file_exists_text_view);
- final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
- showOnMapToggle.setChecked(true);
-
- final String suggestedName = new SimpleDateFormat("yyyy-M-dd_HH-mm_EEE", Locale.US).format(new Date());
- String displayedName = suggestedName;
- File fout = new File(dir, suggestedName + GPX_SUFFIX);
- int ind = 1;
- while (fout.exists()) {
- displayedName = suggestedName + "_" + (++ind);
- fout = new File(dir, displayedName + GPX_SUFFIX);
+ private void recalculateSnapToRoadIfNedeed() {
+ if (calculationProgress != null) {
+ calculationProgress.isCancelled = true;
+ }
+ if (isInSnapToRoadMode) {
+ doSnapToRoad();
}
- nameEt.setText(displayedName);
- nameEt.setSelection(displayedName.length());
-
- final boolean[] textChanged = new boolean[1];
- nameEt.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- if (new File(dir, editable.toString() + GPX_SUFFIX).exists()) {
- fileExistsTv.setVisibility(View.VISIBLE);
- } else {
- fileExistsTv.setVisibility(View.INVISIBLE);
- }
- textChanged[0] = true;
- }
- });
-
- new AlertDialog.Builder(mapActivity)
- .setTitle(R.string.enter_gpx_name)
- .setView(view)
- .setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final String name = nameEt.getText().toString();
- String fileName = name + GPX_SUFFIX;
- if (textChanged[0]) {
- File fout = new File(dir, fileName);
- int ind = 1;
- while (fout.exists()) {
- fileName = name + "_" + (++ind) + GPX_SUFFIX;
- fout = new File(dir, fileName);
- }
- }
- saveGpx(dir, fileName, showOnMapToggle.isChecked());
- }
- })
- .setNegativeButton(R.string.shared_string_cancel, null)
- .show();
}
- private void saveGpx(final File dir, final String fileName, final boolean showOnMap) {
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ exitMeasurementMode();
+ adapter.setAdapterListener(null);
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ if (inMovePointMode) {
+ switchMovePointMode(false);
+ }
+ if (inAddPointAfterMode) {
+ switchAddPointAfterMode(false);
+ }
+ if (inAddPointBeforeMode) {
+ switchAddPointBeforeMode(false);
+ }
+ MeasurementToolLayer layer = getMeasurementLayer();
+ if (layer != null) {
+ layer.exitMovePointMode();
+ layer.exitAddPointAfterMode();
+ layer.exitAddPointBeforeMode();
+ layer.setOnSingleTapListener(null);
+ layer.setOnEnterMovePointModeListener(null);
+ }
+ }
+
+ private MapActivity getMapActivity() {
+ return (MapActivity) getActivity();
+ }
+
+ private MeasurementToolLayer getMeasurementLayer() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ return mapActivity.getMapLayers().getMeasurementToolLayer();
+ }
+ return null;
+ }
+
+ private Drawable getContentIcon(@DrawableRes int id) {
+ return iconsCache.getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.icon_color);
+ }
+
+ private Drawable getActiveIcon(@DrawableRes int id) {
+ return iconsCache.getIcon(id, nightMode ? R.color.osmand_orange : R.color.color_myloc_distance);
+ }
+
+ private void showSnapToRoadMenu(boolean rememberPreviousTitle) {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ if (rememberPreviousTitle) {
+ previousToolBarTitle = toolBarController.getTitle();
+ }
+ toolBarController.setTitle(getString(R.string.snap_to_road));
+ mapActivity.refreshMap();
+ SnapToRoadBottomSheetDialogFragment fragment = new SnapToRoadBottomSheetDialogFragment();
+ fragment.setListener(createSnapToRoadFragmentListener());
+ fragment.show(mapActivity.getSupportFragmentManager(), SnapToRoadBottomSheetDialogFragment.TAG);
+ }
+ }
+
+ private OptionsFragmentListener createOptionsFragmentListener() {
+ return new OptionsFragmentListener() {
+
+ final MapActivity mapActivity = getMapActivity();
+ final MeasurementToolLayer measurementLayer = getMeasurementLayer();
+
+ @Override
+ public void snapToRoadOnCLick() {
+ if (!isInSnapToRoadMode) {
+ showSnapToRoadMenu(true);
+ } else {
+ disableSnapToRoadMode();
+ }
+ }
+
+ @Override
+ public void addToGpxOnClick() {
+ if (mapActivity != null && measurementLayer != null) {
+ if (measurementPoints.size() > 0) {
+ addToGpx(mapActivity);
+ } else {
+ Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ @Override
+ public void saveAsNewTrackOnClick() {
+ if (mapActivity != null && measurementLayer != null) {
+ if (measurementPoints.size() > 0) {
+ openSaveAsNewTrackMenu(mapActivity);
+ } else {
+ Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ @Override
+ public void addToTheTrackOnClick() {
+ if (mapActivity != null && measurementLayer != null) {
+ if (measurementPoints.size() > 0) {
+ showAddToTrackDialog(mapActivity);
+ } else {
+ Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ @Override
+ public void clearAllOnClick() {
+ commandManager.execute(new ClearPointsCommand(measurementLayer));
+ if (calculationProgress != null) {
+ calculationProgress.isCancelled = true;
+ }
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ disable(redoBtn, upDownBtn);
+ updateText();
+ saved = false;
+ }
+ };
+ }
+
+ private SelectedPointFragmentListener createSelectedPointFragmentListener() {
+ return new SelectedPointFragmentListener() {
+
+ final MeasurementToolLayer measurementLayer = getMeasurementLayer();
+
+ @Override
+ public void moveOnClick() {
+ if (measurementLayer != null) {
+ measurementLayer.enterMovingPointMode();
+ }
+ switchMovePointMode(true);
+ }
+
+ @Override
+ public void deleteOnClick() {
+ clearSelection();
+ if (measurementLayer != null) {
+ removePoint(measurementLayer, measurementLayer.getSelectedPointPos());
+ measurementLayer.clearSelection();
+ }
+ }
+
+ @Override
+ public void addPointAfterOnClick() {
+ if (measurementLayer != null) {
+ positionToAddPoint = measurementLayer.getSelectedPointPos() + 1;
+ measurementLayer.enterAddingPointAfterMode();
+ }
+ switchAddPointAfterMode(true);
+ }
+
+ @Override
+ public void addPointBeforeOnClick() {
+ if (measurementLayer != null) {
+ positionToAddPoint = measurementLayer.getSelectedPointPos();
+ measurementLayer.enterAddingPointBeforeMode();
+ }
+ switchAddPointBeforeMode(true);
+ }
+
+ @Override
+ public void onCloseMenu() {
+ setPreviousMapPosition();
+ }
+ };
+ }
+
+ private SnapToRoadFragmentListener createSnapToRoadFragmentListener() {
+ return new SnapToRoadFragmentListener() {
+ @Override
+ public void onDestroyView(boolean snapToRoadEnabled) {
+ if (!snapToRoadEnabled) {
+ toolBarController.setTitle(previousToolBarTitle);
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.refreshMap();
+ }
+ }
+ }
+
+ @Override
+ public void onApplicationModeItemClick(ApplicationMode mode) {
+ snapToRoadAppMode = mode;
+ enableSnapToRoadMode(false);
+ }
+ };
+ }
+
+ private void removePoint(MeasurementToolLayer layer, int position) {
+ commandManager.execute(new RemovePointCommand(layer, position));
+ recalculateSnapToRoadIfNedeed();
+ adapter.notifyDataSetChanged();
+ disable(redoBtn);
+ updateText();
+ saved = false;
+ hidePointsListIfNoPoints();
+ }
+
+ private SaveAsNewTrackFragmentListener createSaveAsNewTrackFragmentListener() {
+ return new SaveAsNewTrackFragmentListener() {
+ @Override
+ public void saveAsRoutePointOnClick() {
+ saveAsGpx(SaveType.ROUTE_POINT);
+ }
+
+ @Override
+ public void saveAsLineOnClick() {
+ saveAsGpx(SaveType.LINE);
+ }
+ };
+ }
+
+ private MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) {
+ return new MeasurementAdapterListener() {
+
+ final MapActivity mapActivity = getMapActivity();
+ final MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ private int fromPosition;
+ private int toPosition;
+
+ @Override
+ public void onRemoveClick(int position) {
+ if (measurementLayer != null) {
+ removePoint(measurementLayer, position);
+ }
+ }
+
+ @Override
+ public void onItemClick(View view) {
+ if (mapActivity != null && measurementLayer != null) {
+ clearSelection();
+ int position = pointsRv.indexOfChild(view);
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ OsmandMapTileView tileView = mapActivity.getMapView();
+ if (portrait) {
+ previousMapPosition = tileView.getMapPosition();
+ tileView.setMapPosition(MIDDLE_TOP_CONSTANT);
+ }
+ mapActivity.refreshMap();
+ measurementLayer.moveMapToPoint(position);
+ measurementLayer.selectPoint(position);
+ }
+ }
+
+ @Override
+ public void onDragStarted(RecyclerView.ViewHolder holder) {
+ fromPosition = holder.getAdapterPosition();
+ touchHelper.startDrag(holder);
+ }
+
+ @Override
+ public void onDragEnded(RecyclerView.ViewHolder holder) {
+ if (mapActivity != null && measurementLayer != null) {
+ toPosition = holder.getAdapterPosition();
+ if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) {
+ commandManager.execute(new ReorderPointCommand(measurementLayer, fromPosition, toPosition));
+ recalculateSnapToRoadIfNedeed();
+ adapter.notifyDataSetChanged();
+ disable(redoBtn);
+ updateText();
+ mapActivity.refreshMap();
+ saved = false;
+ }
+ }
+ }
+ };
+ }
+
+ private void enableSnapToRoadMode(boolean enableAfterRotating) {
+ if (snapToRoadAppMode != null) {
+ toolBarController.setTopBarSwitchVisible(true);
+ toolBarController.setTopBarSwitchChecked(true);
+ isInSnapToRoadMode = true;
+ mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_snap_to_road));
+ final MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
+ snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
+ snapToRoadBtn.setImageDrawable(getActiveIcon(snapToRoadAppMode.getSmallIconDark()));
+ snapToRoadBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showSnapToRoadMenu(false);
+ }
+ });
+ snapToRoadBtn.setVisibility(View.VISIBLE);
+
+ snapToRoadProgressBar = (ProgressBar) mainView.findViewById(R.id.snap_to_road_progress_bar);
+ snapToRoadProgressBar.setMinimumHeight(0);
+
+ if (!enableAfterRotating) {
+ snapToRoadProgressBar.setProgress(0);
+ doSnapToRoad();
+ }
+
+ mapActivity.refreshMap();
+ }
+ }
+ }
+
+ private void doSnapToRoad() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null && measurementPoints.size() > 1) {
+ Location start = new Location("");
+ WptPt first = measurementPoints.get(0);
+ start.setLatitude(first.getLatitude());
+ start.setLongitude(first.getLongitude());
+
+ WptPt last = measurementPoints.get(measurementPoints.size() - 1);
+ LatLon end = new LatLon(last.getLatitude(), last.getLongitude());
+
+ List intermediates = new ArrayList<>();
+ if (measurementPoints.size() > 2) {
+ for (int i = 1; i < measurementPoints.size() - 1; i++) {
+ WptPt pt = measurementPoints.get(i);
+ intermediates.add(new LatLon(pt.getLatitude(), pt.getLongitude()));
+ }
+ }
+
+ final SnapToRoadParams params = new SnapToRoadParams();
+ params.applicationMode = snapToRoadAppMode;
+ params.calculationProgress = calculationProgress = new RouteCalculationProgress();
+ params.calculationProgressCallback = new RoutingHelper.RouteCalculationProgressCallback() {
+ @Override
+ public void updateProgress(int progress) {
+ snapToRoadProgressBar.setProgress(progress);
+ }
+
+ @Override
+ public void requestPrivateAccessRouting() {
+
+ }
+
+ @Override
+ public void finish() {
+ snapToRoadProgressBar.setVisibility(View.GONE);
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.refreshMap();
+ }
+ }
+ };
+ params.listener = new SnapToRoadParams.SnapToRoadListener() {
+ @Override
+ public void onSnapToRoadDone() {
+ ArrayList pts = new ArrayList<>(params.points.size());
+ for (Location loc : params.points) {
+ WptPt pt = new WptPt();
+ pt.lat = loc.getLatitude();
+ pt.lon = loc.getLongitude();
+ pts.add(pt);
+ }
+ MeasurementToolLayer layer = getMeasurementLayer();
+ if (layer != null) {
+ commandManager.execute(new SnapToRoadCommand(layer, pts));
+ }
+ }
+ };
+ snapToRoadProgressBar.setVisibility(View.VISIBLE);
+
+ mapActivity.getMyApplication().getRoutingHelper().recalculateSnapToRoad(start, end, intermediates, params);
+ } else if (calculationProgress != null) {
+ calculationProgress.isCancelled = true;
+ }
+ }
+
+ private void disableSnapToRoadMode() {
+ toolBarController.setTopBarSwitchVisible(false);
+ toolBarController.setTitle(previousToolBarTitle);
+ isInSnapToRoadMode = false;
+ mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
+ if (calculationProgress != null) {
+ calculationProgress.isCancelled = true;
+ }
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.findViewById(R.id.snap_to_road_image_button).setVisibility(View.GONE);
+ mainView.findViewById(R.id.snap_to_road_progress_bar).setVisibility(View.GONE);
+ mapActivity.refreshMap();
+ }
+ }
+
+ private void displayRoutePoints() {
+ final MeasurementToolLayer measurementLayer = getMeasurementLayer();
+
+ GPXFile gpx = newGpxData.getGpxFile();
+ List points = gpx.getRoutePoints();
+ if (measurementLayer != null) {
+ measurementPoints.addAll(points);
+ adapter.notifyDataSetChanged();
+ updateText();
+ }
+ }
+
+ private void displaySegmentPoints() {
+ final MeasurementToolLayer measurementLayer = getMeasurementLayer();
+
+ TrkSegment segment = newGpxData.getTrkSegment();
+ List points = segment.points;
+ if (measurementLayer != null) {
+ measurementPoints.addAll(points);
+ adapter.notifyDataSetChanged();
+ updateText();
+ }
+ }
+
+ private void openSelectedPointMenu(MapActivity mapActivity) {
+ SelectedPointBottomSheetDialogFragment fragment = new SelectedPointBottomSheetDialogFragment();
+ fragment.setActionType(newGpxData != null ? newGpxData.getActionType() : null);
+ fragment.setListener(createSelectedPointFragmentListener());
+ fragment.show(mapActivity.getSupportFragmentManager(), SelectedPointBottomSheetDialogFragment.TAG);
+ }
+
+ private void openSaveAsNewTrackMenu(MapActivity mapActivity) {
+ SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment();
+ fragment.setListener(createSaveAsNewTrackFragmentListener());
+ fragment.show(mapActivity.getSupportFragmentManager(), SaveAsNewTrackBottomSheetDialogFragment.TAG);
+ }
+
+ private AlertDialog showAddToTrackDialog(final MapActivity mapActivity) {
+ CallbackWithObject callbackWithObject = new CallbackWithObject() {
+ @Override
+ public boolean processResult(GPXFile[] result) {
+ GPXFile gpxFile;
+ if (result != null && result.length > 0) {
+ gpxFile = result[0];
+ SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path);
+ boolean showOnMap = selectedGpxFile != null;
+ saveExistingGpx(gpxFile, showOnMap, null, false);
+ }
+ return true;
+ }
+ };
+
+ return GpxUiHelper.selectGPXFile(mapActivity, false, false, callbackWithObject);
+ }
+
+ private void applyMovePointMode() {
+ if (inMovePointMode) {
+ switchMovePointMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ WptPt newPoint = measurementLayer.getMovedPointToApply();
+ WptPt oldPoint = measurementLayer.getSelectedCachedPoint();
+ int position = measurementLayer.getSelectedPointPos();
+ commandManager.execute(new MovePointCommand(measurementLayer, oldPoint, newPoint, position));
+ doAddOrMovePointCommonStuff();
+ measurementLayer.exitMovePointMode();
+ measurementLayer.clearSelection();
+ measurementLayer.refreshMap();
+ }
+ }
+
+ private void cancelMovePointMode() {
+ if (inMovePointMode) {
+ switchMovePointMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
+ if (measurementToolLayer != null) {
+ measurementToolLayer.exitMovePointMode();
+ measurementToolLayer.clearSelection();
+ measurementToolLayer.refreshMap();
+ }
+ }
+
+ private void addPointAfter() {
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null && positionToAddPoint != -1) {
+ if (addPointToPosition(positionToAddPoint)) {
+ selectedPointPos += 1;
+ selectedCachedPoint = new WptPt(measurementLayer.getMeasurementPoints().get(selectedPointPos));
+ measurementLayer.setSelectedPointPos(selectedPointPos);
+ measurementLayer.setSelectedCachedPoint(selectedCachedPoint);
+ measurementLayer.refreshMap();
+ positionToAddPoint += 1;
+ }
+ }
+ }
+
+ private void applyAddPointAfterMode() {
+ if (inAddPointAfterMode) {
+ switchAddPointAfterMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ measurementLayer.exitAddPointAfterMode();
+ measurementLayer.clearSelection();
+ measurementLayer.refreshMap();
+ }
+ positionToAddPoint = -1;
+ }
+
+ private void cancelAddPointAfterMode() {
+ if (inAddPointAfterMode) {
+ switchAddPointAfterMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
+ if (measurementToolLayer != null) {
+ measurementToolLayer.exitAddPointAfterMode();
+ measurementToolLayer.clearSelection();
+ measurementToolLayer.refreshMap();
+ }
+ positionToAddPoint = -1;
+ }
+
+ private void addPointBefore() {
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null && positionToAddPoint != -1) {
+ if (addPointToPosition(positionToAddPoint)) {
+ selectedCachedPoint = new WptPt(measurementLayer.getMeasurementPoints().get(selectedPointPos));
+ measurementLayer.setSelectedPointPos(selectedPointPos);
+ measurementLayer.setSelectedCachedPoint(selectedCachedPoint);
+ measurementLayer.refreshMap();
+ }
+ }
+ }
+
+ private void applyAddPointBeforeMode() {
+ if (inAddPointBeforeMode) {
+ switchAddPointBeforeMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ measurementLayer.exitAddPointBeforeMode();
+ measurementLayer.clearSelection();
+ measurementLayer.refreshMap();
+ }
+ positionToAddPoint = -1;
+ }
+
+ private void cancelAddPointBeforeMode() {
+ if (inAddPointBeforeMode) {
+ switchAddPointBeforeMode(false);
+ }
+ clearSelection();
+ MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
+ if (measurementToolLayer != null) {
+ measurementToolLayer.exitAddPointBeforeMode();
+ measurementToolLayer.clearSelection();
+ measurementToolLayer.refreshMap();
+ }
+ positionToAddPoint = -1;
+ }
+
+ private void clearSelection() {
+ selectedPointPos = -1;
+ selectedCachedPoint = null;
+ }
+
+ private void switchMovePointMode(boolean enable) {
+ inMovePointMode = enable;
+ if (inMovePointMode) {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_mode_back, R.drawable.ic_action_mode_back);
+ } else {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_remove_dark, R.drawable.ic_action_remove_dark);
+ }
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.showTopToolbar(toolBarController);
+ }
+ markGeneralComponents(enable ? View.GONE : View.VISIBLE);
+ mark(enable ? View.VISIBLE : View.GONE,
+ R.id.move_point_text,
+ R.id.move_point_controls);
+ mainIcon.setImageDrawable(getActiveIcon(enable
+ ? R.drawable.ic_action_move_point
+ : R.drawable.ic_action_ruler));
+ }
+
+ private void switchAddPointAfterMode(boolean enable) {
+ inAddPointAfterMode = enable;
+ if (inAddPointAfterMode) {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_mode_back, R.drawable.ic_action_mode_back);
+ } else {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_remove_dark, R.drawable.ic_action_remove_dark);
+ }
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.showTopToolbar(toolBarController);
+ }
+ markGeneralComponents(enable ? View.GONE : View.VISIBLE);
+ mark(enable ? View.VISIBLE : View.GONE,
+ R.id.add_point_after_text,
+ R.id.add_point_before_after_controls);
+ mainIcon.setImageDrawable(getActiveIcon(enable
+ ? R.drawable.ic_action_addpoint_above
+ : R.drawable.ic_action_ruler));
+ }
+
+ private void switchAddPointBeforeMode(boolean enable) {
+ inAddPointBeforeMode = enable;
+ if (inAddPointBeforeMode) {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_mode_back, R.drawable.ic_action_mode_back);
+ } else {
+ toolBarController.setBackBtnIconIds(R.drawable.ic_action_remove_dark, R.drawable.ic_action_remove_dark);
+ }
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.showTopToolbar(toolBarController);
+ }
+ markGeneralComponents(enable ? View.GONE : View.VISIBLE);
+ mark(enable ? View.VISIBLE : View.GONE,
+ R.id.add_point_before_text,
+ R.id.add_point_before_after_controls);
+ mainIcon.setImageDrawable(getActiveIcon(enable
+ ? R.drawable.ic_action_addpoint_below
+ : R.drawable.ic_action_ruler));
+ }
+
+ private void markGeneralComponents(int status) {
+ mark(status,
+ R.id.measurement_distance_text_view,
+ R.id.measurement_points_text_view,
+ R.id.distance_to_center_text_view,
+ R.id.up_down_button,
+ R.id.measure_mode_controls);
+ }
+
+ private void addPoint() {
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ commandManager.execute(new AddPointCommand(measurementLayer, false));
+ doAddOrMovePointCommonStuff();
+ }
+ }
+
+ private void addCenterPoint() {
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ commandManager.execute(new AddPointCommand(measurementLayer, true));
+ doAddOrMovePointCommonStuff();
+ }
+ }
+
+ private boolean addPointToPosition(int position) {
+ boolean added = false;
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ added = commandManager.execute(new AddPointCommand(measurementLayer, position));
+ doAddOrMovePointCommonStuff();
+ }
+ return added;
+ }
+
+ private void doAddOrMovePointCommonStuff() {
+ recalculateSnapToRoadIfNedeed();
+ enable(undoBtn, upDownBtn);
+ disable(redoBtn);
+ updateText();
+ adapter.notifyDataSetChanged();
+ saved = false;
+ }
+
+ private void showPointsList() {
+ pointsListOpened = true;
+ upDownBtn.setImageDrawable(downIcon);
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ if (portrait && pointsListContainer != null) {
+ pointsListContainer.setVisibility(View.VISIBLE);
+ } else {
+ showPointsListFragment();
+ }
+ OsmandMapTileView tileView = mapActivity.getMapView();
+ previousMapPosition = tileView.getMapPosition();
+ if (portrait) {
+ tileView.setMapPosition(MIDDLE_TOP_CONSTANT);
+ } else {
+ tileView.setMapPosition(LANDSCAPE_MIDDLE_RIGHT_CONSTANT);
+ }
+ mapActivity.refreshMap();
+ }
+ }
+
+ private void hidePointsList() {
+ pointsListOpened = false;
+ upDownBtn.setImageDrawable(upIcon);
+ if (portrait && pointsListContainer != null) {
+ pointsListContainer.setVisibility(View.GONE);
+ } else {
+ hidePointsListFragment();
+ }
+ setPreviousMapPosition();
+ }
+
+ private void hidePointsListIfNoPoints() {
+ MeasurementToolLayer measurementLayer = getMeasurementLayer();
+ if (measurementLayer != null) {
+ if (measurementPoints.size() < 1) {
+ disable(upDownBtn);
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ }
+ }
+ }
+
+ private void showPointsListFragment() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ int screenHeight = AndroidUtils.getScreenHeight(mapActivity) - AndroidUtils.getStatusBarHeight(mapActivity);
+ MeasurePointsListFragment fragment = new MeasurePointsListFragment();
+ fragment.setRecyclerView(pointsRv);
+ fragment.setWidth(upDownRow.getWidth());
+ fragment.setHeight(screenHeight - upDownRow.getHeight());
+ mapActivity.getSupportFragmentManager().beginTransaction()
+ .add(R.id.fragmentContainer, fragment, MeasurePointsListFragment.TAG)
+ .commitAllowingStateLoss();
+ }
+ }
+
+ private void hidePointsListFragment() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ try {
+ FragmentManager manager = mapActivity.getSupportFragmentManager();
+ Fragment fragment = manager.findFragmentByTag(MeasurePointsListFragment.TAG);
+ if (fragment != null) {
+ manager.beginTransaction().remove(fragment).commitAllowingStateLoss();
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ private void setPreviousMapPosition() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.getMapView().setMapPosition(previousMapPosition);
+ mapActivity.refreshMap();
+ }
+ }
+
+ private void addToGpx(MapActivity mapActivity) {
+ GPXFile gpx = newGpxData.getGpxFile();
+ SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpx.path);
+ boolean showOnMap = selectedGpxFile != null;
+ NewGpxData.ActionType actionType = newGpxData.getActionType();
+ saveExistingGpx(gpx, showOnMap, actionType, true);
+ }
+
+ private void saveAsGpx(final SaveType saveType) {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
+ final LayoutInflater inflater = mapActivity.getLayoutInflater();
+ final View view = inflater.inflate(R.layout.save_gpx_dialog, null);
+ final EditText nameEt = (EditText) view.findViewById(R.id.gpx_name_et);
+ final TextView fileExistsTv = (TextView) view.findViewById(R.id.file_exists_text_view);
+ final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
+ showOnMapToggle.setChecked(true);
+
+ final String suggestedName = new SimpleDateFormat("yyyy-M-dd_HH-mm_EEE", Locale.US).format(new Date());
+ String displayedName = suggestedName;
+ File fout = new File(dir, suggestedName + GPX_SUFFIX);
+ int ind = 1;
+ while (fout.exists()) {
+ displayedName = suggestedName + "_" + (++ind);
+ fout = new File(dir, displayedName + GPX_SUFFIX);
+ }
+ nameEt.setText(displayedName);
+ nameEt.setSelection(displayedName.length());
+
+ final boolean[] textChanged = new boolean[1];
+ nameEt.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ if (new File(dir, editable.toString() + GPX_SUFFIX).exists()) {
+ fileExistsTv.setVisibility(View.VISIBLE);
+ } else {
+ fileExistsTv.setVisibility(View.INVISIBLE);
+ }
+ textChanged[0] = true;
+ }
+ });
+
+ new AlertDialog.Builder(mapActivity)
+ .setTitle(R.string.enter_gpx_name)
+ .setView(view)
+ .setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final String name = nameEt.getText().toString();
+ String fileName = name + GPX_SUFFIX;
+ if (textChanged[0]) {
+ File fout = new File(dir, fileName);
+ int ind = 1;
+ while (fout.exists()) {
+ fileName = name + "_" + (++ind) + GPX_SUFFIX;
+ fout = new File(dir, fileName);
+ }
+ }
+ saveNewGpx(dir, fileName, showOnMapToggle.isChecked(), saveType);
+ }
+ })
+ .setNegativeButton(R.string.shared_string_cancel, null)
+ .show();
+ }
+ }
+
+ private void saveNewGpx(File dir, String fileName, boolean checked, SaveType saveType) {
+ saveGpx(dir, fileName, checked, null, false, null, saveType);
+ }
+
+ private void saveExistingGpx(GPXFile gpx, boolean showOnMap, NewGpxData.ActionType actionType, boolean openTrackActivity) {
+ saveGpx(null, null, showOnMap, gpx, openTrackActivity, actionType, null);
+ }
+
+ private void saveGpx(final File dir,
+ final String fileName,
+ final boolean showOnMap,
+ final GPXFile gpx,
+ final boolean openTrackActivity,
+ final NewGpxData.ActionType actionType,
+ final SaveType saveType) {
+
new AsyncTask() {
private ProgressDialog progressDialog;
@@ -287,27 +1347,67 @@ 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 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 (showOnMap) {
- activity.getMyApplication().getSelectedGpxHelper().selectGpxFile(gpx, true, false);
+ if (gpx == null) {
+ toSave = new File(dir, fileName);
+ GPXFile gpx = new GPXFile();
+ if (measurementLayer != null) {
+ List points = measurementLayer.getMeasurementPoints();
+ if (saveType == SaveType.LINE) {
+ TrkSegment segment = new TrkSegment();
+ segment.points.addAll(points);
+ Track track = new Track();
+ track.segments.add(segment);
+ gpx.tracks.add(track);
+ } else if (saveType == SaveType.ROUTE_POINT) {
+ Route rt = new Route();
+ gpx.routes.add(rt);
+ rt.points.addAll(points);
+ }
+ }
+ if (activity != null) {
+ String res = GPXUtilities.writeGpxFile(toSave, gpx, activity.getMyApplication());
+ gpx.path = toSave.getAbsolutePath();
+ if (showOnMap) {
+ activity.getMyApplication().getSelectedGpxHelper().selectGpxFile(gpx, true, false);
+ }
+ return res;
+ }
+ } else {
+ toSave = new File(gpx.path);
+ if (measurementLayer != null) {
+ List points = measurementLayer.getMeasurementPoints();
+ if (actionType != null) {
+ switch (actionType) {
+ case ADD_SEGMENT:
+ gpx.addTrkSegment(points);
+ break;
+ case ADD_ROUTE_POINTS:
+ gpx.replaceRoutePoints(points);
+ break;
+ case EDIT_SEGMENT:
+ TrkSegment segment = new TrkSegment();
+ segment.points.addAll(points);
+ gpx.replaceSegment(newGpxData.getTrkSegment(), segment);
+ break;
+ }
+ } else {
+ gpx.addRoutePoints(points);
+ }
+ }
+ if (activity != null) {
+ String res = GPXUtilities.writeGpxFile(toSave, gpx, activity.getMyApplication());
+ if (showOnMap) {
+ SelectedGpxFile sf = activity.getMyApplication().getSelectedGpxHelper().selectGpxFile(gpx, true, false);
+ if (sf != null) {
+ if (actionType == NewGpxData.ActionType.ADD_SEGMENT || actionType == NewGpxData.ActionType.EDIT_SEGMENT) {
+ sf.processPoints();
+ }
+ }
+ }
+ return res;
}
- return res;
}
return null;
}
@@ -315,41 +1415,28 @@ public class MeasurementToolFragment extends Fragment {
@Override
protected void onPostExecute(String warning) {
MapActivity activity = getMapActivity();
- if (activity != null) {
- if (warning == null) {
- Toast.makeText(activity,
- MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getAbsolutePath()),
- Toast.LENGTH_LONG).show();
- } else {
- Toast.makeText(activity, warning, Toast.LENGTH_LONG).show();
- }
- activity.refreshMap();
- }
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
+ if (activity != null) {
+ activity.refreshMap();
+ if (warning == null) {
+ saved = true;
+ if (openTrackActivity) {
+ dismiss(activity);
+ } else {
+ Toast.makeText(activity,
+ MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getAbsolutePath()),
+ Toast.LENGTH_LONG).show();
+ }
+ } else {
+ Toast.makeText(activity, warning, Toast.LENGTH_LONG).show();
+ }
+ }
}
}.execute();
}
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- exitMeasurementMode();
- }
-
- private MapActivity getMapActivity() {
- return (MapActivity) getActivity();
- }
-
- private MeasurementToolLayer getMeasurementLayer() {
- MapActivity mapActivity = getMapActivity();
- if (mapActivity != null) {
- return mapActivity.getMapLayers().getMeasurementToolLayer();
- }
- return null;
- }
-
private void enable(View... views) {
for (View view : views) {
view.setEnabled(true);
@@ -368,7 +1455,7 @@ public class MeasurementToolFragment extends Fragment {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
distanceTv.setText(measurementLayer.getDistanceSt() + ",");
- pointsTv.setText(pointsSt + ": " + measurementLayer.getPointsCount());
+ pointsTv.setText((portrait ? pointsSt + ": " : "") + measurementPoints.size());
}
}
@@ -379,9 +1466,18 @@ public class MeasurementToolFragment extends Fragment {
measurementLayer.setInMeasurementMode(true);
mapActivity.refreshMap();
mapActivity.disableDrawer();
- mark(View.INVISIBLE, R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
- mark(View.GONE, R.id.map_route_info_button, R.id.map_menu_button, R.id.map_compass_button, R.id.map_layers_button,
- R.id.map_search_button, R.id.map_quick_actions_button);
+
+ mark(portrait ? View.INVISIBLE : View.GONE,
+ R.id.map_left_widgets_panel,
+ R.id.map_right_widgets_panel,
+ R.id.map_center_info);
+ mark(View.GONE,
+ R.id.map_route_info_button,
+ R.id.map_menu_button,
+ R.id.map_compass_button,
+ R.id.map_layers_button,
+ R.id.map_search_button,
+ R.id.map_quick_actions_button);
View collapseButton = mapActivity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && collapseButton.getVisibility() == View.VISIBLE) {
@@ -403,18 +1499,25 @@ public class MeasurementToolFragment extends Fragment {
mapActivity.hideTopToolbar(toolBarController);
}
measurementLayer.setInMeasurementMode(false);
- mapActivity.refreshMap();
mapActivity.enableDrawer();
- mark(View.VISIBLE, R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info,
- R.id.map_route_info_button, R.id.map_menu_button, R.id.map_compass_button, R.id.map_layers_button,
- R.id.map_search_button, R.id.map_quick_actions_button);
+
+ mark(View.VISIBLE,
+ R.id.map_left_widgets_panel,
+ R.id.map_right_widgets_panel,
+ R.id.map_center_info,
+ R.id.map_route_info_button,
+ R.id.map_menu_button,
+ R.id.map_compass_button,
+ R.id.map_layers_button,
+ R.id.map_search_button,
+ R.id.map_quick_actions_button);
View collapseButton = mapActivity.findViewById(R.id.map_collapse_button);
if (collapseButton != null && wasCollapseButtonVisible) {
collapseButton.setVisibility(View.VISIBLE);
}
- measurementLayer.clearPoints();
+ mapActivity.refreshMap();
}
}
@@ -430,11 +1533,31 @@ public class MeasurementToolFragment extends Fragment {
}
}
- public void showQuitDialog() {
+ public void quit(boolean hidePointsListFirst) {
+ if (inMovePointMode) {
+ cancelMovePointMode();
+ return;
+ }
+ if (inAddPointAfterMode) {
+ cancelAddPointAfterMode();
+ return;
+ }
+ if (inAddPointBeforeMode) {
+ cancelAddPointBeforeMode();
+ return;
+ }
+ showQuitDialog(hidePointsListFirst);
+ }
+
+ private 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 (measurementPoints.size() < 1 || saved) {
dismiss(mapActivity);
return;
}
@@ -454,31 +1577,67 @@ public class MeasurementToolFragment extends Fragment {
private void dismiss(MapActivity mapActivity) {
try {
- mapActivity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
+ if (measurementToolLayer != null) {
+ measurementToolLayer.getMeasurementPoints().clear();
+ }
+ if (pointsListOpened) {
+ hidePointsList();
+ }
+ if (isInSnapToRoadMode) {
+ disableSnapToRoadMode();
+ }
+ if (newGpxData != null) {
+ GPXFile gpx = newGpxData.getGpxFile();
+ Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
+ newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path);
+ newIntent.putExtra(TrackActivity.OPEN_TRACKS_LIST, true);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(newIntent);
+ }
+ mapActivity.getSupportFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
} catch (Exception e) {
// ignore
}
}
- private static class MeasurementToolBarController extends TopToolbarController {
+ public static boolean showInstance(FragmentManager fragmentManager, NewGpxData newGpxData) {
+ try {
+ MeasurementToolFragment fragment = new MeasurementToolFragment();
+ fragment.setNewGpxData(newGpxData);
+ fragment.setRetainInstance(true);
+ fragmentManager.beginTransaction()
+ .add(R.id.bottomFragmentContainer, fragment, MeasurementToolFragment.TAG)
+ .commitAllowingStateLoss();
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
- MeasurementToolBarController() {
+ private class MeasurementToolBarController extends TopToolbarController {
+
+ MeasurementToolBarController(NewGpxData newGpxData) {
super(MapInfoWidgetsFactory.TopToolbarControllerType.MEASUREMENT_TOOL);
setBackBtnIconClrIds(0, 0);
- setCloseBtnIconClrIds(0, 0);
setTitleTextClrIds(R.color.primary_text_dark, R.color.primary_text_dark);
setDescrTextClrIds(R.color.primary_text_dark, R.color.primary_text_dark);
setBgIds(R.drawable.gradient_toolbar, R.drawable.gradient_toolbar,
R.drawable.gradient_toolbar, R.drawable.gradient_toolbar);
- setCloseBtnIconIds(R.drawable.ic_overflow_menu_white, R.drawable.ic_overflow_menu_white);
- setBackBtnIconIds(R.drawable.ic_action_remove_dark, R.drawable.ic_action_remove_dark);
+ setCloseBtnVisible(false);
+ if (newGpxData != null) {
+ setSaveViewVisible(true);
+ }
setSingleLineTitle(false);
}
@Override
public void updateToolbar(MapInfoWidgetsFactory.TopToolbarView view) {
super.updateToolbar(view);
- view.getShadowView().setVisibility(View.GONE);
+ View shadow = view.getShadowView();
+ if (shadow != null) {
+ shadow.setVisibility(View.GONE);
+ }
}
}
}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java
index 1ea5208cc6..3ca9f8402f 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolLayer.java
@@ -7,6 +7,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
+import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadPoint;
@@ -28,18 +29,32 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
private OsmandMapTileView view;
private boolean inMeasurementMode;
- private LinkedList measurementPoints = new LinkedList<>();
- private LinkedList cacheMeasurementPoints = new LinkedList<>();
+ private boolean inMovePointMode;
+ private boolean inAddPointAfterMode;
+ private boolean inAddPointBeforeMode;
+ private List measurementPoints = new LinkedList<>();
+ private List snappedToRoadPoints = new LinkedList<>();
private Bitmap centerIconDay;
private Bitmap centerIconNight;
private Bitmap pointIcon;
+ private Bitmap applyingPointIcon;
private Paint bitmapPaint;
- private RenderingLineAttributes lineAttrs = new RenderingLineAttributes("rulerLine");
- private Path path = new Path();
- private int marginX;
- private int marginY;
- private TIntArrayList tx = new TIntArrayList();
- private TIntArrayList ty = new TIntArrayList();
+ private final RenderingLineAttributes lineAttrs = new RenderingLineAttributes("measureDistanceLine");
+ private final Path path = new Path();
+ private int marginPointIconX;
+ private int marginPointIconY;
+ private int marginApplyingPointIconX;
+ private int marginApplyingPointIconY;
+ private final TIntArrayList tx = new TIntArrayList();
+ private final TIntArrayList ty = new TIntArrayList();
+ private OnMeasureDistanceToCenter measureDistanceToCenterListener;
+ private OnSingleTapListener singleTapListener;
+ private OnEnterMovePointModeListener enterMovePointModeListener;
+ private int selectedPointPos = -1;
+ private WptPt selectedCachedPoint;
+ private LatLon pressedPointLatLon;
+ private boolean overlapped;
+ private int pointsToDraw = 50;
@Override
public void initLayer(OsmandMapTileView view) {
@@ -47,31 +62,83 @@ 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);
+ pointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_measure_point_day);
+ applyingPointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_measure_point_move_day);
bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);
bitmapPaint.setDither(true);
bitmapPaint.setFilterBitmap(true);
- marginY = pointIcon.getHeight() / 2;
- marginX = pointIcon.getWidth() / 2;
+ marginPointIconY = pointIcon.getHeight() / 2;
+ marginPointIconX = pointIcon.getWidth() / 2;
+
+ marginApplyingPointIconY = applyingPointIcon.getHeight() / 2;
+ marginApplyingPointIconX = applyingPointIcon.getWidth() / 2;
+ }
+
+ void setOnSingleTapListener(OnSingleTapListener listener) {
+ this.singleTapListener = listener;
+ }
+
+ void setOnEnterMovePointModeListener(OnEnterMovePointModeListener listener) {
+ this.enterMovePointModeListener = listener;
+ }
+
+ void setOnMeasureDistanceToCenterListener(OnMeasureDistanceToCenter listener) {
+ this.measureDistanceToCenterListener = listener;
+ }
+
+ void setSelectedPointPos(int pos) {
+ selectedPointPos = pos;
+ }
+
+ void setSelectedCachedPoint(WptPt selectedCachedPoint) {
+ this.selectedCachedPoint = selectedCachedPoint;
+ }
+
+ WptPt getSelectedCachedPoint() {
+ return selectedCachedPoint;
+ }
+
+ int getSelectedPointPos() {
+ return selectedPointPos;
}
public boolean isInMeasurementMode() {
return inMeasurementMode;
}
+ boolean isInMovePointMode() {
+ return inMovePointMode;
+ }
+
+ boolean isInAddPointAfterMode() {
+ return inAddPointAfterMode;
+ }
+
+ boolean isInAddPointBeforeMode() {
+ return inAddPointBeforeMode;
+ }
+
void setInMeasurementMode(boolean inMeasurementMode) {
this.inMeasurementMode = inMeasurementMode;
}
- int getPointsCount() {
- return measurementPoints.size();
+ public List getMeasurementPoints() {
+ return measurementPoints;
}
- public LinkedList getMeasurementPoints() {
- return measurementPoints;
+ void setMeasurementPoints(List points) {
+ measurementPoints = points;
+ }
+
+ public List getSnappedToRoadPoints() {
+ return snappedToRoadPoints;
+ }
+
+ public void setSnappedToRoadPoints(List snappedToRoadPoints) {
+ this.snappedToRoadPoints = snappedToRoadPoints;
}
String getDistanceSt() {
@@ -85,50 +152,223 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
return OsmAndFormatter.getFormattedDistance(dist, view.getApplication());
}
- void clearPoints() {
- measurementPoints.clear();
- cacheMeasurementPoints.clear();
- view.refreshMap();
+ @Override
+ public boolean onSingleTap(PointF point, RotatedTileBox tileBox) {
+ if (singleTapListener != null) {
+ if (inMeasurementMode && !inMovePointMode && !inAddPointAfterMode && !inAddPointBeforeMode) {
+ if (overlapped) {
+ clearSelection();
+ } else {
+ selectPoint(point.x, point.y, true);
+ }
+ if (selectedPointPos == -1) {
+ pressedPointLatLon = tileBox.getLatLonFromPixel(point.x, point.y);
+ singleTapListener.onAddPoint();
+ }
+ }
+ }
+ return false;
+ }
+
+ void clearSelection() {
+ selectedPointPos = -1;
+ selectedCachedPoint = null;
+ }
+
+ @Override
+ public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
+ if (inMeasurementMode) {
+ if (!overlapped && !inMovePointMode && !inAddPointAfterMode && !inAddPointBeforeMode && measurementPoints.size() > 0) {
+ selectPoint(point.x, point.y, false);
+ if (selectedCachedPoint != null && selectedPointPos != -1) {
+ enterMovingPointMode();
+ if (inMeasurementMode && inMovePointMode && enterMovePointModeListener != null) {
+ enterMovePointModeListener.onEnterMovePointMode();
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ void enterMovingPointMode() {
+ inMovePointMode = true;
+ moveMapToPoint(selectedPointPos);
+ }
+
+ void enterAddingPointAfterMode() {
+ inAddPointAfterMode = true;
+ moveMapToPoint(selectedPointPos);
+ }
+
+ void enterAddingPointBeforeMode() {
+ inAddPointBeforeMode = true;
+ moveMapToPoint(selectedPointPos);
+ }
+
+ private void selectPoint(double x, double y, boolean singleTap) {
+ clearSelection();
+ RotatedTileBox tb = view.getCurrentRotatedTileBox();
+ double lowestDistance = view.getResources().getDimension(R.dimen.measurement_tool_select_radius);
+ for (int i = 0; i < measurementPoints.size(); i++) {
+ WptPt pt = measurementPoints.get(i);
+ if (tb.containsLatLon(pt.getLatitude(), pt.getLongitude())) {
+ double xDiff = tb.getPixXFromLonNoRot(pt.getLongitude()) - x;
+ double yDiff = tb.getPixYFromLatNoRot(pt.getLatitude()) - y;
+ double distToPoint = Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2));
+ if (distToPoint < lowestDistance) {
+ lowestDistance = distToPoint;
+ selectedCachedPoint = new WptPt(pt);
+ selectedPointPos = i;
+ }
+ }
+ }
+ if (singleTap && singleTapListener != null) {
+ singleTapListener.onSelectPoint(selectedPointPos, selectedCachedPoint);
+ }
+ }
+
+ void selectPoint(int position) {
+ clearSelection();
+ selectedCachedPoint = new WptPt(measurementPoints.get(position));
+ selectedPointPos = position;
+ if (singleTapListener != null) {
+ singleTapListener.onSelectPoint(selectedPointPos, selectedCachedPoint);
+ }
}
@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 && !inAddPointAfterMode && !inAddPointBeforeMode) {
+ drawCenterIcon(canvas, tb, tb.getCenterPixelPoint(), settings.isNightMode());
+ if (measureDistanceToCenterListener != null) {
+ float distance = 0;
+ if (measurementPoints.size() > 0) {
+ WptPt lastPoint = measurementPoints.get(measurementPoints.size() - 1);
+ LatLon centerLatLon = tb.getCenterLatLon();
+ distance = (float) MapUtils.getDistance(lastPoint.lat, lastPoint.lon, centerLatLon.getLatitude(), centerLatLon.getLongitude());
+ }
+ measureDistanceToCenterListener.onMeasure(distance);
+ }
+ }
- if (measurementPoints.size() > 0) {
+ List drawPoints;
+ if (snappedToRoadPoints.size() > 0) {
+ drawPoints = snappedToRoadPoints;
+ } else {
+ drawPoints = measurementPoints;
+ }
+ if (drawPoints.size() > 0) {
path.reset();
tx.reset();
ty.reset();
+
+ for (int i = 0; i < drawPoints.size(); i++) {
+ WptPt pt = drawPoints.get(i);
+ int locX;
+ int locY;
+ if (selectedPointPos == i && (inMovePointMode || inAddPointAfterMode || inAddPointBeforeMode)) {
+ locX = tb.getCenterPixelX();
+ locY = tb.getCenterPixelY();
+ } else {
+ locX = tb.getPixXFromLonNoRot(pt.lon);
+ locY = tb.getPixYFromLatNoRot(pt.lat);
+ }
+ if (inAddPointAfterMode) {
+ int previousLocX = tb.getPixXFromLonNoRot(pt.lon);
+ int previousLocY = tb.getPixYFromLatNoRot(pt.lat);
+ if (i == 0) {
+ path.moveTo(previousLocX, previousLocY);
+ } else {
+ path.lineTo(previousLocX, previousLocY);
+ }
+ tx.add(previousLocX);
+ ty.add(previousLocY);
+ path.lineTo(locX, locY);
+ tx.add(locX);
+ ty.add(locY);
+ } else if (inAddPointBeforeMode) {
+ if (i == 0) {
+ path.moveTo(locX, locY);
+ } else {
+ path.lineTo(locX, locY);
+ }
+ tx.add(locX);
+ ty.add(locY);
+ int followingLocX = tb.getPixXFromLonNoRot(pt.lon);
+ int followingLocY = tb.getPixYFromLatNoRot(pt.lat);
+ path.lineTo(followingLocX, followingLocY);
+ tx.add(followingLocX);
+ ty.add(followingLocY);
+ } else {
+ if (i == 0) {
+ path.moveTo(locX, locY);
+ } else {
+ path.lineTo(locX, locY);
+ }
+ tx.add(locX);
+ ty.add(locY);
+ }
+ }
+ if (!inMovePointMode && !inAddPointAfterMode && !inAddPointBeforeMode) {
+ path.lineTo(tb.getCenterPixelX(), tb.getCenterPixelY());
+ tx.add(tb.getCenterPixelX());
+ ty.add(tb.getCenterPixelY());
+ }
+ calculatePath(tb, tx, ty, path);
+ canvas.drawPath(path, lineAttrs.paint);
+
+ overlapped = false;
+ int drawn = 0;
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);
- if (i == 0) {
- path.moveTo(locX, locY);
- } else {
- path.lineTo(locX, locY);
+ if (locX >= 0 && locX <= tb.getPixWidth() && locY >= 0 && locY <= tb.getPixHeight()) {
+ if (!(inMovePointMode && i == selectedPointPos)) {
+ drawn++;
+ if (drawn > pointsToDraw) {
+ overlapped = true;
+ break;
+ }
+ }
}
- tx.add(locX);
- ty.add(locY);
}
- 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)) {
+ if (!overlapped) {
+ 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);
- canvas.drawBitmap(pointIcon, locX - marginX, locY - marginY, bitmapPaint);
+ if (locX >= 0 && locX <= tb.getPixWidth() && locY >= 0 && locY <= tb.getPixHeight()) {
+ if (!(inMovePointMode && i == selectedPointPos)) {
+ canvas.drawBitmap(pointIcon, locX - marginPointIconX, locY - marginPointIconY, bitmapPaint);
+ }
+ }
}
}
+ if (inAddPointAfterMode || inAddPointBeforeMode || inMovePointMode) {
+ int locX = tb.getCenterPixelX();
+ int locY = tb.getCenterPixelY();
+ canvas.drawBitmap(applyingPointIcon, locX - marginApplyingPointIconX, locY - marginApplyingPointIconY, bitmapPaint);
+ }
}
}
}
+ void exitMovePointMode() {
+ inMovePointMode = false;
+ }
+
+ void exitAddPointAfterMode() {
+ inAddPointAfterMode = false;
+ }
+
+ void exitAddPointBeforeMode() {
+ inAddPointBeforeMode = false;
+ }
+
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode) {
canvas.rotate(-tb.getRotate(), center.x, center.y);
if (nightMode) {
@@ -141,37 +381,59 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
canvas.rotate(tb.getRotate(), center.x, center.y);
}
- void addPointOnClick() {
+ public WptPt addCenterPoint(int position) {
RotatedTileBox tb = view.getCurrentRotatedTileBox();
LatLon l = tb.getLatLonFromPixel(tb.getCenterPixelX(), tb.getCenterPixelY());
WptPt pt = new WptPt();
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
- if (measurementPoints.size() > 0) {
- if (!measurementPoints.get(measurementPoints.size() - 1).equals(pt)) {
- measurementPoints.add(pt);
- }
- } else {
- measurementPoints.add(pt);
+ boolean allowed = measurementPoints.size() == 0 || !measurementPoints.get(measurementPoints.size() - 1).equals(pt);
+ if (allowed) {
+ measurementPoints.add(position, pt);
+ return pt;
}
- cacheMeasurementPoints = new LinkedList<>(measurementPoints);
- view.refreshMap();
+ return null;
}
- boolean undoPointOnClick() {
- measurementPoints.remove(measurementPoints.size() - 1);
+ public WptPt addPoint(int position) {
+ if (pressedPointLatLon != null) {
+ WptPt pt = new WptPt();
+ pt.lat = pressedPointLatLon.getLatitude();
+ pt.lon = pressedPointLatLon.getLongitude();
+ pressedPointLatLon = null;
+ boolean allowed = measurementPoints.size() == 0 || !measurementPoints.get(measurementPoints.size() - 1).equals(pt);
+ if (allowed) {
+ measurementPoints.add(position, pt);
+ moveMapToPoint(position);
+ return pt;
+ }
+ }
+ return null;
+ }
+
+ WptPt getMovedPointToApply() {
+ RotatedTileBox tb = view.getCurrentRotatedTileBox();
+ LatLon latLon = tb.getCenterLatLon();
+ WptPt pt = measurementPoints.get(selectedPointPos);
+ pt.lat = latLon.getLatitude();
+ pt.lon = latLon.getLongitude();
+ return pt;
+ }
+
+ 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 +475,19 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
public boolean isObjectClickable(Object o) {
return !isInMeasurementMode();
}
+
+ interface OnSingleTapListener {
+
+ void onAddPoint();
+
+ void onSelectPoint(int selectedPointPos, WptPt selectedCachedPoint);
+ }
+
+ interface OnEnterMovePointModeListener {
+ void onEnterMovePointMode();
+ }
+
+ interface OnMeasureDistanceToCenter {
+ void onMeasure(float distance);
+ }
}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/NewGpxData.java b/OsmAnd/src/net/osmand/plus/measurementtool/NewGpxData.java
new file mode 100644
index 0000000000..500c0335c7
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/NewGpxData.java
@@ -0,0 +1,36 @@
+package net.osmand.plus.measurementtool;
+
+import net.osmand.data.QuadRect;
+import net.osmand.plus.GPXUtilities;
+
+public class NewGpxData {
+ public enum ActionType { ADD_SEGMENT, ADD_ROUTE_POINTS, EDIT_SEGMENT }
+
+ private GPXUtilities.GPXFile gpxFile;
+ private GPXUtilities.TrkSegment trkSegment;
+ private QuadRect rect;
+ private ActionType actionType;
+
+ public NewGpxData(GPXUtilities.GPXFile gpxFile, QuadRect rect, ActionType actionType, GPXUtilities.TrkSegment trkSegment) {
+ this.gpxFile = gpxFile;
+ this.rect = rect;
+ this.actionType = actionType;
+ this.trkSegment = trkSegment;
+ }
+
+ public GPXUtilities.GPXFile getGpxFile() {
+ return gpxFile;
+ }
+
+ public QuadRect getRect() {
+ return rect;
+ }
+
+ public ActionType getActionType() {
+ return actionType;
+ }
+
+ public GPXUtilities.TrkSegment getTrkSegment() {
+ return trkSegment;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java
new file mode 100644
index 0000000000..63b68e4191
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java
@@ -0,0 +1,206 @@
+package net.osmand.plus.measurementtool;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.SwitchCompat;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.R;
+import net.osmand.plus.base.BottomSheetDialogFragment;
+import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.plus.widgets.TextViewEx;
+
+public class OptionsBottomSheetDialogFragment extends BottomSheetDialogFragment {
+
+ public final static String TAG = "OptionsBottomSheetDialogFragment";
+
+ private OptionsFragmentListener listener;
+ private boolean addLineMode;
+ private boolean portrait;
+ private boolean nightMode;
+ private boolean snapToRoadEnabled;
+
+ public void setListener(OptionsFragmentListener listener) {
+ this.listener = listener;
+ }
+
+ public void setAddLineMode(boolean addLineMode) {
+ this.addLineMode = addLineMode;
+ }
+
+ public void setSnapToRoadEnabled(boolean snapToRoadEnabled) {
+ this.snapToRoadEnabled = snapToRoadEnabled;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ portrait = AndroidUiHelper.isOrientationPortrait(getActivity());
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+
+ final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_options_bottom_sheet_dialog, null);
+ if (portrait) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
+ }
+
+ if (nightMode) {
+ ((TextViewEx) mainView.findViewById(R.id.options_title)).setTextColor(getResources().getColor(R.color.ctx_menu_info_text_dark));
+ }
+ if (snapToRoadEnabled) {
+ mainView.findViewById(R.id.snap_to_road_enabled_text_view).setVisibility(View.VISIBLE);
+ ((SwitchCompat) mainView.findViewById(R.id.snap_to_road_switch)).setChecked(true);
+ }
+ ((ImageView) mainView.findViewById(R.id.snap_to_road_icon)).setImageDrawable(snapToRoadEnabled
+ ? getActiveIcon(R.drawable.ic_action_snap_to_road)
+ : getContentIcon(R.drawable.ic_action_snap_to_road));
+ ((ImageView) mainView.findViewById(R.id.clear_all_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_reset_to_default_dark));
+ if (!addLineMode) {
+ ((ImageView) mainView.findViewById(R.id.save_as_new_track_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_polygom_dark));
+ ((ImageView) mainView.findViewById(R.id.add_to_the_track_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_split_interval));
+ } else {
+ mainView.findViewById(R.id.save_as_new_track_row).setVisibility(View.GONE);
+ mainView.findViewById(R.id.add_to_the_track_row).setVisibility(View.GONE);
+ mainView.findViewById(R.id.save_as_new_segment_row).setVisibility(View.VISIBLE);
+ ((ImageView) mainView.findViewById(R.id.save_as_new_segment_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_polygom_dark));
+ }
+
+ mainView.findViewById(R.id.snap_to_road_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.snapToRoadOnCLick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.clear_all_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.clearAllOnClick();
+ }
+ dismiss();
+ }
+ });
+ if (!addLineMode) {
+ mainView.findViewById(R.id.save_as_new_track_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.saveAsNewTrackOnClick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.add_to_the_track_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.addToTheTrackOnClick();
+ }
+ dismiss();
+ }
+ });
+ } else {
+ mainView.findViewById(R.id.save_as_new_segment_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.addToGpxOnClick();
+ }
+ dismiss();
+ }
+ });
+ }
+ mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+
+ final int screenHeight = AndroidUtils.getScreenHeight(getActivity());
+ final int statusBarHeight = AndroidUtils.getStatusBarHeight(getActivity());
+ final int navBarHeight = AndroidUtils.getNavBarHeight(getActivity());
+
+ mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ final View scrollView = mainView.findViewById(R.id.measure_options_scroll_view);
+ int scrollViewHeight = scrollView.getHeight();
+ int dividerHeight = AndroidUtils.dpToPx(getContext(), 1);
+ int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.measure_distance_bottom_sheet_cancel_button_height);
+ int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight;
+ if (scrollViewHeight > spaceForScrollView) {
+ scrollView.getLayoutParams().height = spaceForScrollView;
+ scrollView.requestLayout();
+ }
+
+ if (!portrait) {
+ if (screenHeight - statusBarHeight - mainView.getHeight()
+ >= AndroidUtils.dpToPx(getActivity(), 8)) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark);
+ } else {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_sides_landscape_light, R.drawable.bg_bottom_sheet_sides_landscape_dark);
+ }
+ }
+
+ ViewTreeObserver obs = mainView.getViewTreeObserver();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ obs.removeOnGlobalLayoutListener(this);
+ } else {
+ obs.removeGlobalOnLayoutListener(this);
+ }
+ }
+ });
+
+ return mainView;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!portrait) {
+ final Window window = getDialog().getWindow();
+ WindowManager.LayoutParams params = window.getAttributes();
+ params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
+ window.setAttributes(params);
+ }
+ }
+
+ @Override
+ protected Drawable getContentIcon(@DrawableRes int id) {
+ return getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.on_map_icon_color);
+ }
+
+ private Drawable getActiveIcon(@DrawableRes int id) {
+ return getIcon(id, nightMode ? R.color.osmand_orange : R.color.color_myloc_distance);
+ }
+
+ interface OptionsFragmentListener {
+
+ void snapToRoadOnCLick();
+
+ void addToGpxOnClick();
+
+ void saveAsNewTrackOnClick();
+
+ void addToTheTrackOnClick();
+
+ void clearAllOnClick();
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java
new file mode 100644
index 0000000000..5ea34628da
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java
@@ -0,0 +1,178 @@
+package net.osmand.plus.measurementtool;
+
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.R;
+import net.osmand.plus.Version;
+import net.osmand.plus.base.BottomSheetDialogFragment;
+import net.osmand.plus.helpers.AndroidUiHelper;
+
+public class SaveAsNewTrackBottomSheetDialogFragment extends BottomSheetDialogFragment {
+
+ public final static String TAG = "SaveAsNewTrackBottomSheetDialogFragment";
+
+ private SaveAsNewTrackFragmentListener listener;
+ private boolean nightMode;
+ private boolean portrait;
+
+ public void setListener(SaveAsNewTrackFragmentListener listener) {
+ this.listener = listener;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ portrait = AndroidUiHelper.isOrientationPortrait(getActivity());
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+
+ final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_save_as_new_track_bottom_sheet_dialog, container);
+ if (portrait) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
+ }
+
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ mainView.findViewById(R.id.images_row).setVisibility(View.GONE);
+ } else {
+ final ImageView routePointImage = (ImageView) mainView.findViewById(R.id.route_point_image);
+ ImageView lineImage = (ImageView) mainView.findViewById(R.id.line_image);
+ if (nightMode) {
+ routePointImage.setImageResource(R.drawable.img_help_trip_route_points_night);
+ lineImage.setImageResource(R.drawable.img_help_trip_track_night);
+ } else {
+ routePointImage.setImageResource(R.drawable.img_help_trip_route_points_day);
+ lineImage.setImageResource(R.drawable.img_help_trip_track_day);
+ }
+
+ mainView.findViewById(R.id.line_text).setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ return false;
+ }
+ });
+ lineImage.setOnClickListener(saveAsLineOnClickListener);
+
+ mainView.findViewById(R.id.route_point_text).setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ return false;
+ }
+ });
+ routePointImage.setOnClickListener(saveAsRoutePointOnClickListener);
+ }
+
+ if (nightMode) {
+ ((TextView) mainView.findViewById(R.id.save_as_new_track_title)).setTextColor(getResources().getColor(R.color.ctx_menu_info_text_dark));
+ }
+
+ ((ImageView) mainView.findViewById(R.id.route_point_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_route_points));
+ ((ImageView) mainView.findViewById(R.id.line_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_split_interval));
+
+ mainView.findViewById(R.id.save_as_line_row).setOnClickListener(saveAsLineOnClickListener);
+ mainView.findViewById(R.id.save_as_route_point_row).setOnClickListener(saveAsRoutePointOnClickListener);
+
+ mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+
+ final int screenHeight = AndroidUtils.getScreenHeight(getActivity());
+ final int statusBarHeight = AndroidUtils.getStatusBarHeight(getActivity());
+ final int navBarHeight = AndroidUtils.getNavBarHeight(getActivity());
+
+ mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ final View scrollView = mainView.findViewById(R.id.save_as_new_track_scroll_view);
+ int scrollViewHeight = scrollView.getHeight();
+ int dividerHeight = AndroidUtils.dpToPx(getContext(), 1);
+ int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.measure_distance_bottom_sheet_cancel_button_height);
+ int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight;
+ if (scrollViewHeight > spaceForScrollView) {
+ scrollView.getLayoutParams().height = spaceForScrollView;
+ scrollView.requestLayout();
+ }
+
+ if (!portrait) {
+ if (screenHeight - statusBarHeight - mainView.getHeight()
+ >= AndroidUtils.dpToPx(getActivity(), 8)) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark);
+ } else {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_sides_landscape_light, R.drawable.bg_bottom_sheet_sides_landscape_dark);
+ }
+ }
+
+ ViewTreeObserver obs = mainView.getViewTreeObserver();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ obs.removeOnGlobalLayoutListener(this);
+ } else {
+ obs.removeGlobalOnLayoutListener(this);
+ }
+ }
+ });
+
+ return mainView;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!portrait) {
+ final Window window = getDialog().getWindow();
+ WindowManager.LayoutParams params = window.getAttributes();
+ params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
+ window.setAttributes(params);
+ }
+ }
+
+ @Override
+ protected Drawable getContentIcon(@DrawableRes int id) {
+ return getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.on_map_icon_color);
+ }
+
+ private View.OnClickListener saveAsLineOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.saveAsLineOnClick();
+ }
+ dismiss();
+ }
+ };
+
+ private View.OnClickListener saveAsRoutePointOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.saveAsRoutePointOnClick();
+ }
+ dismiss();
+ }
+ };
+
+ interface SaveAsNewTrackFragmentListener {
+
+ void saveAsRoutePointOnClick();
+
+ void saveAsLineOnClick();
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java
new file mode 100644
index 0000000000..dbca650225
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java
@@ -0,0 +1,227 @@
+package net.osmand.plus.measurementtool;
+
+import android.content.DialogInterface;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import net.osmand.AndroidUtils;
+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.plus.activities.TrackActivity;
+import net.osmand.plus.base.BottomSheetDialogFragment;
+import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.util.MapUtils;
+
+import java.util.List;
+
+public class SelectedPointBottomSheetDialogFragment extends BottomSheetDialogFragment {
+
+ public final static String TAG = "SelectedPointBottomSheetDialogFragment";
+
+ private SelectedPointFragmentListener listener;
+ private boolean nightMode;
+ private boolean portrait;
+ private NewGpxData.ActionType actionType;
+
+ public void setListener(SelectedPointFragmentListener listener) {
+ this.listener = listener;
+ }
+
+ public void setActionType(NewGpxData.ActionType actionType) {
+ this.actionType = actionType;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final MapActivity mapActivity = (MapActivity) getActivity();
+ nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
+ final IconsCache iconsCache = mapActivity.getMyApplication().getIconsCache();
+ final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+
+ final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_selected_menu_bottom_sheet_dialog, null);
+ if (portrait) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
+ }
+
+ int color = nightMode ? R.color.osmand_orange : R.color.color_myloc_distance;
+ ((ImageView) mainView.findViewById(R.id.selected_point_icon)).setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_measure_point, color));
+ ((ImageView) mainView.findViewById(R.id.move_point_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_move_point));
+ ((ImageView) mainView.findViewById(R.id.delete_point_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_remove_dark));
+ ((ImageView) mainView.findViewById(R.id.add_point_after_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_addpoint_above));
+ ((ImageView) mainView.findViewById(R.id.add_point_before_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_addpoint_below));
+
+ mainView.findViewById(R.id.move_point_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.moveOnClick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.delete_point_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.deleteOnClick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.add_point_after_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.addPointAfterOnClick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.add_point_before_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (listener != null) {
+ listener.addPointBeforeOnClick();
+ }
+ dismiss();
+ }
+ });
+ mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+
+ List points = measurementLayer.getMeasurementPoints();
+ int pos = measurementLayer.getSelectedPointPos();
+ WptPt pt = points.get(pos);
+ String pointTitle = pt.name;
+ if (!TextUtils.isEmpty(pointTitle)) {
+ ((TextView) mainView.findViewById(R.id.selected_point_title)).setText(pointTitle);
+ } else {
+ if (actionType == NewGpxData.ActionType.ADD_ROUTE_POINTS) {
+ ((TextView) mainView.findViewById(R.id.selected_point_title)).setText(mapActivity.getString(R.string.route_point) + " - " + (pos + 1));
+ } else {
+ ((TextView) mainView.findViewById(R.id.selected_point_title)).setText(mapActivity.getString(R.string.plugin_distance_point) + " - " + (pos + 1));
+ }
+ }
+ String pointDesc = pt.desc;
+ if (!TextUtils.isEmpty(pointDesc)) {
+ ((TextView) mainView.findViewById(R.id.selected_point_distance)).setText(pointDesc);
+ } else {
+ if (pos < 1) {
+ ((TextView) mainView.findViewById(R.id.selected_point_distance)).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);
+ }
+ ((TextView) mainView.findViewById(R.id.selected_point_distance)).setText(OsmAndFormatter.getFormattedDistance(dist, mapActivity.getMyApplication()));
+ }
+ }
+
+ final int screenHeight = AndroidUtils.getScreenHeight(getActivity());
+ final int statusBarHeight = AndroidUtils.getStatusBarHeight(getActivity());
+ final int navBarHeight = AndroidUtils.getNavBarHeight(getActivity());
+
+ mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ final View scrollView = mainView.findViewById(R.id.selected_point_options_scroll_view);
+ int scrollViewHeight = scrollView.getHeight();
+ int dividerHeight = AndroidUtils.dpToPx(getContext(), 1);
+ int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.measure_distance_bottom_sheet_cancel_button_height);
+ int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight;
+ if (scrollViewHeight > spaceForScrollView) {
+ scrollView.getLayoutParams().height = spaceForScrollView;
+ scrollView.requestLayout();
+ }
+
+ if (!portrait) {
+ if (screenHeight - statusBarHeight - mainView.getHeight()
+ >= AndroidUtils.dpToPx(getActivity(), 8)) {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark);
+ } else {
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ R.drawable.bg_bottom_sheet_sides_landscape_light, R.drawable.bg_bottom_sheet_sides_landscape_dark);
+ }
+ }
+
+ ViewTreeObserver obs = mainView.getViewTreeObserver();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ obs.removeOnGlobalLayoutListener(this);
+ } else {
+ obs.removeGlobalOnLayoutListener(this);
+ }
+ }
+ });
+
+ return mainView;
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!portrait) {
+ final Window window = getDialog().getWindow();
+ WindowManager.LayoutParams params = window.getAttributes();
+ params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
+ window.setAttributes(params);
+ }
+ }
+
+ @Override
+ protected Drawable getContentIcon(@DrawableRes int id) {
+ return getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.on_map_icon_color);
+ }
+
+ @Override
+ public void dismiss() {
+ if (listener != null) {
+ listener.onCloseMenu();
+ }
+ super.dismiss();
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (listener != null) {
+ listener.onCloseMenu();
+ }
+ super.onCancel(dialog);
+ }
+
+ interface SelectedPointFragmentListener {
+
+ void moveOnClick();
+
+ void deleteOnClick();
+
+ void addPointAfterOnClick();
+
+ void addPointBeforeOnClick();
+
+ void onCloseMenu();
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SnapToRoadBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SnapToRoadBottomSheetDialogFragment.java
new file mode 100644
index 0000000000..9b8084ad99
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/SnapToRoadBottomSheetDialogFragment.java
@@ -0,0 +1,144 @@
+package net.osmand.plus.measurementtool;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.design.widget.BottomSheetBehavior;
+import android.support.design.widget.BottomSheetDialog;
+import android.support.v4.content.ContextCompat;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.ApplicationMode;
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.OsmandSettings;
+import net.osmand.plus.R;
+import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.helpers.AndroidUiHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SnapToRoadBottomSheetDialogFragment extends android.support.design.widget.BottomSheetDialogFragment {
+
+ public static final String TAG = "SnapToRoadBottomSheetDialogFragment";
+
+ private SnapToRoadFragmentListener listener;
+ private boolean nightMode;
+ private boolean portrait;
+ private boolean snapToRoadEnabled;
+
+ public void setListener(SnapToRoadFragmentListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void setupDialog(Dialog dialog, int style) {
+ super.setupDialog(dialog, style);
+
+ nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ portrait = AndroidUiHelper.isOrientationPortrait(getActivity());
+ final OsmandSettings settings = getMyApplication().getSettings();
+ final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+
+ final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_snap_to_road_bottom_sheet_dialog, null);
+
+ AndroidUtils.setBackground(getActivity(), mainView, nightMode,
+ portrait ? R.drawable.bg_bottom_menu_light : R.drawable.bg_bottom_sheet_topsides_landscape_light,
+ portrait ? R.drawable.bg_bottom_menu_dark : R.drawable.bg_bottom_sheet_topsides_landscape_dark);
+
+ mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+
+ if (nightMode) {
+ ((TextView) mainView.findViewById(R.id.choose_navigation_title))
+ .setTextColor(ContextCompat.getColor(getActivity(), R.color.ctx_menu_info_text_dark));
+ }
+
+ LinearLayout container = (LinearLayout) mainView.findViewById(R.id.navigation_types_container);
+ final List modes = new ArrayList<>(ApplicationMode.values(settings));
+ modes.remove(ApplicationMode.DEFAULT);
+
+ View.OnClickListener onClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ snapToRoadEnabled = true;
+ if (listener != null) {
+ listener.onApplicationModeItemClick(modes.get((int) view.getTag()));
+ }
+ dismiss();
+ }
+ };
+
+ for (int i = 0; i < modes.size(); i++) {
+ ApplicationMode mode = modes.get(i);
+ View row = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.list_item_icon_and_title, null);
+ ((ImageView) row.findViewById(R.id.icon)).setImageDrawable(getContentIcon(mode.getSmallIconDark()));
+ ((TextView) row.findViewById(R.id.title)).setText(mode.toHumanString(getContext()));
+ row.setOnClickListener(onClickListener);
+ row.setTag(i);
+ container.addView(row);
+ }
+
+ if (!portrait) {
+ dialog.setOnShowListener(new DialogInterface.OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialogInterface) {
+ BottomSheetDialog dialog = (BottomSheetDialog) dialogInterface;
+ FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
+ BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
+ }
+ });
+ }
+
+ dialog.setContentView(mainView);
+ ((View) mainView.getParent()).setBackgroundResource(0);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!portrait) {
+ final Window window = getDialog().getWindow();
+ WindowManager.LayoutParams params = window.getAttributes();
+ params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
+ window.setAttributes(params);
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ if (listener != null) {
+ listener.onDestroyView(snapToRoadEnabled);
+ }
+ super.onDestroyView();
+ }
+
+ private OsmandApplication getMyApplication() {
+ return ((MapActivity) getActivity()).getMyApplication();
+ }
+
+ private Drawable getContentIcon(@DrawableRes int id) {
+ return getMyApplication().getIconsCache()
+ .getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.on_map_icon_color);
+ }
+
+ interface SnapToRoadFragmentListener {
+
+ void onDestroyView(boolean snapToRoadEnabled);
+
+ void onApplicationModeItemClick(ApplicationMode mode);
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolAdapter.java b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolAdapter.java
new file mode 100644
index 0000000000..f5ed512090
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolAdapter.java
@@ -0,0 +1,181 @@
+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.text.TextUtils;
+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.plus.measurementtool.NewGpxData;
+import net.osmand.util.MapUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+public class MeasurementToolAdapter extends RecyclerView.Adapter
+ implements MeasurementToolItemTouchHelperCallback.ItemTouchHelperAdapter {
+
+ private final MapActivity mapActivity;
+ private final List points;
+ private MeasurementAdapterListener listener;
+ private boolean nightMode;
+ private NewGpxData.ActionType actionType;
+
+ public MeasurementToolAdapter(MapActivity mapActivity, List points, NewGpxData.ActionType actionType) {
+ this.mapActivity = mapActivity;
+ this.points = points;
+ this.actionType = actionType;
+ }
+
+ 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);
+ 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.getIcon(R.drawable.ic_action_measure_point,
+ nightMode ? R.color.ctx_menu_info_text_dark : R.color.icon_color));
+ if (nightMode) {
+ holder.title.setTextColor(mapActivity.getMyApplication().getResources().getColor(R.color.primary_text_dark));
+ }
+ WptPt pt = points.get(pos);
+ String pointTitle = pt.name;
+ if (!TextUtils.isEmpty(pointTitle)) {
+ holder.title.setText(pointTitle);
+ } else {
+ if (actionType == NewGpxData.ActionType.ADD_ROUTE_POINTS) {
+ holder.title.setText(mapActivity.getString(R.string.route_point) + " - " + (pos + 1));
+ } else {
+ holder.title.setText(mapActivity.getString(R.string.plugin_distance_point) + " - " + (pos + 1));
+ }
+ }
+ String pointDesc = pt.desc;
+ if (!TextUtils.isEmpty(pointDesc)) {
+ holder.descr.setText(pointDesc);
+ } else {
+ 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()));
+ }
+ }
+ if (actionType == NewGpxData.ActionType.EDIT_SEGMENT) {
+ double elevation = pt.ele;
+ if (!Double.isNaN(elevation)) {
+ holder.elevation.setText(mapActivity.getString(R.string.measurement_tool_altitude, OsmAndFormatter.getFormattedAlt(elevation, mapActivity.getMyApplication())));
+ } else {
+ holder.elevation.setText("");
+ }
+ float speed = (float) pt.speed;
+ if (speed != 0) {
+ holder.speed.setText(mapActivity.getString(R.string.measurement_tool_speed, OsmAndFormatter.getFormattedSpeed(speed, mapActivity.getMyApplication())));
+ } else {
+ holder.speed.setText("");
+ }
+ }
+ holder.deleteBtn.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_remove_dark,
+ nightMode ? R.color.ctx_menu_info_text_dark : R.color.icon_color));
+ 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 TextView elevation;
+ final TextView speed;
+ 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);
+ elevation = (TextView) view.findViewById(R.id.measure_point_ele);
+ speed = (TextView) view.findViewById(R.id.measure_point_speed);
+ 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);
+ }
+}
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolItemTouchHelperCallback.java b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolItemTouchHelperCallback.java
new file mode 100644
index 0000000000..5c5c4d1e7c
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/adapter/MeasurementToolItemTouchHelperCallback.java
@@ -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);
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/AddPointCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/AddPointCommand.java
new file mode 100644
index 0000000000..1d4582dc17
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/AddPointCommand.java
@@ -0,0 +1,52 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+public class AddPointCommand extends MeasurementModeCommand {
+
+ private final int position;
+ private WptPt point;
+ private boolean center;
+
+ public AddPointCommand(MeasurementToolLayer measurementLayer, int position) {
+ this.measurementLayer = measurementLayer;
+ this.center = true;
+ this.position = position;
+ }
+
+ public AddPointCommand(MeasurementToolLayer measurementLayer, boolean center) {
+ this.measurementLayer = measurementLayer;
+ this.center = center;
+ position = measurementLayer.getMeasurementPoints().size();
+ }
+
+ @Override
+ public boolean execute() {
+ if (center) {
+ point = measurementLayer.addCenterPoint(position);
+ } else {
+ point = measurementLayer.addPoint(position);
+ }
+ measurementLayer.refreshMap();
+ return point != null;
+ }
+
+ @Override
+ public void undo() {
+ measurementLayer.getMeasurementPoints().remove(position);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ public void redo() {
+ measurementLayer.getMeasurementPoints().add(position, point);
+ measurementLayer.refreshMap();
+ measurementLayer.moveMapToPoint(position);
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.ADD_POINT;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/ClearPointsCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/ClearPointsCommand.java
new file mode 100644
index 0000000000..f80340def6
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/ClearPointsCommand.java
@@ -0,0 +1,48 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class ClearPointsCommand extends MeasurementModeCommand {
+
+ private List points;
+ private List snappedToRoadPoints;
+
+ public ClearPointsCommand(MeasurementToolLayer measurementLayer) {
+ this.measurementLayer = measurementLayer;
+ }
+
+ @Override
+ public boolean execute() {
+ List pts = measurementLayer.getMeasurementPoints();
+ List snappedPts = measurementLayer.getSnappedToRoadPoints();
+ points = new LinkedList<>(pts);
+ snappedToRoadPoints = new LinkedList<>(snappedPts);
+ pts.clear();
+ snappedPts.clear();
+ measurementLayer.refreshMap();
+ return true;
+ }
+
+ @Override
+ public void undo() {
+ measurementLayer.getMeasurementPoints().addAll(points);
+ measurementLayer.getSnappedToRoadPoints().addAll(snappedToRoadPoints);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ public void redo() {
+ measurementLayer.getMeasurementPoints().clear();
+ measurementLayer.getSnappedToRoadPoints().clear();
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.CLEAR_POINTS;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/Command.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/Command.java
new file mode 100644
index 0000000000..cb09b3fffc
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/Command.java
@@ -0,0 +1,10 @@
+package net.osmand.plus.measurementtool.command;
+
+public interface Command {
+
+ boolean execute();
+
+ void undo();
+
+ void redo();
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementCommandManager.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementCommandManager.java
new file mode 100644
index 0000000000..4261271adb
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementCommandManager.java
@@ -0,0 +1,63 @@
+package net.osmand.plus.measurementtool.command;
+
+import android.support.annotation.Nullable;
+
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+import net.osmand.plus.measurementtool.command.MeasurementModeCommand.MeasurementCommandType;
+
+import java.util.Deque;
+import java.util.LinkedList;
+
+public class MeasurementCommandManager {
+
+ private final Deque undoCommands = new LinkedList<>();
+ private final Deque redoCommands = new LinkedList<>();
+
+ public boolean canUndo() {
+ return undoCommands.size() > 0;
+ }
+
+ public boolean canRedo() {
+ return redoCommands.size() > 0;
+ }
+
+ public boolean execute(MeasurementModeCommand command) {
+ if (command.execute()) {
+ undoCommands.push(command);
+ redoCommands.clear();
+ return true;
+ }
+ return false;
+ }
+
+ @Nullable
+ public MeasurementCommandType undo() {
+ if (canUndo()) {
+ MeasurementModeCommand command = undoCommands.pop();
+ redoCommands.push(command);
+ command.undo();
+ return command.getType();
+ }
+ return null;
+ }
+
+ @Nullable
+ public MeasurementCommandType redo() {
+ if (canRedo()) {
+ MeasurementModeCommand command = redoCommands.pop();
+ undoCommands.push(command);
+ command.redo();
+ return command.getType();
+ }
+ return null;
+ }
+
+ public void resetMeasurementLayer(MeasurementToolLayer layer) {
+ for (MeasurementModeCommand command : undoCommands) {
+ command.setMeasurementLayer(layer);
+ }
+ for (MeasurementModeCommand command : redoCommands) {
+ command.setMeasurementLayer(layer);
+ }
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java
new file mode 100644
index 0000000000..f0fb2133ea
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java
@@ -0,0 +1,23 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+public abstract class MeasurementModeCommand implements Command {
+
+ MeasurementToolLayer measurementLayer;
+
+ void setMeasurementLayer(MeasurementToolLayer layer) {
+ this.measurementLayer = layer;
+ }
+
+ abstract MeasurementCommandType getType();
+
+ public enum MeasurementCommandType {
+ ADD_POINT,
+ CLEAR_POINTS,
+ MOVE_POINT,
+ REMOVE_POINT,
+ REORDER_POINT,
+ SNAP_TO_ROAD
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/MovePointCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/MovePointCommand.java
new file mode 100644
index 0000000000..242f981ea1
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/MovePointCommand.java
@@ -0,0 +1,42 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+public class MovePointCommand extends MeasurementModeCommand {
+
+ 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() {
+ measurementLayer.getMeasurementPoints().remove(position);
+ measurementLayer.getMeasurementPoints().add(position, oldPoint);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ public void redo() {
+ measurementLayer.getMeasurementPoints().remove(position);
+ measurementLayer.getMeasurementPoints().add(position, newPoint);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.MOVE_POINT;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/RemovePointCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/RemovePointCommand.java
new file mode 100644
index 0000000000..380e55e331
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/RemovePointCommand.java
@@ -0,0 +1,40 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+public class RemovePointCommand extends MeasurementModeCommand {
+
+ 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.getMeasurementPoints().remove(position);
+ measurementLayer.refreshMap();
+ return true;
+ }
+
+ @Override
+ public void undo() {
+ measurementLayer.getMeasurementPoints().add(position, point);
+ measurementLayer.refreshMap();
+ measurementLayer.moveMapToPoint(position);
+ }
+
+ @Override
+ public void redo() {
+ measurementLayer.getMeasurementPoints().remove(position);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.REMOVE_POINT;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/ReorderPointCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/ReorderPointCommand.java
new file mode 100644
index 0000000000..69c9218a28
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/ReorderPointCommand.java
@@ -0,0 +1,42 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+import java.util.Collections;
+
+public class ReorderPointCommand extends MeasurementModeCommand {
+
+ 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();
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.REORDER_POINT;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/SnapToRoadCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/SnapToRoadCommand.java
new file mode 100644
index 0000000000..ceb4d1bdd2
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/SnapToRoadCommand.java
@@ -0,0 +1,41 @@
+package net.osmand.plus.measurementtool.command;
+
+import net.osmand.plus.GPXUtilities.WptPt;
+import net.osmand.plus.measurementtool.MeasurementToolLayer;
+
+import java.util.List;
+
+public class SnapToRoadCommand extends MeasurementModeCommand {
+
+ private List snappedPoints;
+
+ public SnapToRoadCommand(MeasurementToolLayer measurementLayer, List points) {
+ this.measurementLayer = measurementLayer;
+ this.snappedPoints = points;
+ }
+
+ @Override
+ public boolean execute() {
+ measurementLayer.getSnappedToRoadPoints().clear();
+ measurementLayer.getSnappedToRoadPoints().addAll(snappedPoints);
+ measurementLayer.refreshMap();
+ return true;
+ }
+
+ @Override
+ public void undo() {
+ measurementLayer.getSnappedToRoadPoints().clear();
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ public void redo() {
+ measurementLayer.getSnappedToRoadPoints().addAll(snappedPoints);
+ measurementLayer.refreshMap();
+ }
+
+ @Override
+ MeasurementCommandType getType() {
+ return MeasurementCommandType.SNAP_TO_ROAD;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java
index 3fbf92947e..95dc1638b4 100644
--- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java
+++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java
@@ -124,6 +124,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
private View currentGpxView;
private View footerView;
private boolean importing = false;
+ private View emptyView;
@Override
public void onAttach(Context activity) {
@@ -327,6 +328,16 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
}
footerView = inflater.inflate(R.layout.list_shadow_footer, null, false);
listView.addFooterView(footerView);
+ 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();
+ }
+ });
if (this.adapter != null) {
listView.setAdapter(this.adapter);
}
@@ -1597,6 +1608,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
@Override
protected void onPostExecute(Void aVoid) {
asyncProcessor = null;
+ listView.setEmptyView(emptyView);
}
}
diff --git a/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java b/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java
index 54182345a1..f58fb91504 100644
--- a/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java
+++ b/OsmAnd/src/net/osmand/plus/myplaces/FavoritesActivity.java
@@ -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 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 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 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;
}
diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java
index d4bd49e319..54ceae5c4c 100644
--- a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java
+++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java
@@ -57,7 +57,7 @@ import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.FavoriteImageDrawable;
import net.osmand.plus.base.OsmandExpandableListFragment;
import net.osmand.plus.dialogs.DirectionsDialogs;
-import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
+import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.util.Algorithms;
import java.io.File;
@@ -99,6 +99,9 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
private View waypointTextLayout;
private FloatingActionButton routePointFab;
private View routePointTextLayout;
+ private FloatingActionButton lineFab;
+ private View lineTextLayout;
+ private View overlayView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -114,6 +117,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
public void onScrollStateChanged(AbsListView absListView, int i) {
if (i == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
if (menuOpened) {
+ hideTransparentOverlay();
closeMenu();
}
}
@@ -128,43 +132,74 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
: R.color.ctx_menu_info_view_bg_dark));
}
+ private void hideTransparentOverlay() {
+ overlayView.setVisibility(View.GONE);
+ }
+
+ private void showTransparentOverlay() {
+ overlayView.setVisibility(View.VISIBLE);
+ }
+
+ private View.OnClickListener onFabClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.overlay_view:
+ hideTransparentOverlay();
+ closeMenu();
+ break;
+ case R.id.menu_fab:
+ if (menuOpened) {
+ hideTransparentOverlay();
+ closeMenu();
+ } else {
+ showTransparentOverlay();
+ openMenu();
+ }
+ break;
+ case R.id.waypoint_text_layout:
+ 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_text_layout:
+ case R.id.route_fab:
+ addNewGpxData(NewGpxData.ActionType.ADD_ROUTE_POINTS);
+ break;
+ case R.id.line_text_layout:
+ case R.id.line_fab:
+ addNewGpxData(NewGpxData.ActionType.ADD_SEGMENT);
+ break;
+ }
+ }
+ };
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.points_tree, container, false);
+ View view = inflater.inflate(R.layout.track_points_tree, container, false);
ExpandableListView listView = (ExpandableListView) view.findViewById(android.R.id.list);
setHasOptionsMenu(true);
+ overlayView = view.findViewById(R.id.overlay_view);
+ overlayView.setOnClickListener(onFabClickListener);
+
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);
+ waypointTextLayout.setOnClickListener(onFabClickListener);
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);
+ routePointTextLayout.setOnClickListener(onFabClickListener);
+
+ lineFab = (FloatingActionButton) view.findViewById(R.id.line_fab);
+ lineFab.setOnClickListener(onFabClickListener);
+ lineTextLayout = view.findViewById(R.id.line_text_layout);
+ lineTextLayout.setOnClickListener(onFabClickListener);
TextView tv = new TextView(getActivity());
tv.setText(R.string.none_selected_gpx);
@@ -178,22 +213,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 addNewGpxData(NewGpxData.ActionType actionType) {
+ getTrackActivity().addNewGpxData(actionType);
}
private void openMenu() {
@@ -202,6 +226,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 +237,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;
}
diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java
index 177494d1eb..a84e07a802 100644
--- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java
+++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java
@@ -1,6 +1,7 @@
package net.osmand.plus.myplaces;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -17,10 +18,12 @@ 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;
import android.support.v4.view.ViewCompat;
+import android.support.v7.app.AlertDialog;
import android.support.v7.widget.ListPopupWindow;
import android.support.v7.widget.SwitchCompat;
import android.util.DisplayMetrics;
@@ -34,6 +37,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;
@@ -62,7 +66,6 @@ import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
-import net.osmand.plus.GPXUtilities.Route;
import net.osmand.plus.GPXUtilities.Track;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
@@ -86,6 +89,7 @@ import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
+import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.resources.AsyncLoadingThread;
import net.osmand.plus.resources.ResourceManager;
@@ -95,6 +99,7 @@ import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface;
+import net.osmand.plus.widgets.IconPopupMenu;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
@@ -134,11 +139,22 @@ public class TrackSegmentFragment extends OsmAndListFragment {
private int defPointColor;
private Paint paintIcon;
private Bitmap pointSmall;
+ private SwitchCompat vis;
private ImageView imageView;
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;
+ private View overlayView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -149,16 +165,72 @@ 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) {
+ hideTransparentOverlay();
+ 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 void hideTransparentOverlay() {
+ overlayView.setVisibility(View.GONE);
+ }
+
+ private void showTransparentOverlay() {
+ overlayView.setVisibility(View.VISIBLE);
+ }
+
+ private View.OnClickListener onFabClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.overlay_view:
+ hideTransparentOverlay();
+ closeMenu();
+ break;
+ case R.id.menu_fab:
+ if (menuOpened) {
+ hideTransparentOverlay();
+ closeMenu();
+ } else {
+ showTransparentOverlay();
+ openMenu();
+ }
+ break;
+ case R.id.waypoint_text_layout:
+ 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_text_layout:
+ case R.id.route_fab:
+ addNewGpxData(NewGpxData.ActionType.ADD_ROUTE_POINTS);
+ break;
+ case R.id.line_text_layout:
+ case R.id.line_fab:
+ addNewGpxData(NewGpxData.ActionType.ADD_SEGMENT);
+ 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 +241,27 @@ public class TrackSegmentFragment extends OsmAndListFragment {
tv.setTextSize(24);
listView.setEmptyView(tv);
+ overlayView = view.findViewById(R.id.overlay_view);
+ overlayView.setOnClickListener(onFabClickListener);
+
+ 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);
+ waypointTextLayout.setOnClickListener(onFabClickListener);
+
+ routePointFab = (FloatingActionButton) view.findViewById(R.id.route_fab);
+ routePointFab.setOnClickListener(onFabClickListener);
+ routePointTextLayout = view.findViewById(R.id.route_text_layout);
+ routePointTextLayout.setOnClickListener(onFabClickListener);
+
+ lineFab = (FloatingActionButton) view.findViewById(R.id.line_fab);
+ lineFab.setOnClickListener(onFabClickListener);
+ lineTextLayout = view.findViewById(R.id.line_text_layout);
+ lineTextLayout.setOnClickListener(onFabClickListener);
+
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
@@ -182,11 +275,50 @@ 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 addNewGpxData(NewGpxData.ActionType actionType) {
+ getTrackActivity().addNewGpxData(actionType);
+ }
+
+ private void addNewGpxData(NewGpxData.ActionType actionType, TrkSegment segment) {
+ getTrackActivity().addNewGpxData(actionType, segment);
+ }
+
+ 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();
}
@@ -312,7 +444,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
final View divider = headerView.findViewById(R.id.divider);
final View splitIntervalView = headerView.findViewById(R.id.split_interval_view);
final View colorView = headerView.findViewById(R.id.color_view);
- final SwitchCompat vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle);
+ vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle);
final ProgressBar progressBar = (ProgressBar) headerView.findViewById(R.id.mapLoadProgress);
final boolean selected = getGpx() != null &&
((getGpx().showCurrentTrack && app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null) ||
@@ -598,56 +730,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 getOriginalGroups() {
@@ -1073,6 +1156,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,107 +1175,117 @@ 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));
+ }
+ }
+ }
+ }
+ });
}
}
});
- IconsCache ic = app.getIconsCache();
+ final IconsCache ic = app.getIconsCache();
switch (tabType) {
case GPX_TAB_ITEM_GENERAL:
if (analysis != null) {
@@ -1254,6 +1348,55 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
});
}
+ if (!gpxItem.group.getTrack().generalTrack) {
+ ((ImageView) view.findViewById(R.id.overflow_menu)).setImageDrawable(ic.getThemedIcon(R.drawable.ic_overflow_menu_dark));
+ view.findViewById(R.id.overflow_menu).setVisibility(View.VISIBLE);
+ view.findViewById(R.id.overflow_menu).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ IconPopupMenu popupMenu = new IconPopupMenu(getTrackActivity(), view.findViewById(R.id.overflow_menu));
+ Menu menu = popupMenu.getMenu();
+ popupMenu.getMenuInflater().inflate(R.menu.track_segment_menu, menu);
+ menu.findItem(R.id.action_edit).setIcon(ic.getThemedIcon(R.drawable.ic_action_edit_dark));
+ menu.findItem(R.id.action_delete).setIcon(ic.getThemedIcon(R.drawable.ic_action_remove_dark));
+ popupMenu.setOnMenuItemClickListener(new IconPopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_edit:
+ TrkSegment segment = getTrkSegment();
+ if (segment != null) {
+ addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
+ }
+ return true;
+ case R.id.action_delete:
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(R.string.recording_delete_confirm);
+ builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (deleteSegment()) {
+ GPXFile gpx = getGpx();
+ if (gpx != null) {
+ SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, vis.isChecked(), false);
+ new SaveGpxAsyncTask(gpx, vis.isChecked() ? sf : null).execute();
+ }
+ }
+ }
+ });
+ builder.setNegativeButton(R.string.shared_string_cancel, null);
+ builder.show();
+ return true;
+ }
+ return false;
+ }
+ });
+ popupMenu.show();
+ }
+ });
+ } else {
+ view.findViewById(R.id.overflow_menu).setVisibility(View.GONE);
+ }
break;
case GPX_TAB_ITEM_ALTITUDE:
@@ -1308,6 +1451,46 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
});
}
+ if (!gpxItem.group.getTrack().generalTrack) {
+ ((ImageView) view.findViewById(R.id.overflow_menu)).setImageDrawable(ic.getThemedIcon(R.drawable.ic_overflow_menu_dark));
+ view.findViewById(R.id.overflow_menu).setVisibility(View.VISIBLE);
+ view.findViewById(R.id.overflow_menu).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ IconPopupMenu popupMenu = new IconPopupMenu(getTrackActivity(), view.findViewById(R.id.overflow_menu));
+ Menu menu = popupMenu.getMenu();
+ popupMenu.getMenuInflater().inflate(R.menu.track_segment_menu, menu);
+ menu.findItem(R.id.action_edit).setIcon(ic.getThemedIcon(R.drawable.ic_action_edit_dark));
+ menu.findItem(R.id.action_delete).setIcon(ic.getThemedIcon(R.drawable.ic_action_remove_dark));
+ popupMenu.setOnMenuItemClickListener(new IconPopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_edit:
+ TrkSegment segment = getTrkSegment();
+ if (segment != null) {
+ addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
+ }
+ return true;
+ case R.id.action_delete:
+ if (deleteSegment()) {
+ GPXFile gpx = getGpx();
+ if (gpx != null) {
+ SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, vis.isChecked(), false);
+ new SaveGpxAsyncTask(gpx, vis.isChecked() ? sf : null).execute();
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ });
+ popupMenu.show();
+ }
+ });
+ } else {
+ view.findViewById(R.id.overflow_menu).setVisibility(View.GONE);
+ }
break;
case GPX_TAB_ITEM_SPEED:
@@ -1361,6 +1544,47 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
});
}
+ if (!gpxItem.group.getTrack().generalTrack) {
+ ((ImageView) view.findViewById(R.id.overflow_menu)).setImageDrawable(ic.getThemedIcon(R.drawable.ic_overflow_menu_dark));
+ view.findViewById(R.id.overflow_menu).setVisibility(View.VISIBLE);
+ view.findViewById(R.id.overflow_menu).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ IconPopupMenu popupMenu = new IconPopupMenu(getTrackActivity(), view.findViewById(R.id.overflow_menu));
+ Menu menu = popupMenu.getMenu();
+ popupMenu.getMenuInflater().inflate(R.menu.track_segment_menu, menu);
+ menu.findItem(R.id.action_edit).setIcon(ic.getThemedIcon(R.drawable.ic_action_edit_dark));
+ menu.findItem(R.id.action_delete).setIcon(ic.getThemedIcon(R.drawable.ic_action_remove_dark));
+ popupMenu.setOnMenuItemClickListener(new IconPopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_edit:
+ TrkSegment segment = getTrkSegment();
+ if (segment != null) {
+ addNewGpxData(NewGpxData.ActionType.EDIT_SEGMENT, segment);
+ }
+ return true;
+ case R.id.action_delete:
+ if (deleteSegment()) {
+ GPXFile gpx = getGpx();
+ if (gpx != null) {
+ SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, vis.isChecked(), false);
+ new SaveGpxAsyncTask(gpx, vis.isChecked() ? sf : null).execute();
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ });
+ popupMenu.show();
+ }
+ });
+ } else {
+ view.findViewById(R.id.overflow_menu).setVisibility(View.GONE);
+ }
+
break;
}
}
@@ -1371,6 +1595,17 @@ public class TrackSegmentFragment extends OsmAndListFragment {
return view;
}
+ private boolean deleteSegment() {
+ TrkSegment segment = getTrkSegment();
+ if (segment != null) {
+ GPXFile gpx = getGpx();
+ if (gpx != null) {
+ return gpx.removeTrkSegment(segment);
+ }
+ }
+ return false;
+ }
+
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
views.remove(position);
@@ -1463,6 +1698,17 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
}
+ private TrkSegment getTrkSegment() {
+ for (Track t : gpxItem.group.getGpx().tracks) {
+ for (TrkSegment s : t.segments) {
+ if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
+ return s;
+ }
+ }
+ }
+ return null;
+ }
+
void openAnalyzeOnMap(GPXTabItemType tabType) {
LatLon location = null;
WptPt wpt = null;
@@ -1535,6 +1781,42 @@ public class TrackSegmentFragment extends OsmAndListFragment {
getTrackActivity().getSlidingTabLayout().setVisibility(View.GONE);
}
+ private class SaveGpxAsyncTask extends AsyncTask {
+ private final GPXFile mGpx;
+ private final SelectedGpxFile mSelectedGpx;
+ private final TrackActivity mActivity;
+
+ SaveGpxAsyncTask(GPXFile gpx, SelectedGpxFile selectedGpxFile) {
+ mGpx = gpx;
+ mActivity = getTrackActivity();
+ mSelectedGpx = selectedGpxFile;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ mActivity.setSupportProgressBarIndeterminateVisibility(true);
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ GPXUtilities.writeGpxFile(new File(mGpx.path), mGpx, app);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ if (mSelectedGpx != null) {
+ List groups = getDisplayGroups();
+ mSelectedGpx.setDisplayGroups(groups);
+ mSelectedGpx.processPoints();
+ }
+ updateContent();
+ if (!mActivity.isFinishing()) {
+ mActivity.setSupportProgressBarIndeterminateVisibility(false);
+ }
+ }
+ }
+
private class SplitTrackAsyncTask extends AsyncTask {
@Nullable
private final SelectedGpxFile mSelectedGpxFile;
diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java
index 88e5038851..1a5654ac7d 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java
@@ -1,15 +1,16 @@
package net.osmand.plus.routing;
-import java.util.List;
-
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.routing.RouteProvider.GPXRouteParams;
import net.osmand.plus.routing.RouteProvider.RouteService;
+import net.osmand.plus.routing.RouteProvider.SnapToRoadParams;
import net.osmand.router.RouteCalculationProgress;
+import java.util.List;
+
public class RouteCalculationParams {
public Location start;
@@ -21,6 +22,7 @@ public class RouteCalculationParams {
public ApplicationMode mode;
public RouteService type;
public GPXRouteParams gpxRoute;
+ public SnapToRoadParams snapToRoadParams;
public RouteCalculationResult previousToRecalculate;
public boolean onlyStartPointChanged;
public boolean fast;
diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
index abfdbc7f80..1cb3acc763 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java
@@ -44,11 +44,13 @@ import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.Version;
import net.osmand.plus.activities.SettingsNavigationActivity;
import net.osmand.plus.render.NativeOsmandLibrary;
+import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.GeneralRouter.RoutingParameter;
import net.osmand.router.GeneralRouter.RoutingParameterType;
import net.osmand.router.PrecalculatedRouteDirection;
+import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
import net.osmand.router.RouteSegmentResult;
@@ -282,6 +284,19 @@ public class RouteProvider {
}
}
+ public static class SnapToRoadParams {
+
+ public ApplicationMode applicationMode;
+ public RouteCalculationProgress calculationProgress;
+ public RouteCalculationProgressCallback calculationProgressCallback;
+ public SnapToRoadListener listener;
+ public List points;
+
+ public interface SnapToRoadListener {
+ void onSnapToRoadDone();
+ }
+ }
+
private static Location createLocation(WptPt pt){
Location loc = new Location("OsmandRouteProvider");
loc.setLatitude(pt.lat);
@@ -754,6 +769,9 @@ public class RouteProvider {
paramsR.put(key, vl);
}
}
+ if (params.snapToRoadParams != null) {
+ paramsR.put(GeneralRouter.ALLOW_PRIVATE, "true");
+ }
float mb = (1 << 20);
Runtime rt = Runtime.getRuntime();
// make visible
diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
index f1201150a7..dcbad72858 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
@@ -19,6 +19,7 @@ import net.osmand.plus.notifications.OsmandNotification.NotificationType;
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder;
import net.osmand.plus.routing.RouteProvider.RouteService;
+import net.osmand.plus.routing.RouteProvider.SnapToRoadParams;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.TurnType;
@@ -33,38 +34,38 @@ import java.util.List;
import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION;
public class RoutingHelper {
-
+
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class);
-
+
public interface IRouteInformationListener {
-
+
void newRouteIsCalculated(boolean newRoute, ValueHolder showToast);
-
+
void routeWasCancelled();
void routeWasFinished();
}
-
+
private static final float POSITION_TOLERANCE = 60;
-
-
+
+
private List> listeners = new LinkedList>();
private OsmandApplication app;
-
+
private boolean isFollowingMode = false;
private boolean isRoutePlanningMode = false;
private boolean isPauseNavigation = false;
-
+
private GPXRouteParamsBuilder currentGPXRoute = null;
private RouteCalculationResult route = new RouteCalculationResult("");
-
+
private LatLon finalLocation;
private List intermediatePoints;
private Location lastProjection;
private Location lastFixedLocation;
-
+
private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3;
private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2*60*1000;
private Thread currentRunningJob;
@@ -73,10 +74,10 @@ public class RoutingHelper {
private String lastRouteCalcErrorShort;
private long recalculateCountInInterval = 0;
private int evalWaitInterval = 0;
-
+
private ApplicationMode mode;
private OsmandSettings settings;
-
+
private RouteProvider provider;
private VoiceRouter voiceRouter;
@@ -101,12 +102,12 @@ public class RoutingHelper {
provider = new RouteProvider();
setAppMode(settings.APPLICATION_MODE.get());
}
-
+
public boolean isFollowingMode() {
return isFollowingMode;
}
-
+
public OsmandApplication getApplication() {
return app;
}
@@ -132,11 +133,11 @@ public class RoutingHelper {
app.startNavigationService(NavigationService.USED_BY_NAVIGATION, 0);
}
}
-
+
public boolean isPauseNavigation() {
return isPauseNavigation;
}
-
+
public void setFollowingMode(boolean follow) {
isFollowingMode = follow;
isPauseNavigation = false;
@@ -151,24 +152,24 @@ public class RoutingHelper {
app.startNavigationService(NavigationService.USED_BY_NAVIGATION, 0);
}
}
-
+
public boolean isRoutePlanningMode() {
return isRoutePlanningMode;
}
-
+
public void setRoutePlanningMode(boolean isRoutePlanningMode) {
this.isRoutePlanningMode = isRoutePlanningMode;
}
-
-
+
+
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List intermediatePoints, Location currentLocation){
RouteCalculationResult previousRoute = route;
clearCurrentRoute(finalLocation, intermediatePoints);
// to update route
setCurrentLocation(currentLocation, false, previousRoute, true);
}
-
+
public synchronized void clearCurrentRoute(LatLon newFinalLocation, List newIntermediatePoints) {
route = new RouteCalculationResult("");
isDeviatedFromRoute = false;
@@ -184,7 +185,7 @@ public class RoutingHelper {
if(l == null) {
it.remove();
} else {
- l.routeWasCancelled();
+ l.routeWasCancelled();
}
}
}
@@ -224,50 +225,50 @@ public class RoutingHelper {
public GPXRouteParamsBuilder getCurrentGPXRoute() {
return currentGPXRoute;
}
-
+
public void setGpxParams(GPXRouteParamsBuilder params) {
currentGPXRoute = params;
- }
-
+ }
+
public List getCurrentCalculatedRoute() {
return route.getImmutableAllLocations();
}
-
+
public void setAppMode(ApplicationMode mode){
this.mode = mode;
voiceRouter.updateAppMode();
}
-
+
public ApplicationMode getAppMode() {
return mode;
}
-
+
public LatLon getFinalLocation() {
return finalLocation;
}
-
+
public List getIntermediatePoints() {
return intermediatePoints;
}
-
+
public boolean isRouteCalculated(){
return route.isCalculated();
}
-
+
public VoiceRouter getVoiceRouter() {
return voiceRouter;
}
-
+
public Location getLastProjection(){
return lastProjection;
}
-
+
public void addListener(IRouteInformationListener l){
listeners.add(new WeakReference(l));
}
-
+
public boolean removeListener(IRouteInformationListener lt){
Iterator> it = listeners.iterator();
while(it.hasNext()) {
@@ -280,14 +281,14 @@ public class RoutingHelper {
}
return false;
}
-
+
public void updateLocation(Location currentLocation) {
if(isFollowingMode() || (settings.getPointToStart() == null && isRoutePlanningMode) ||
app.getLocationProvider().getLocationSimulation().isRouteAnimating()) {
setCurrentLocation(currentLocation, false);
}
}
-
+
public Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation) {
return setCurrentLocation(currentLocation, returnUpdatedLocation, route, false);
}
@@ -301,8 +302,8 @@ public class RoutingHelper {
List routeNodes = route.getImmutableAllLocations();
return getOrthogonalDistance(lastFixedLocation, routeNodes.get(route.currentRoute -1), routeNodes.get(route.currentRoute));
}
-
- private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation,
+
+ private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation,
RouteCalculationResult previousRoute, boolean targetPointsChanged) {
Location locationProjection = currentLocation;
if (finalLocation == null || currentLocation == null) {
@@ -367,7 +368,7 @@ public class RoutingHelper {
voiceRouter.announceOffRoute(distOrth);
}
}
-
+
// calculate projection of current location
if (currentRoute > 0) {
locationProjection = new Location(currentLocation);
@@ -386,8 +387,8 @@ public class RoutingHelper {
}
if (calculateRoute) {
- recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute,
- previousRoute.isCalculated() ? previousRoute : null, false, !targetPointsChanged);
+ recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute,
+ previousRoute.isCalculated() ? previousRoute : null, false, !targetPointsChanged, null);
} else {
Thread job = currentRunningJob;
if(job instanceof RouteRecalculationThread) {
@@ -414,13 +415,13 @@ public class RoutingHelper {
loc.getLongitude(), from.getLatitude(), from.getLongitude(),
to.getLatitude(), to.getLongitude());
}
-
+
private static LatLon getProject(Location loc, Location from, Location to) {
return MapUtils.getProjection(loc.getLatitude(),
loc.getLongitude(), from.getLatitude(), from.getLongitude(),
to.getLatitude(), to.getLongitude());
}
-
+
private static int lookAheadFindMinOrthogonalDistance(Location currentLocation, List routeNodes, int currentRoute, int iterations) {
double newDist;
double dist = Double.POSITIVE_INFINITY;
@@ -444,7 +445,7 @@ public class RoutingHelper {
while (currentRoute + 1 < routeNodes.size()) {
double dist = currentLocation.distanceTo(routeNodes.get(currentRoute));
if(currentRoute > 0) {
- dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1),
+ dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1),
routeNodes.get(currentRoute));
}
boolean processed = false;
@@ -452,7 +453,7 @@ public class RoutingHelper {
// if not then look ahead only 3 in order to catch sharp turns
boolean longDistance = dist >= 250;
int newCurrentRoute = lookAheadFindMinOrthogonalDistance(currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8);
- double newDist = getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute),
+ double newDist = getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute),
routeNodes.get(newCurrentRoute + 1));
if(longDistance) {
if(newDist < dist) {
@@ -496,7 +497,7 @@ public class RoutingHelper {
break;
}
}
-
+
// 2. check if intermediate found
if(route.getIntermediatePointsToPass() > 0
&& route.getDistanceToNextIntermediate(lastFixedLocation) < getArrivalDistance() * 2f && !isRoutePlanningMode) {
@@ -536,7 +537,7 @@ public class RoutingHelper {
//showMessage(app.getString(R.string.arrived_at_destination));
TargetPointsHelper targets = app.getTargetPointsHelper();
TargetPoint tp = targets.getPointToNavigate();
- String description = tp == null ? "" : tp.getOnlyName();
+ String description = tp == null ? "" : tp.getOnlyName();
if(isFollowingMode) {
voiceRouter.arrivedDestinationPoint(description);
}
@@ -564,7 +565,7 @@ public class RoutingHelper {
private float getArrivalDistance() {
return ((float)settings.getApplicationMode().getArrivalDistance()) * settings.ARRIVAL_DISTANCE_FACTOR.get();
}
-
+
private boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) {
if (finalLocation == null || currentLocation == null || !route.isCalculated()) {
@@ -596,9 +597,9 @@ public class RoutingHelper {
}
return isOffRoute;
}
-
+
/**
- * Wrong movement direction is considered when between
+ * Wrong movement direction is considered when between
* current location bearing (determines by 2 last fixed position or provided)
* and bearing from currentLocation to next (current) point
* the difference is more than 60 degrees
@@ -648,11 +649,11 @@ public class RoutingHelper {
evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2);
evalWaitInterval = Math.min(evalWaitInterval, 120000);
}
-
+
}
}
-
+
// trigger voice prompt only if new route is in forward direction
// If route is in wrong direction after one more setLocation it will be recalculated
if (!wrongMovementDirection || newRoute) {
@@ -687,23 +688,23 @@ public class RoutingHelper {
}
});
}
-
+
public int getLeftDistance(){
return route.getDistanceToFinish(lastFixedLocation);
}
-
+
public int getLeftDistanceNextIntermediate() {
return route.getDistanceToNextIntermediate(lastFixedLocation);
}
-
+
public int getLeftTime() {
return route.getLeftTime(lastFixedLocation);
}
-
+
public OsmandSettings getSettings() {
return settings;
}
-
+
public String getGeneralRouteInformation(){
int dist = getLeftDistance();
int hours = getLeftTime() / (60 * 60);
@@ -711,11 +712,11 @@ public class RoutingHelper {
return app.getString(R.string.route_general_information, OsmAndFormatter.getFormattedDistance(dist, app),
hours, minutes);
}
-
+
public Location getLocationFromRouteDirection(RouteDirectionInfo i){
return route.getLocationFromRouteDirection(i);
}
-
+
public synchronized NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, boolean toSpeak){
NextDirectionInfo i = route.getNextRouteDirectionInfo(info, lastProjection, toSpeak);
if(i != null) {
@@ -723,12 +724,12 @@ public class RoutingHelper {
}
return i;
}
-
+
public synchronized float getCurrentMaxSpeed() {
return route.getCurrentMaxSpeed();
}
-
-
+
+
public static String formatStreetName(String name, String ref, String destination, String towards) {
//Hardy, 2016-08-05:
//Now returns: (ref) + ((" ")+name) + ((" ")+"toward "+dest) or ""
@@ -752,14 +753,14 @@ public class RoutingHelper {
return formattedStreetName.replace(";", ", ");
}
-
+
// protected boolean isDistanceLess(float currentSpeed, double dist, double etalon, float defSpeed){
// if(dist < etalon || ((dist / currentSpeed) < (etalon / defSpeed))){
// return true;
// }
// return false;
// }
-
+
public synchronized String getCurrentName(TurnType[] next){
NextDirectionInfo n = getNextRouteDirectionInfo(new NextDirectionInfo(), true);
Location l = lastFixedLocation;
@@ -767,7 +768,7 @@ public class RoutingHelper {
if(l != null && l.hasSpeed()) {
speed = l.getSpeed();
}
- if(n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() &&
+ if(n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() &&
voiceRouter.isDistanceLess(speed, n.distanceTo, voiceRouter.PREPARE_DISTANCE * 0.75f, 0f)) {
String nm = n.directionInfo.getStreetName();
String rf = n.directionInfo.getRef();
@@ -781,7 +782,7 @@ public class RoutingHelper {
if(rs != null) {
String nm = rs.getObject().getName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get());
String rf = rs.getObject().getRef(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection());
- String dn = rs.getObject().getDestinationName(settings.MAP_PREFERRED_LOCALE.get(),
+ String dn = rs.getObject().getDestinationName(settings.MAP_PREFERRED_LOCALE.get(),
settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection());
return formatStreetName(nm, rf, dn, "»");
}
@@ -791,11 +792,11 @@ public class RoutingHelper {
public RouteSegmentResult getCurrentSegmentResult() {
return route.getCurrentSegmentResult();
}
-
+
public List getUpcomingTunnel(float distToStart) {
return route.getUpcomingTunnel(distToStart);
}
-
+
public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak){
NextDirectionInfo i = route.getNextRouteDirectionInfoAfter(previous, to, toSpeak);
if(i != null) {
@@ -803,15 +804,15 @@ public class RoutingHelper {
}
return i;
}
-
+
public List getRouteDirections(){
return route.getRouteDirections();
}
-
-
-
+
+
+
private class RouteRecalculationThread extends Thread {
-
+
private final RouteCalculationParams params;
private boolean paramsChanged;
private Thread prevRunningJob;
@@ -824,7 +825,7 @@ public class RoutingHelper {
params.calculationProgress = new RouteCalculationProgress();
}
}
-
+
public boolean isParamsChanged() {
return paramsChanged;
}
@@ -832,8 +833,8 @@ public class RoutingHelper {
public void stopCalculation(){
params.calculationProgress.isCancelled = true;
}
-
-
+
+
@Override
public void run() {
synchronized (RoutingHelper.this) {
@@ -870,6 +871,12 @@ public class RoutingHelper {
synchronized (RoutingHelper.this) {
if (res.isCalculated()) {
route = res;
+ if (params.snapToRoadParams != null) {
+ params.snapToRoadParams.points = res.getRouteLocations();
+ if (params.snapToRoadParams.listener != null) {
+ params.snapToRoadParams.listener.onSnapToRoadDone();
+ }
+ }
} else {
evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); // for Issue #3899
evalWaitInterval = Math.min(evalWaitInterval, 120000);
@@ -903,14 +910,19 @@ public class RoutingHelper {
this.prevRunningJob = prevRunningJob;
}
}
-
+
+ public void recalculateSnapToRoad(final Location start, final LatLon end, final List intermediates, SnapToRoadParams params) {
+ recalculateRouteInBackground(start, end, intermediates, null, route, true, false, params);
+ }
+
public void recalculateRouteDueToSettingsChange() {
clearCurrentRoute(finalLocation, intermediatePoints);
- recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false);
+ recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false, null);
}
-
+
private void recalculateRouteInBackground(final Location start, final LatLon end, final List intermediates,
- final GPXRouteParamsBuilder gpxRoute, final RouteCalculationResult previousRoute, boolean paramsChanged, boolean onlyStartPointChanged){
+ final GPXRouteParamsBuilder gpxRoute, final RouteCalculationResult previousRoute, boolean paramsChanged, boolean onlyStartPointChanged,
+ final SnapToRoadParams snapToRoadParams){
if (start == null || end == null) {
return;
}
@@ -932,12 +944,23 @@ public class RoutingHelper {
recalculateCountInInterval = 0;
}
params.leftSide = settings.DRIVING_REGION.get().leftHandDriving;
+ ApplicationMode mode;
+ if (snapToRoadParams != null && snapToRoadParams.applicationMode != null) {
+ params.snapToRoadParams = snapToRoadParams;
+ mode = snapToRoadParams.applicationMode;
+ } else {
+ mode = this.mode;
+ }
params.fast = settings.FAST_ROUTE_MODE.getModeValue(mode);
params.type = settings.ROUTER_SERVICE.getModeValue(mode);
params.mode = mode;
params.ctx = app;
if (params.type == RouteService.OSMAND) {
- params.calculationProgress = new RouteCalculationProgress();
+ if (snapToRoadParams != null && snapToRoadParams.calculationProgress != null) {
+ params.calculationProgress = snapToRoadParams.calculationProgress;
+ } else {
+ params.calculationProgress = new RouteCalculationProgress();
+ }
updateProgress(params);
}
synchronized (this) {
@@ -954,6 +977,12 @@ public class RoutingHelper {
}
private void updateProgress(final RouteCalculationParams params) {
+ final RouteCalculationProgressCallback progressRoute;
+ if (params.snapToRoadParams != null) {
+ progressRoute = params.snapToRoadParams.calculationProgressCallback;
+ } else {
+ progressRoute = this.progressRoute;
+ }
if(progressRoute != null ) {
app.runInUIThread(new Runnable() {
@@ -970,7 +999,7 @@ public class RoutingHelper {
Thread t = currentRunningJob;
if(t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) {
// different calculation started
- return;
+ return;
} else {
if (calculationProgress.requestPrivateAccessRouting) {
progressRoute.requestPrivateAccessRouting();
@@ -987,13 +1016,13 @@ public class RoutingHelper {
}, 300);
}
}
-
+
public void setProgressBar(RouteCalculationProgressCallback progressRoute) {
this.progressRoute = progressRoute;
}
-
+
public interface RouteCalculationProgressCallback {
-
+
// set visibility
public void updateProgress(int progress);
public void requestPrivateAccessRouting();
@@ -1004,7 +1033,7 @@ public class RoutingHelper {
public boolean isRouteBeingCalculated(){
return currentRunningJob instanceof RouteRecalculationThread;
}
-
+
private void showMessage(final String msg){
app.runInUIThread(new Runnable() {
@Override
@@ -1013,13 +1042,13 @@ public class RoutingHelper {
}
});
}
-
-
+
+
// NEVER returns null
public RouteCalculationResult getRoute() {
return route;
}
-
+
public GPXFile generateGPXFileWithRoute(){
return provider.createOsmandRouterGPX(route, app);
}
diff --git a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java
index 51f736222b..40d9b9e342 100644
--- a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java
+++ b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java
@@ -8,6 +8,7 @@ import android.widget.TextView;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
+import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.IconsCache;
@@ -67,6 +68,7 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
public void onClick(View v) {
hide();
contextMenuLayer.cancelAddGpxPoint();
+ openTrackActivity();
}
});
}
@@ -129,6 +131,14 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
@Override
public void onDismiss() {
+ MapContextMenu contextMenu = mapActivity.getContextMenu();
+ if (contextMenu.isVisible() && contextMenu.isClosable()) {
+ contextMenu.close();
+ }
+ openTrackActivity();
+ }
+
+ private void openTrackActivity() {
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, newGpxPoint.getGpx().path);
newIntent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
@@ -139,10 +149,12 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
public static class NewGpxPoint {
private PointDescription pointDescription;
private GPXFile gpx;
+ private QuadRect rect;
- public NewGpxPoint(GPXFile gpx, PointDescription pointDescription) {
+ public NewGpxPoint(GPXFile gpx, PointDescription pointDescription, QuadRect rect) {
this.gpx = gpx;
this.pointDescription = pointDescription;
+ this.rect = rect;
}
public GPXFile getGpx() {
@@ -152,5 +164,9 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
public PointDescription getPointDescription() {
return pointDescription;
}
+
+ public QuadRect getRect() {
+ return rect;
+ }
}
}
diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
index 0f6dc6c72d..14902589be 100644
--- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
@@ -449,7 +449,7 @@ public class ContextMenuLayer extends OsmandMapLayer {
}
}
- private void quitAddGpxPoint() {
+ public void quitAddGpxPoint() {
mInAddGpxPointMode = false;
mark(View.VISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
diff --git a/OsmAnd/src/net/osmand/plus/views/MapQuickActionLayer.java b/OsmAnd/src/net/osmand/plus/views/MapQuickActionLayer.java
index c5365d41ff..f5129c680a 100644
--- a/OsmAnd/src/net/osmand/plus/views/MapQuickActionLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/MapQuickActionLayer.java
@@ -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();
diff --git a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java
index 2553ffaaad..79aa23f434 100644
--- a/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java
+++ b/OsmAnd/src/net/osmand/plus/views/OsmandMapTileView.java
@@ -578,12 +578,19 @@ 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;
}
- final float ratiox = mapPositionX == 0 ? 0.5f : 0.75f;
+ final float ratiox;
+ if (mapPosition == OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT) {
+ ratiox = 0.7f;
+ } else {
+ ratiox = mapPositionX == 0 ? 0.5f : 0.75f;
+ }
final int cy = (int) (ratioy * view.getHeight());
final int cx = (int) (ratiox * view.getWidth());
if (currentViewport.getPixWidth() != view.getWidth() || currentViewport.getPixHeight() != view.getHeight() ||
diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
index d0911e299d..b811242940 100644
--- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
+++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
@@ -1,8 +1,10 @@
package net.osmand.plus.views.mapwidgets;
import android.graphics.drawable.Drawable;
+import android.support.v7.widget.SwitchCompat;
import android.view.View;
import android.view.View.OnClickListener;
+import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -229,7 +231,11 @@ public class MapInfoWidgetsFactory {
int refreshBtnIconDarkId = R.drawable.ic_action_refresh_dark;
int refreshBtnIconClrLightId = R.color.icon_color;
int refreshBtnIconClrDarkId = 0;
+
boolean refreshBtnVisible = false;
+ boolean saveViewVisible = false;
+ protected boolean topBarSwitchVisible = false;
+ protected boolean topBarSwitchChecked = false;
int titleTextClrLightId = R.color.primary_text_light;
int titleTextClrDarkId = R.color.primary_text_dark;
@@ -247,6 +253,8 @@ public class MapInfoWidgetsFactory {
OnClickListener onTitleClickListener;
OnClickListener onCloseButtonClickListener;
OnClickListener onRefreshButtonClickListener;
+ OnClickListener onSaveViewClickListener;
+ OnCheckedChangeListener onSwitchCheckedChangeListener;
Runnable onCloseToolbarListener;
@@ -264,6 +272,10 @@ public class MapInfoWidgetsFactory {
this.title = title;
}
+ public String getTitle() {
+ return title;
+ }
+
public void setBottomView(View bottomView) {
this.bottomView = bottomView;
}
@@ -321,6 +333,18 @@ public class MapInfoWidgetsFactory {
this.refreshBtnVisible = visible;
}
+ public void setSaveViewVisible(boolean visible) {
+ this.saveViewVisible = visible;
+ }
+
+ public void setTopBarSwitchVisible(boolean visible) {
+ this.topBarSwitchVisible = visible;
+ }
+
+ public void setTopBarSwitchChecked(boolean checked) {
+ this.topBarSwitchChecked = checked;
+ }
+
public void setTitleTextClrIds(int titleTextClrLightId, int titleTextClrDarkId) {
this.titleTextClrLightId = titleTextClrLightId;
this.titleTextClrDarkId = titleTextClrDarkId;
@@ -343,6 +367,14 @@ public class MapInfoWidgetsFactory {
this.onCloseButtonClickListener = onCloseButtonClickListener;
}
+ public void setOnSaveViewClickListener(OnClickListener onSaveViewClickListener) {
+ this.onSaveViewClickListener = onSaveViewClickListener;
+ }
+
+ public void setOnSwitchCheckedChangeListener(OnCheckedChangeListener onSwitchCheckedChangeListener) {
+ this.onSwitchCheckedChangeListener = onSwitchCheckedChangeListener;
+ }
+
public void setOnRefreshButtonClickListener(OnClickListener onRefreshButtonClickListener) {
this.onRefreshButtonClickListener = onRefreshButtonClickListener;
}
@@ -355,6 +387,7 @@ public class MapInfoWidgetsFactory {
TextView titleView = view.getTitleView();
TextView descrView = view.getDescrView();
LinearLayout bottomViewLayout = view.getBottomViewLayout();
+ SwitchCompat switchCompat = view.getTopBarSwitch();
if (title != null) {
titleView.setText(title);
view.updateVisibility(titleView, true);
@@ -374,6 +407,10 @@ public class MapInfoWidgetsFactory {
} else {
view.updateVisibility(bottomViewLayout, false);
}
+ view.updateVisibility(switchCompat, topBarSwitchVisible);
+ if (topBarSwitchVisible) {
+ switchCompat.setChecked(topBarSwitchChecked);
+ }
if (view.getShadowView() != null) {
view.getShadowView().setVisibility(View.VISIBLE);
}
@@ -393,6 +430,8 @@ public class MapInfoWidgetsFactory {
private TextView descrView;
private ImageButton refreshButton;
private ImageButton closeButton;
+ private TextView saveView;
+ private SwitchCompat topBarSwitch;
private View shadowView;
private boolean nightMode;
@@ -407,7 +446,9 @@ public class MapInfoWidgetsFactory {
refreshButton = (ImageButton) map.findViewById(R.id.widget_top_bar_refresh_button);
closeButton = (ImageButton) map.findViewById(R.id.widget_top_bar_close_button);
titleView = (TextView) map.findViewById(R.id.widget_top_bar_title);
+ saveView = (TextView) map.findViewById(R.id.widget_top_bar_save);
descrView = (TextView) map.findViewById(R.id.widget_top_bar_description);
+ topBarSwitch = (SwitchCompat) map.findViewById(R.id.widget_top_bar_switch);
shadowView = map.findViewById(R.id.widget_top_bar_shadow);
updateVisibility(false);
}
@@ -444,6 +485,14 @@ public class MapInfoWidgetsFactory {
return closeButton;
}
+ public TextView getSaveView() {
+ return saveView;
+ }
+
+ public SwitchCompat getTopBarSwitch() {
+ return topBarSwitch;
+ }
+
public ImageButton getRefreshButton() {
return refreshButton;
}
@@ -515,6 +564,8 @@ public class MapInfoWidgetsFactory {
topBarTitleLayout.setOnClickListener(controller.onTitleClickListener);
closeButton.setOnClickListener(controller.onCloseButtonClickListener);
refreshButton.setOnClickListener(controller.onRefreshButtonClickListener);
+ saveView.setOnClickListener(controller.onSaveViewClickListener);
+ topBarSwitch.setOnCheckedChangeListener(controller.onSwitchCheckedChangeListener);
}
public void updateInfo() {
@@ -553,6 +604,7 @@ public class MapInfoWidgetsFactory {
int descrColor = map.getResources().getColor(controller.descrTextClrDarkId);
titleView.setTextColor(titleColor);
descrView.setTextColor(descrColor);
+ saveView.setTextColor(titleColor);
} else {
topBarLayout.setBackgroundResource(AndroidUiHelper.isOrientationPortrait(map) ? controller.bgLightId : controller.bgLightLandId);
if (controller.backBtnIconLightId == 0) {
@@ -574,6 +626,7 @@ public class MapInfoWidgetsFactory {
int descrColor = map.getResources().getColor(controller.descrTextClrLightId);
titleView.setTextColor(titleColor);
descrView.setTextColor(descrColor);
+ saveView.setTextColor(titleColor);
}
if (controller.singleLineTitle) {
titleView.setSingleLine(true);
@@ -595,6 +648,13 @@ public class MapInfoWidgetsFactory {
} else if (refreshButton.getVisibility() == View.VISIBLE) {
refreshButton.setVisibility(View.GONE);
}
+ if (controller.saveViewVisible) {
+ if (saveView.getVisibility() == View.GONE) {
+ saveView.setVisibility(View.VISIBLE);
+ }
+ } else if (saveView.getVisibility() == View.VISIBLE) {
+ saveView.setVisibility(View.GONE);
+ }
}
public void updateColors() {