diff --git a/OsmAnd/res/color/bottom_navigation_color_selector.xml b/OsmAnd/res/drawable/bottom_navigation_color_selector.xml similarity index 100% rename from OsmAnd/res/color/bottom_navigation_color_selector.xml rename to OsmAnd/res/drawable/bottom_navigation_color_selector.xml diff --git a/OsmAnd/res/drawable/marker_circle_background_light_n.xml b/OsmAnd/res/drawable/marker_circle_background_light_n.xml new file mode 100644 index 0000000000..135fceccb2 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_light_n.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_light_n_with_inset.xml b/OsmAnd/res/drawable/marker_circle_background_light_n_with_inset.xml new file mode 100644 index 0000000000..b20f1f27f0 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_light_n_with_inset.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_light_with_inset.xml b/OsmAnd/res/drawable/marker_circle_background_light_with_inset.xml new file mode 100644 index 0000000000..9028ba95f8 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_light_with_inset.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_on_map_n.xml b/OsmAnd/res/drawable/marker_circle_background_on_map_n.xml new file mode 100644 index 0000000000..c9a69c97ff --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_on_map_n.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_on_map_n_with_inset.xml b/OsmAnd/res/drawable/marker_circle_background_on_map_n_with_inset.xml new file mode 100644 index 0000000000..e9ab9f1da0 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_on_map_n_with_inset.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_on_map_with_inset.xml b/OsmAnd/res/drawable/marker_circle_background_on_map_with_inset.xml new file mode 100644 index 0000000000..c8a1ec15a5 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_on_map_with_inset.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_p.xml b/OsmAnd/res/drawable/marker_circle_background_p.xml new file mode 100644 index 0000000000..66ed549f5f --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_p.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/marker_circle_background_p_with_inset.xml b/OsmAnd/res/drawable/marker_circle_background_p_with_inset.xml new file mode 100644 index 0000000000..87a731b9d6 --- /dev/null +++ b/OsmAnd/res/drawable/marker_circle_background_p_with_inset.xml @@ -0,0 +1,9 @@ + + + + \ 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 index 9dd92bdcca..88782a4fb5 100644 --- a/OsmAnd/res/layout-land/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout-land/fragment_measurement_tool.xml @@ -46,10 +46,10 @@ android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_centerVertical="true" - android:layout_marginEnd="@dimen/measurement_tool_content_margin" - android:layout_marginLeft="@dimen/measurement_tool_content_margin" - android:layout_marginRight="@dimen/measurement_tool_content_margin" - android:layout_marginStart="@dimen/measurement_tool_content_margin" + android:layout_marginEnd="@dimen/bottom_sheet_content_margin" + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginRight="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin" android:background="@null" tools:src="@drawable/ic_action_ruler"/> @@ -60,10 +60,10 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" - android:layout_marginEnd="@dimen/measurement_tool_content_margin" - android:layout_marginLeft="@dimen/measurement_tool_content_margin" - android:layout_marginRight="@dimen/measurement_tool_content_margin" - android:layout_marginStart="@dimen/measurement_tool_content_margin" + android:layout_marginEnd="@dimen/bottom_sheet_content_margin" + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginRight="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin" android:background="@null" tools:src="@drawable/ic_action_arrow_down"/> diff --git a/OsmAnd/res/layout/close_measurement_tool_dialog.xml b/OsmAnd/res/layout/close_measurement_tool_dialog.xml index 6485e8582f..e1c823056a 100644 --- a/OsmAnd/res/layout/close_measurement_tool_dialog.xml +++ b/OsmAnd/res/layout/close_measurement_tool_dialog.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" - android:padding="@dimen/measurement_tool_content_padding"> + android:padding="@dimen/bottom_sheet_content_padding"> + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin"/> \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_map_markers_dialog.xml b/OsmAnd/res/layout/fragment_map_markers_dialog.xml index f07f3a3c15..2d3f7b246f 100644 --- a/OsmAnd/res/layout/fragment_map_markers_dialog.xml +++ b/OsmAnd/res/layout/fragment_map_markers_dialog.xml @@ -4,53 +4,65 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + xmlns:osmand="http://schemas.android.com/tools" android:orientation="vertical"> - + android:layout_height="@dimen/dashboard_map_toolbar"> - + android:layout_height="match_parent" + app:contentInsetLeft="54dp" + app:contentInsetStart="54dp"> - + android:gravity="center_vertical"> - - + - + + + + + + + android:layout_weight="1" + android:background="?attr/ctx_menu_info_view_bg"> - + + android:layout_height="wrap_content"> + + + diff --git a/OsmAnd/res/layout/fragment_marker_history_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_marker_history_bottom_sheet_dialog.xml new file mode 100644 index 0000000000..24d9579995 --- /dev/null +++ b/OsmAnd/res/layout/fragment_marker_history_bottom_sheet_dialog.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_marker_options_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_marker_options_bottom_sheet_dialog.xml index e77703ddfc..d5fd81800e 100644 --- a/OsmAnd/res/layout/fragment_marker_options_bottom_sheet_dialog.xml +++ b/OsmAnd/res/layout/fragment_marker_options_bottom_sheet_dialog.xml @@ -21,34 +21,34 @@ + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:layout_marginEnd="@dimen/bottom_sheet_icon_margin" + android:layout_marginRight="@dimen/bottom_sheet_icon_margin" + tools:background="@drawable/ic_action_device_top"/> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 57ddf558b8..6b5a3da674 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool.xml @@ -41,10 +41,10 @@ android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_centerVertical="true" - android:layout_marginEnd="@dimen/measurement_tool_content_margin" - android:layout_marginLeft="@dimen/measurement_tool_content_margin" - android:layout_marginRight="@dimen/measurement_tool_content_margin" - android:layout_marginStart="@dimen/measurement_tool_content_margin" + android:layout_marginEnd="@dimen/bottom_sheet_content_margin" + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginRight="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin" android:background="@null" tools:src="@drawable/ic_action_ruler"/> @@ -55,10 +55,10 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" - android:layout_marginEnd="@dimen/measurement_tool_content_margin" - android:layout_marginLeft="@dimen/measurement_tool_content_margin" - android:layout_marginRight="@dimen/measurement_tool_content_margin" - android:layout_marginStart="@dimen/measurement_tool_content_margin" + android:layout_marginEnd="@dimen/bottom_sheet_content_margin" + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginRight="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin" android:background="@null" tools:src="@drawable/ic_action_arrow_down"/> diff --git a/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml b/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml index ed0730b8d2..4e1a338a84 100644 --- a/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml +++ b/OsmAnd/res/layout/fragment_options_bottom_sheet_dialog.xml @@ -22,12 +22,12 @@ @@ -35,21 +35,21 @@ + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:paddingBottom="@dimen/bottom_sheet_content_padding_small"> @@ -46,16 +46,16 @@ android:id="@+id/images_row" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="16dp" + android:layout_marginBottom="@dimen/bottom_sheet_content_margin" android:orientation="horizontal"> @@ -84,10 +84,10 @@ @@ -118,21 +118,21 @@ + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:paddingBottom="@dimen/bottom_sheet_content_padding_small"> + android:layout_height="@dimen/bottom_sheet_selected_item_title_height" + android:minHeight="@dimen/bottom_sheet_selected_item_title_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + android:paddingBottom="@dimen/bottom_sheet_content_padding_small"> @@ -50,7 +50,7 @@ + android:minHeight="@dimen/bottom_sheet_list_item_height" + android:paddingEnd="@dimen/bottom_sheet_content_padding" + android:paddingLeft="@dimen/bottom_sheet_content_padding" + android:paddingRight="@dimen/bottom_sheet_content_padding" + android:paddingStart="@dimen/bottom_sheet_content_padding"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/map_marker_item_new.xml b/OsmAnd/res/layout/map_marker_item_new.xml index 7ae162e70d..0f4ddb6a42 100644 --- a/OsmAnd/res/layout/map_marker_item_new.xml +++ b/OsmAnd/res/layout/map_marker_item_new.xml @@ -1,123 +1,154 @@ - + android:layout_height="wrap_content" + android:descendantFocusability="blocksDescendants" + android:orientation="vertical"> - - - - + android:layout_height="wrap_content"> + android:layout_width="match_parent" + android:layout_height="56dp" + android:background="?attr/selectableItemBackground"> - + + + + + + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:orientation="vertical"> - + - + - + + + + + + + + + + + + + + + + - + + - + android:layout_height="1dp" + android:layout_marginLeft="56dp" + android:layout_marginStart="56dp" + android:background="?attr/dashboard_divider"/> - + - + diff --git a/OsmAnd/res/layout/save_gpx_dialog.xml b/OsmAnd/res/layout/save_gpx_dialog.xml index 080dce6622..ef4f0a66b2 100644 --- a/OsmAnd/res/layout/save_gpx_dialog.xml +++ b/OsmAnd/res/layout/save_gpx_dialog.xml @@ -9,21 +9,21 @@ android:id="@+id/gpx_name_et" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/measurement_tool_content_margin" - android:layout_marginLeft="@dimen/measurement_tool_content_margin" - android:layout_marginRight="@dimen/measurement_tool_content_margin" - android:layout_marginStart="@dimen/measurement_tool_content_margin" - android:layout_marginTop="@dimen/measurement_tool_content_margin" + android:layout_marginEnd="@dimen/bottom_sheet_content_margin" + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginRight="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin" + android:layout_marginTop="@dimen/bottom_sheet_content_margin" android:inputType="text"/> + android:padding="@dimen/bottom_sheet_content_padding"> + android:layout_marginLeft="@dimen/bottom_sheet_content_margin" + android:layout_marginStart="@dimen/bottom_sheet_content_margin"/> + android:icon="@drawable/ic_action_markers_list" + android:title="@string/shared_string_list"/> + + 90dp 96dp - 72dp + 72dp 540dp 30dp - 24dp - 12dp - 24dp - 12dp + 24dp + 12dp + 24dp + 12dp 12dp 18dp 6dp @@ -113,14 +113,14 @@ 12dp 12dp 54dp - 78dp - 66dp - 72dp - 36dp + 78dp + 66dp + 72dp + 36dp 11dp 12dp 96dp - 15dp - 84dp + 15dp + 84dp \ No newline at end of file diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml index 12872af5b5..27bd83e435 100644 --- a/OsmAnd/res/values/colors.xml +++ b/OsmAnd/res/values/colors.xml @@ -258,5 +258,8 @@ #101821 #46bd2a + #0d464a + #17828a + #f2f4ff \ No newline at end of file diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index aed0718f34..8ff94dfbef 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -156,14 +156,14 @@ 60dp 64dp - 48dp + 48dp 360dp 20dp - 16dp - 8dp - 16dp - 8dp + 16dp + 8dp + 16dp + 8dp 8dp 12dp 4dp @@ -178,13 +178,13 @@ 8dp 8dp 36dp - 52dp - 44dp - 48dp - 24dp + 52dp + 44dp + 48dp + 24dp 7dp 8dp 64dp - 10dp - 56dp + 10dp + 56dp \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 7565a99cb9..5dc07ab55c 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -9,11 +9,25 @@ 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 --> + Map orientation change in accordance with speed + Use built in compass instead of direction of movement to determine map orientation at low speed + All markers moved to History + Marker moved to History + Marker moved to Active + List + Groups + Passed: %1$s + Make active + Today + Yesterday + Last 7 days + This year + Widget + Top bar Move all to history Build route Show direction Sort by - Marker options Do not use animations Disables animations in the app Keep showing on map diff --git a/OsmAnd/res/xml/navigation_settings.xml b/OsmAnd/res/xml/navigation_settings.xml index 5463abb74c..47eefe9ade 100644 --- a/OsmAnd/res/xml/navigation_settings.xml +++ b/OsmAnd/res/xml/navigation_settings.xml @@ -1,55 +1,92 @@ - + - - - - - + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java index cf1a3a30fd..96674888da 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java @@ -797,7 +797,7 @@ public class OsmandAidlApi { List mapMarkers = markersHelper.getMapMarkers(); for (MapMarker m : mapMarkers) { if (m.getOnlyName().equals(marker.getName()) && latLon.equals(new LatLon(m.getLatitude(), m.getLongitude()))) { - markersHelper.removeMapMarker(m); + markersHelper.moveMapMarkerToHistory(m); refreshMap(); return true; } @@ -818,7 +818,10 @@ public class OsmandAidlApi { if (m.getOnlyName().equals(markerPrev.getName()) && latLon.equals(new LatLon(m.getLatitude(), m.getLongitude()))) { PointDescription pd = new PointDescription( PointDescription.POINT_TYPE_MAP_MARKER, markerNew.getName() != null ? markerNew.getName() : ""); - MapMarker marker = new MapMarker(m.point, pd, m.colorIndex, m.selected, m.creationDate, m.index); + MapMarker marker = new MapMarker(m.point, pd, m.colorIndex, m.selected, m.index); + marker.id = m.id; + marker.creationDate = m.creationDate; + marker.visitedDate = m.visitedDate; markersHelper.moveMapMarker(marker, latLonNew); refreshMap(); return true; diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 48acbed4d9..ec14837769 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -29,6 +29,7 @@ import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; import net.osmand.plus.helpers.AvoidSpecificRoads; import net.osmand.plus.helpers.WaypointHelper; import net.osmand.plus.liveupdates.LiveUpdatesHelper; +import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.poi.PoiFiltersHelper; @@ -373,6 +374,7 @@ public class AppInitializer implements IProgress { app.rendererRegistry = startupInit(new RendererRegistry(app), RendererRegistry.class); app.geocodingLookupService = startupInit(new GeocodingLookupService(app), GeocodingLookupService.class); app.targetPointsHelper = startupInit(new TargetPointsHelper(app), TargetPointsHelper.class); + app.mapMarkersDbHelper = startupInit(new MapMarkersDbHelper(app), MapMarkersDbHelper.class); app.mapMarkersHelper = startupInit(new MapMarkersHelper(app), MapMarkersHelper.class); app.searchUICore = startupInit(new QuickSearchHelper(app), QuickSearchHelper.class); } @@ -499,6 +501,7 @@ public class AppInitializer implements IProgress { startBgTime = System.currentTimeMillis(); app.favorites.loadFavorites(); notifyEvent(InitEvents.FAVORITES_INITIALIZED); + app.mapMarkersHelper.syncAllGroups(); // init poi types before indexes and before POI initPoiTypes(); notifyEvent(InitEvents.POI_TYPES_INITIALIZED); diff --git a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java index 5d9e0db424..6ab73a355f 100644 --- a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java @@ -7,6 +7,7 @@ import net.osmand.PlatformUtil; import net.osmand.data.FavouritePoint; import net.osmand.plus.GPXUtilities.GPXFile; import net.osmand.plus.GPXUtilities.WptPt; +import net.osmand.plus.MapMarkersHelper.MarkersSyncGroup; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; import net.osmand.util.Algorithms; @@ -20,6 +21,7 @@ import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -33,7 +35,7 @@ public class FavouritesDbHelper { private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(FavouritesDbHelper.class); - + public static final String FILE_TO_SAVE = "favourites.gpx"; //$NON-NLS-1$ public static final String BACKUP_FOLDER = "backup"; //$NON-NLS-1$ public static final int BACKUP_CNT = 20; //$NON-NLS-1$ @@ -45,27 +47,27 @@ public class FavouritesDbHelper { private final OsmandApplication context; protected static final String HIDDEN = "HIDDEN"; private static final String DELIMETER = "__"; - + public FavouritesDbHelper(OsmandApplication context) { this.context = context; } - + public static class FavoriteGroup { public String name; public boolean visible = true; public int color; public List points = new ArrayList(); } - + public void loadFavorites() { flatGroups.clear(); favoriteGroups.clear(); - + File internalFile = getInternalFile(); - if(!internalFile.exists()) { + if (!internalFile.exists()) { File dbPath = context.getDatabasePath(FAVOURITE_DB_NAME); - if(dbPath.exists()) { + if (dbPath.exists()) { loadAndCheckDatabasePoints(); saveCurrentPointsIntoFile(); } @@ -76,28 +78,28 @@ public class FavouritesDbHelper { loadGPXFile(internalFile, points); loadGPXFile(getExternalFile(), extPoints); boolean changed = merge(extPoints, points); - - for(FavouritePoint pns : points.values()) { + + for (FavouritePoint pns : points.values()) { FavoriteGroup group = getOrCreateGroup(pns, 0); group.points.add(pns); } sortAll(); recalculateCachedFavPoints(); - if(changed) { + if (changed) { saveCurrentPointsIntoFile(); } favouritesUpdated(); - + } - private void favouritesUpdated(){ + private void favouritesUpdated() { } private boolean merge(Map source, Map destination) { boolean changed = false; - for(String ks : source.keySet()) { - if(!destination.containsKey(ks)) { + for (String ks : source.keySet()) { + if (!destination.containsKey(ks)) { changed = true; destination.put(ks, source.get(ks)); } @@ -106,31 +108,36 @@ public class FavouritesDbHelper { } - private File getInternalFile() { return context.getFileStreamPath(FILE_TO_BACKUP); } - + public void delete(Set groupsToDelete, Set favoritesSelected) { if (favoritesSelected != null) { + Set groupsToSync = new HashSet<>(); for (FavouritePoint p : favoritesSelected) { FavoriteGroup group = flatGroups.get(p.getCategory()); if (group != null) { group.points.remove(p); + groupsToSync.add(group); } cachedFavoritePoints.remove(p); } + for (FavoriteGroup gr : groupsToSync) { + context.getMapMarkersHelper().syncGroup(new MarkersSyncGroup(gr.name, gr.name, MarkersSyncGroup.FAVORITES_TYPE)); + } } if (groupsToDelete != null) { for (FavoriteGroup g : groupsToDelete) { flatGroups.remove(g.name); favoriteGroups.remove(g); cachedFavoritePoints.removeAll(g.points); + context.getMapMarkersHelper().removeMarkersSyncGroup(g.name, true); } } saveCurrentPointsIntoFile(); } - + public boolean deleteFavourite(FavouritePoint p) { return deleteFavourite(p, true); } @@ -140,6 +147,7 @@ public class FavouritesDbHelper { FavoriteGroup group = flatGroups.get(p.getCategory()); if (group != null) { group.points.remove(p); + context.getMapMarkersHelper().syncGroup(new MarkersSyncGroup(group.name, group.name, MarkersSyncGroup.FAVORITES_TYPE)); } cachedFavoritePoints.remove(p); } @@ -148,7 +156,7 @@ public class FavouritesDbHelper { } return true; } - + public boolean addFavourite(FavouritePoint p) { return addFavourite(p, true); } @@ -169,10 +177,11 @@ public class FavouritesDbHelper { sortAll(); saveCurrentPointsIntoFile(); } + context.getMapMarkersHelper().syncGroup(new MarkersSyncGroup(group.name, group.name, MarkersSyncGroup.FAVORITES_TYPE)); return true; } - + public static AlertDialog.Builder checkDuplicates(FavouritePoint p, FavouritesDbHelper fdb, Context uiContext) { boolean emoticons = false; String index = ""; @@ -201,7 +210,7 @@ public class FavouritesDbHelper { } } } - if ((index.length() > 0 || emoticons) ) { + if ((index.length() > 0 || emoticons)) { AlertDialog.Builder builder = new AlertDialog.Builder(uiContext); builder.setTitle(R.string.fav_point_dublicate); if (emoticons) { @@ -215,7 +224,7 @@ public class FavouritesDbHelper { return null; } - public static String checkEmoticons(String name){ + public static String checkEmoticons(String name) { char[] chars = name.toCharArray(); int index; char ch1; @@ -225,16 +234,15 @@ public class FavouritesDbHelper { StringBuilder builder = new StringBuilder(); while (index < chars.length) { ch1 = chars[index]; - if ((int)ch1 == 0xD83C) { - ch2 = chars[index+1]; - if ((int)ch2 >= 0xDF00 && (int)ch2 <= 0xDFFF) { + if ((int) ch1 == 0xD83C) { + ch2 = chars[index + 1]; + if ((int) ch2 >= 0xDF00 && (int) ch2 <= 0xDFFF) { index += 2; continue; } - } - else if ((int)ch1 == 0xD83D) { - ch2 = chars[index+1]; - if ((int)ch2 >= 0xDC00 && (int)ch2 <= 0xDDFF) { + } else if ((int) ch1 == 0xD83D) { + ch2 = chars[index + 1]; + if ((int) ch2 >= 0xDC00 && (int) ch2 <= 0xDDFF) { index += 2; continue; } @@ -264,22 +272,23 @@ public class FavouritesDbHelper { } sortAll(); saveCurrentPointsIntoFile(); + context.getMapMarkersHelper().syncGroup(new MarkersSyncGroup(category, category, MarkersSyncGroup.FAVORITES_TYPE)); return true; } - public boolean editFavourite(FavouritePoint p, double lat, double lon) { p.setLatitude(lat); p.setLongitude(lon); saveCurrentPointsIntoFile(); + context.getMapMarkersHelper().syncGroup(new MarkersSyncGroup(p.getCategory(), p.getCategory(), MarkersSyncGroup.FAVORITES_TYPE)); return true; } - + public void saveCurrentPointsIntoFile() { try { Map deletedInMemory = new LinkedHashMap(); loadGPXFile(getInternalFile(), deletedInMemory); - for(FavouritePoint fp : cachedFavoritePoints) { + for (FavouritePoint fp : cachedFavoritePoints) { deletedInMemory.remove(getKey(fp)); } saveFile(cachedFavoritePoints, getInternalFile()); @@ -289,7 +298,7 @@ public class FavouritesDbHelper { log.error(e.getMessage(), e); } } - + private void backup(File backupFile, File externalFile) { try { File f = new File(backupFile.getParentFile(), backupFile.getName()); @@ -312,18 +321,17 @@ public class FavouritesDbHelper { } - private String saveExternalFile(Set deleted) { Map all = new LinkedHashMap(); loadGPXFile(getExternalFile(), all); List favoritePoints = new ArrayList(cachedFavoritePoints); - if(deleted != null) { - for(String key : deleted) { + if (deleted != null) { + for (String key : deleted) { all.remove(key); } } // remove already existing in memory - for(FavouritePoint p : favoritePoints) { + for (FavouritePoint p : favoritePoints) { all.remove(getKey(p)); } // save favoritePoints from memory in order to update existing @@ -332,18 +340,16 @@ public class FavouritesDbHelper { } - private String getKey(FavouritePoint p) { return p.getName() + DELIMETER + p.getCategory(); } - - public boolean deleteGroup(FavoriteGroup group) { boolean remove = favoriteGroups.remove(group); if (remove) { flatGroups.remove(group.name); saveCurrentPointsIntoFile(); + context.getMapMarkersHelper().removeMarkersSyncGroup(group.name, true); return true; } return false; @@ -352,53 +358,53 @@ public class FavouritesDbHelper { public File getExternalFile() { return new File(context.getAppPath(null), FILE_TO_SAVE); } - + public File getBackupFile() { File fld = new File(context.getAppPath(null), BACKUP_FOLDER); - if(!fld.exists()) { + if (!fld.exists()) { fld.mkdirs(); } int back = 1; String backPrefix = "" + back; File firstModified = null; long firstModifiedMin = System.currentTimeMillis(); - while(back <= BACKUP_CNT) { + while (back <= BACKUP_CNT) { backPrefix = "" + back; - if(back < 10) { - backPrefix = "0"+backPrefix; + if (back < 10) { + backPrefix = "0" + backPrefix; } - File bak = new File(fld, "favourites_bak_" + backPrefix +".gpx.bz2"); + File bak = new File(fld, "favourites_bak_" + backPrefix + ".gpx.bz2"); if (!bak.exists()) { return bak; } else if (bak.lastModified() < firstModifiedMin) { firstModified = bak; firstModifiedMin = bak.lastModified(); } - back ++; + back++; } return firstModified; } - + public String saveFile(List favoritePoints, File f) { GPXFile gpx = asGpxFile(favoritePoints); return GPXUtilities.writeGpxFile(f, gpx, context); } - + public GPXFile asGpxFile() { return asGpxFile(cachedFavoritePoints); } - + private GPXFile asGpxFile(List favoritePoints) { GPXFile gpx = new GPXFile(); for (FavouritePoint p : favoritePoints) { WptPt pt = new WptPt(); pt.lat = p.getLatitude(); pt.lon = p.getLongitude(); - if(!p.isVisible()) { + if (!p.isVisible()) { pt.getExtensionsToWrite().put(HIDDEN, "true"); } - if(p.getColor() != 0) { + if (p.getColor() != 0) { pt.setColor(p.getColor()); } pt.name = p.getName(); @@ -413,7 +419,7 @@ public class FavouritesDbHelper { return gpx; } - + public void addEmptyCategory(String name) { addEmptyCategory(name, 0, true); } @@ -434,17 +440,17 @@ public class FavouritesDbHelper { public List getFavouritePoints() { return cachedFavoritePoints; } - + public List getVisibleFavouritePoints() { List fp = new ArrayList<>(); - for(FavouritePoint p : cachedFavoritePoints) { - if(p.isVisible()) { + for (FavouritePoint p : cachedFavoritePoints) { + if (p.isVisible()) { fp.add(p); } } return fp; } - + public List getFavoriteGroups() { return favoriteGroups; @@ -476,7 +482,7 @@ public class FavouritesDbHelper { } } - private FavouritePoint findFavoriteByAllProperties(String category, String name, double lat, double lon){ + private FavouritePoint findFavoriteByAllProperties(String category, String name, double lat, double lon) { if (flatGroups.containsKey(category)) { FavoriteGroup fg = flatGroups.get(category); for (FavouritePoint fv : fg.points) { @@ -488,16 +494,15 @@ public class FavouritesDbHelper { return null; } - - - public void recalculateCachedFavPoints(){ + + public void recalculateCachedFavPoints() { ArrayList temp = new ArrayList(); - for(FavoriteGroup f : favoriteGroups){ + for (FavoriteGroup f : favoriteGroups) { temp.addAll(f.points); } cachedFavoritePoints = temp; } - + public void sortAll() { final Collator collator = Collator.getInstance(); collator.setStrength(Collator.SECONDARY); @@ -550,10 +555,10 @@ public class FavouritesDbHelper { }; return favoritesComparator; } - + private boolean loadGPXFile(File file, Map points) { - if(!file.exists()) { + if (!file.exists()) { return false; } GPXFile res = GPXUtilities.loadGPXFile(context, file); @@ -583,39 +588,45 @@ public class FavouritesDbHelper { } return true; } - + public void editFavouriteGroup(FavoriteGroup group, String newName, int color, boolean visible) { - if(color != 0 && group.color != color) { + MapMarkersHelper markersHelper = context.getMapMarkersHelper(); + if (color != 0 && group.color != color) { FavoriteGroup gr = flatGroups.get(group.name); group.color = color; - for(FavouritePoint p : gr.points) { + for (FavouritePoint p : gr.points) { p.setColor(color); - } + } } - if(group.visible != visible) { + if (group.visible != visible) { FavoriteGroup gr = flatGroups.get(group.name); group.visible = visible; - for(FavouritePoint p : gr.points) { + for (FavouritePoint p : gr.points) { p.setVisible(visible); - } + } + markersHelper.syncGroup(new MarkersSyncGroup(gr.name, gr.name, MarkersSyncGroup.FAVORITES_TYPE)); } if (!group.name.equals(newName)) { FavoriteGroup gr = flatGroups.remove(group.name); + markersHelper.removeMarkersSyncGroup(group.name, true); gr.name = newName; FavoriteGroup renamedGroup = flatGroups.get(gr.name); boolean existing = renamedGroup != null; - if(renamedGroup == null) { + if (renamedGroup == null) { renamedGroup = gr; flatGroups.put(gr.name, gr); } else { favoriteGroups.remove(gr); } - for(FavouritePoint p : gr.points) { + for (FavouritePoint p : gr.points) { p.setCategory(newName); - if(existing) { + if (existing) { renamedGroup.points.add(p); } } + MarkersSyncGroup syncGroup = new MarkersSyncGroup(renamedGroup.name, renamedGroup.name, MarkersSyncGroup.FAVORITES_TYPE); + markersHelper.addMarkersSyncGroup(syncGroup); + markersHelper.syncGroup(syncGroup); } saveCurrentPointsIntoFile(); } @@ -643,7 +654,7 @@ public class FavouritesDbHelper { return group; } - + /// Deprecated sqlite db private static final int DATABASE_VERSION = 2; public static final String FAVOURITE_DB_NAME = "favourite"; //$NON-NLS-1$ @@ -656,8 +667,8 @@ public class FavouritesDbHelper { FAVOURITE_COL_NAME + " TEXT, " + FAVOURITE_COL_CATEGORY + " TEXT, " + //$NON-NLS-1$ //$NON-NLS-2$ FAVOURITE_COL_LAT + " double, " + FAVOURITE_COL_LON + " double);"; //$NON-NLS-1$ //$NON-NLS-2$ private SQLiteConnection conn; - - + + private SQLiteConnection openConnection(boolean readonly) { conn = context.getSQLiteAPI().getOrCreateDatabase(FAVOURITE_DB_NAME, readonly); if (conn.getVersion() == 0 || DATABASE_VERSION != conn.getVersion()) { @@ -674,19 +685,19 @@ public class FavouritesDbHelper { } return conn; } - + public void onCreate(SQLiteConnection db) { db.execSQL(FAVOURITE_TABLE_CREATE); } public void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { - if(oldVersion == 1){ - db.execSQL("ALTER TABLE " + FAVOURITE_TABLE_NAME + " ADD " + FAVOURITE_COL_CATEGORY + " text"); - db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET category = ?", new Object[] { "" }); //$NON-NLS-1$ //$NON-NLS-2$ + if (oldVersion == 1) { + db.execSQL("ALTER TABLE " + FAVOURITE_TABLE_NAME + " ADD " + FAVOURITE_COL_CATEGORY + " text"); + db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET category = ?", new Object[]{""}); //$NON-NLS-1$ //$NON-NLS-2$ } } - - private void loadAndCheckDatabasePoints(){ + + private void loadAndCheckDatabasePoints() { if (favoriteGroups == null) { SQLiteConnection db = openConnection(true); if (db != null) { @@ -715,29 +726,29 @@ public class FavouritesDbHelper { query.close(); } finally { db.close(); - } + } sortAll(); } recalculateCachedFavPoints(); } } - + public boolean deleteFavouriteDB(FavouritePoint p) { SQLiteConnection db = openConnection(false); if (db != null) { try { db.execSQL( - "DELETE FROM " + FAVOURITE_TABLE_NAME + " WHERE category = ? AND " + whereNameLatLon(), new Object[] { p.getCategory(), p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + "DELETE FROM " + FAVOURITE_TABLE_NAME + " WHERE category = ? AND " + whereNameLatLon(), new Object[]{p.getCategory(), p.getName(), p.getLatitude(), p.getLongitude()}); //$NON-NLS-1$ //$NON-NLS-2$ FavouritePoint fp = findFavoriteByAllProperties(p.getCategory(), p.getName(), p.getLatitude(), p.getLongitude()); if (fp != null) { FavoriteGroup group = flatGroups.get(p.getCategory()); - if(group != null) { + if (group != null) { group.points.remove(fp); } cachedFavoritePoints.remove(fp); } saveCurrentPointsIntoFile(); - } finally{ + } finally { db.close(); } return true; @@ -747,7 +758,7 @@ public class FavouritesDbHelper { public boolean addFavouriteDB(FavouritePoint p) { - if(p.getName().equals("") && flatGroups.containsKey(p.getCategory())){ + if (p.getName().equals("") && flatGroups.containsKey(p.getCategory())) { return true; } SQLiteConnection db = openConnection(false); @@ -755,8 +766,8 @@ public class FavouritesDbHelper { try { db.execSQL( "INSERT INTO " + FAVOURITE_TABLE_NAME + " (" + FAVOURITE_COL_NAME + ", " + FAVOURITE_COL_CATEGORY + ", " - + FAVOURITE_COL_LAT + ", " + FAVOURITE_COL_LON + ")" + " VALUES (?, ?, ?, ?)", new Object[] { p.getName(), p.getCategory(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ - FavoriteGroup group = getOrCreateGroup(p, 0); + + FAVOURITE_COL_LAT + ", " + FAVOURITE_COL_LON + ")" + " VALUES (?, ?, ?, ?)", new Object[]{p.getName(), p.getCategory(), p.getLatitude(), p.getLongitude()}); //$NON-NLS-1$ //$NON-NLS-2$ + FavoriteGroup group = getOrCreateGroup(p, 0); if (!p.getName().equals("")) { p.setVisible(group.visible); p.setColor(group.color); @@ -771,8 +782,7 @@ public class FavouritesDbHelper { } return false; } - - + public boolean editFavouriteNameDB(FavouritePoint p, String newName, String category) { SQLiteConnection db = openConnection(false); @@ -780,7 +790,7 @@ public class FavouritesDbHelper { try { String oldCategory = p.getCategory(); db.execSQL( - "UPDATE " + FAVOURITE_TABLE_NAME + " SET " + FAVOURITE_COL_NAME + " = ?, " + FAVOURITE_COL_CATEGORY + "= ? WHERE " + whereNameLatLon(), new Object[] { newName, category, p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + "UPDATE " + FAVOURITE_TABLE_NAME + " SET " + FAVOURITE_COL_NAME + " = ?, " + FAVOURITE_COL_CATEGORY + "= ? WHERE " + whereNameLatLon(), new Object[]{newName, category, p.getName(), p.getLatitude(), p.getLongitude()}); //$NON-NLS-1$ //$NON-NLS-2$ p.setName(newName); p.setCategory(category); if (!oldCategory.equals(category)) { @@ -801,14 +811,14 @@ public class FavouritesDbHelper { } return false; } - + public boolean editFavouriteDB(FavouritePoint p, double lat, double lon) { SQLiteConnection db = openConnection(false); if (db != null) { try { db.execSQL( - "UPDATE " + FAVOURITE_TABLE_NAME + " SET latitude = ?, longitude = ? WHERE " + whereNameLatLon(), new Object[] { lat, lon, p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + "UPDATE " + FAVOURITE_TABLE_NAME + " SET latitude = ?, longitude = ? WHERE " + whereNameLatLon(), new Object[]{lat, lon, p.getName(), p.getLatitude(), p.getLongitude()}); //$NON-NLS-1$ //$NON-NLS-2$ p.setLatitude(lat); p.setLongitude(lon); saveCurrentPointsIntoFile(); @@ -826,6 +836,4 @@ public class FavouritesDbHelper { } - - } diff --git a/OsmAnd/src/net/osmand/plus/MapMarkersHelper.java b/OsmAnd/src/net/osmand/plus/MapMarkersHelper.java index 5b58d6e20e..501f009d7e 100644 --- a/OsmAnd/src/net/osmand/plus/MapMarkersHelper.java +++ b/OsmAnd/src/net/osmand/plus/MapMarkersHelper.java @@ -1,24 +1,40 @@ package net.osmand.plus; import android.content.Context; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.text.format.DateFormat; +import net.osmand.IndexConstants; +import net.osmand.data.FavouritePoint; import net.osmand.data.LatLon; import net.osmand.data.LocationPoint; import net.osmand.data.PointDescription; +import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.util.Algorithms; +import java.io.File; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import java.util.Locale; + +import static net.osmand.data.PointDescription.POINT_TYPE_MAP_MARKER; public class MapMarkersHelper { public static final int MAP_MARKERS_COLORS_COUNT = 7; - private List mapMarkers = new ArrayList<>(); - private List mapMarkersHistory = new ArrayList<>(); + private List mapMarkers = new LinkedList<>(); + private List mapMarkersHistory = new LinkedList<>(); private OsmandSettings settings; private List listeners = new ArrayList<>(); private OsmandApplication ctx; + private MapMarkersDbHelper markersDbHelper; private boolean startFromMyLocation; public interface MapMarkerChangedListener { @@ -28,6 +44,7 @@ public class MapMarkersHelper { } public static class MapMarker implements LocationPoint { + public String id; public LatLon point; private PointDescription pointDescription; public int colorIndex; @@ -36,19 +53,22 @@ public class MapMarkersHelper { public boolean selected; public int dist; public long creationDate; + public long visitedDate; + public String nextKey; + public String groupKey; + public String groupName; public MapMarker(LatLon point, PointDescription name, int colorIndex, - boolean selected, long creationDate, int index) { + boolean selected, int index) { this.point = point; this.pointDescription = name; this.colorIndex = colorIndex; this.selected = selected; - this.creationDate = creationDate; this.index = index; } public PointDescription getPointDescription(Context ctx) { - return new PointDescription(PointDescription.POINT_TYPE_MAP_MARKER, ctx.getString(R.string.map_marker), + return new PointDescription(POINT_TYPE_MAP_MARKER, ctx.getString(R.string.map_marker), getOnlyName()); } @@ -139,11 +159,40 @@ public class MapMarkersHelper { } } + public static class MarkersSyncGroup { + + public static final int FAVORITES_TYPE = 0; + public static final int GPX_TYPE = 1; + + private String id; + private String name; + private int type; + + public MarkersSyncGroup(@NonNull String id, @NonNull String name, int type) { + this.id = id; + this.name = name; + this.type = type; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public int getType() { + return type; + } + } + public MapMarkersHelper(OsmandApplication ctx) { this.ctx = ctx; settings = ctx.getSettings(); + markersDbHelper = ctx.getMapMarkersDbHelper(); startFromMyLocation = settings.ROUTE_MAP_MARKERS_START_MY_LOC.get(); - readFromSettings(); + loadMarkers(); } public boolean isStartFromMyLocation() { @@ -157,86 +206,212 @@ public class MapMarkersHelper { public void lookupAddressAll() { for (MapMarker mapMarker : mapMarkers) { - lookupAddress(mapMarker, false); + lookupAddress(mapMarker); } for (MapMarker mapMarker : mapMarkersHistory) { - lookupAddress(mapMarker, true); + lookupAddress(mapMarker); } } - private void readFromSettings() { + private void loadMarkers() { mapMarkers.clear(); mapMarkersHistory.clear(); - List ips = settings.getMapMarkersPoints(); - List desc = settings.getMapMarkersPointDescriptions(ips.size()); - List colors = settings.getMapMarkersColors(ips.size()); - List selections = settings.getMapMarkersSelections(ips.size()); - List creationDates = settings.getMapMarkersCreationDates(ips.size()); - int colorIndex = 0; - for (int i = 0; i < ips.size(); i++) { - if (colors.size() > i) { - colorIndex = colors.get(i); - } - MapMarker mapMarker = new MapMarker(ips.get(i), - PointDescription.deserializeFromString(desc.get(i), ips.get(i)), colorIndex, - selections.get(i), creationDates.get(i), i); - mapMarkers.add(mapMarker); - } - ips = settings.getMapMarkersHistoryPoints(); - desc = settings.getMapMarkersHistoryPointDescriptions(ips.size()); - colors = settings.getMapMarkersHistoryColors(ips.size()); - creationDates = settings.getMapMarkersHistoryCreationDates(ips.size()); - for (int i = 0; i < ips.size(); i++) { - if (colors.size() > i) { - colorIndex = colors.get(i); - } - MapMarker mapMarker = new MapMarker(ips.get(i), - PointDescription.deserializeFromString(desc.get(i), ips.get(i)), - colorIndex, false, creationDates.get(i), i); - mapMarker.history = true; - mapMarkersHistory.add(mapMarker); - } + List activeMarkers = markersDbHelper.getActiveMarkers(); + mapMarkers.addAll(activeMarkers); + checkAndFixActiveMarkersOrderIfNeeded(); + + List markersHistory = markersDbHelper.getMarkersHistory(); + sortMarkers(markersHistory, true); + mapMarkersHistory.addAll(markersHistory); if (!ctx.isApplicationInitializing()) { lookupAddressAll(); } } - private void lookupAddress(final MapMarker mapMarker, final boolean history) { + public void checkAndFixActiveMarkersOrderIfNeeded() { + if (!mapMarkers.isEmpty()) { + if (mapMarkers.size() > 1) { + for (int i = 0; i < mapMarkers.size() - 1; i++) { + MapMarker first = mapMarkers.get(i); + MapMarker second = mapMarkers.get(i + 1); + if (!first.nextKey.equals(second.id)) { + markersDbHelper.changeActiveMarkerPosition(first, second); + first.nextKey = second.id; + } + } + } + + MapMarker tail = mapMarkers.get(mapMarkers.size() - 1); + if (!tail.nextKey.equals(MapMarkersDbHelper.TAIL_NEXT_VALUE)) { + markersDbHelper.changeActiveMarkerPosition(tail, null); + } + } + } + + private void sortMarkers(List markers, final boolean history) { + Collections.sort(markers, new Comparator() { + @Override + public int compare(MapMarker mapMarker1, MapMarker mapMarker2) { + long firstMarkerDate = history ? mapMarker1.visitedDate : mapMarker1.creationDate; + long secondMarkerDate = history ? mapMarker2.visitedDate : mapMarker2.creationDate; + if (firstMarkerDate > secondMarkerDate) { + return -1; + } else if (firstMarkerDate == secondMarkerDate) { + return 0; + } else { + return 1; + } + } + }); + } + + private void lookupAddress(final MapMarker mapMarker) { if (mapMarker != null && mapMarker.pointDescription.isSearchingAddress(ctx)) { cancelPointAddressRequests(mapMarker.point); - GeocodingLookupService.AddressLookupRequest lookupRequest = new GeocodingLookupService.AddressLookupRequest(mapMarker.point, new GeocodingLookupService.OnAddressLookupResult() { - @Override - public void geocodingDone(String address) { - if (Algorithms.isEmpty(address)) { - mapMarker.pointDescription.setName(PointDescription.getAddressNotFoundStr(ctx)); - } else { - mapMarker.pointDescription.setName(address); - } - if (history) { - settings.updateMapMarkerHistory(mapMarker.point.getLatitude(), mapMarker.point.getLongitude(), - mapMarker.pointDescription, mapMarker.colorIndex, mapMarker.creationDate); - } else { - settings.updateMapMarker(mapMarker.point.getLatitude(), mapMarker.point.getLongitude(), - mapMarker.pointDescription, mapMarker.colorIndex, mapMarker.selected, mapMarker.creationDate); - } - updateMarker(mapMarker); - } - }, null); + GeocodingLookupService.AddressLookupRequest lookupRequest = + new GeocodingLookupService.AddressLookupRequest(mapMarker.point, new GeocodingLookupService.OnAddressLookupResult() { + @Override + public void geocodingDone(String address) { + if (Algorithms.isEmpty(address)) { + mapMarker.pointDescription.setName(PointDescription.getAddressNotFoundStr(ctx)); + } else { + mapMarker.pointDescription.setName(address); + } + markersDbHelper.updateMarker(mapMarker); + updateMarker(mapMarker); + } + }, null); ctx.getGeocodingLookupService().lookupAddress(lookupRequest); } } - public void removeMapMarker(int index) { - settings.deleteMapMarker(index); - MapMarker mapMarker = mapMarkers.remove(index); - cancelPointAddressRequests(mapMarker.point); - int ind = 0; - for (MapMarker marker : mapMarkers) { - marker.index = ind++; + public void syncAllGroups() { + List groups = markersDbHelper.getAllGroups(); + for (MarkersSyncGroup gr : groups) { + syncGroup(gr); + } + } + + public void syncGroup(MarkersSyncGroup group) { + if (markersDbHelper.getGroup(group.getId()) == null) { + return; + } + List dbMarkers = markersDbHelper.getMarkersFromGroup(group); + + if (group.getType() == MarkersSyncGroup.FAVORITES_TYPE) { + FavouritesDbHelper.FavoriteGroup favGroup = ctx.getFavorites().getGroup(group.name); + if (favGroup == null) { + return; + } + if (!favGroup.visible) { + removeActiveMarkersFromSyncGroup(group.id); + return; + } + List favPoints = favGroup.points; + for (FavouritePoint fp : favPoints) { + LatLon fpLatLon = new LatLon(fp.getLatitude(), fp.getLongitude()); + boolean exists = false; + + for (MapMarker marker : dbMarkers) { + if (marker.id.equals(group.getId() + fp.getName(ctx))) { + exists = true; + if (!marker.history && !marker.point.equals(fpLatLon)) { + for (MapMarker m : mapMarkers) { + if (m.id.equals(marker.id)) { + m.point = fpLatLon; + updateMapMarker(m, true); + break; + } + } + } + dbMarkers.remove(marker); + break; + } + } + + if (!exists) { + addMarkers(Collections.singletonList(fpLatLon), + Collections.singletonList(new PointDescription(POINT_TYPE_MAP_MARKER, fp.getName())), group); + } + } + + if (!dbMarkers.isEmpty()) { + for (MapMarker marker : dbMarkers) { + if (!marker.history) { + markersDbHelper.removeMarker(marker, false); + mapMarkers.remove(marker); + checkAndFixActiveMarkersOrderIfNeeded(); + refresh(); + } + } + } + } else { + + } + } + + public void moveMapMarkerToHistory(MapMarker marker) { + if (marker != null) { + cancelPointAddressRequests(marker.point); + markersDbHelper.moveMarkerToHistory(marker); + mapMarkers.remove(marker); + marker.history = true; + marker.nextKey = MapMarkersDbHelper.HISTORY_NEXT_VALUE; + mapMarkersHistory.add(marker); + checkAndFixActiveMarkersOrderIfNeeded(); + sortMarkers(mapMarkersHistory, true); + refresh(); + } + } + + public void addMarker(MapMarker marker) { + if (marker != null) { + markersDbHelper.addMarker(marker); + if (marker.history) { + mapMarkersHistory.add(marker); + sortMarkers(mapMarkersHistory, true); + } else { + mapMarkers.add(marker); + checkAndFixActiveMarkersOrderIfNeeded(); + } + refresh(); + } + } + + public void restoreMarkerFromHistory(MapMarker marker, int position) { + if (marker != null) { + markersDbHelper.restoreMapMarkerFromHistory(marker); + mapMarkersHistory.remove(marker); + marker.history = false; + mapMarkers.add(position, marker); + checkAndFixActiveMarkersOrderIfNeeded(); + sortMarkers(mapMarkersHistory, true); + refresh(); + } + } + + public void restoreMarkersFromHistory(List markers) { + if (markers != null) { + for (MapMarker marker : markers) { + markersDbHelper.restoreMapMarkerFromHistory(marker); + mapMarkersHistory.remove(marker); + marker.history = false; + mapMarkers.add(marker); + } + checkAndFixActiveMarkersOrderIfNeeded(); + sortMarkers(mapMarkersHistory, true); + refresh(); + } + } + + public void removeMarkerFromHistory(MapMarker marker) { + if (marker != null) { + markersDbHelper.removeMarker(marker, true); + mapMarkersHistory.remove(marker); + refresh(); } - refresh(); } public List getMapMarkers() { @@ -293,58 +468,73 @@ public class MapMarkersHelper { public void reverseActiveMarkersOrder() { cancelAddressRequests(); - - List markers = new ArrayList<>(mapMarkers.size()); - for (int i = mapMarkers.size() - 1; i >= 0; i--) { - MapMarker marker = mapMarkers.get(i); - markers.add(marker); - } - mapMarkers = markers; - saveMapMarkers(mapMarkers, null); + Collections.reverse(mapMarkers); + checkAndFixActiveMarkersOrderIfNeeded(); } - public void removeActiveMarkers() { + public void moveAllActiveMarkersToHistory() { cancelAddressRequests(); - for (int i = mapMarkers.size() - 1; i>= 0; i--) { - MapMarker marker = mapMarkers.get(i); - addMapMarkerHistory(marker); + long timestamp = System.currentTimeMillis(); + markersDbHelper.moveAllActiveMarkersToHistory(timestamp); + for (MapMarker marker : mapMarkers) { + marker.visitedDate = timestamp; + marker.history = true; + marker.nextKey = MapMarkersDbHelper.HISTORY_NEXT_VALUE; } - settings.clearActiveMapMarkers(); - readFromSettings(); + mapMarkersHistory.addAll(mapMarkers); + mapMarkers.clear(); + sortMarkers(mapMarkersHistory, true); refresh(); } public void removeMarkersHistory() { cancelAddressRequests(); - settings.clearMapMarkersHistory(); - readFromSettings(); + markersDbHelper.clearAllMarkersHistory(); + mapMarkersHistory.clear(); refresh(); } - public void addMapMarker(MapMarker marker, int index) { - settings.insertMapMarker(marker.getLatitude(), marker.getLongitude(), marker.pointDescription, - marker.colorIndex, marker.selected, marker.creationDate, index); - readFromSettings(); + public void addMarkersSyncGroup(MarkersSyncGroup group) { + if (group != null) { + if (markersDbHelper.getGroup(group.getId()) == null) { + markersDbHelper.addGroup(group.getId(), group.getName(), group.getType()); + } + } + } + + public void removeMarkersSyncGroup(String id, boolean removeActiveMarkers) { + if (id != null) { + markersDbHelper.removeMarkersSyncGroup(id); + if (removeActiveMarkers) { + removeActiveMarkersFromSyncGroup(id); + } + } + } + + public void removeActiveMarkersFromSyncGroup(String syncGroupId) { + if (syncGroupId != null) { + markersDbHelper.removeActiveMarkersFromSyncGroup(syncGroupId); + for (Iterator iterator = mapMarkers.iterator(); iterator.hasNext(); ) { + if (iterator.next().groupKey.equals(syncGroupId)) { + iterator.remove(); + } + } + checkAndFixActiveMarkersOrderIfNeeded(); + refresh(); + } } public void addMapMarker(LatLon point, PointDescription historyName) { - List points = new ArrayList<>(1); - List historyNames = new ArrayList<>(1); - points.add(point); - historyNames.add(historyName); - addMapMarkers(points, historyNames); + addMarkers(Collections.singletonList(point), Collections.singletonList(historyName), null); } - public void addMapMarkers(List points, List historyNames) { + public void addMapMarkers(List points, List historyNames, @Nullable MarkersSyncGroup group) { + addMarkers(points, historyNames, group); + } + + private void addMarkers(List points, List historyNames, @Nullable MarkersSyncGroup group) { if (points.size() > 0) { int colorIndex = -1; - double[] latitudes = new double[points.size()]; - double[] longitudes = new double[points.size()]; - List pointDescriptions = new ArrayList<>(); - int[] colorIndexes = new int[points.size()]; - int[] positions = new int[points.size()]; - boolean[] selections = new boolean[points.size()]; - int[] indexes = new int[points.size()]; for (int i = 0; i < points.size(); i++) { LatLon point = points.get(i); PointDescription historyName = historyNames.get(i); @@ -359,7 +549,7 @@ public class MapMarkersHelper { } if (colorIndex == -1) { if (mapMarkers.size() > 0) { - colorIndex = (mapMarkers.get(0).colorIndex + 1) % MAP_MARKERS_COLORS_COUNT; + colorIndex = (mapMarkers.get(mapMarkers.size() - 1).colorIndex + 1) % MAP_MARKERS_COLORS_COUNT; } else { colorIndex = 0; } @@ -367,33 +557,28 @@ public class MapMarkersHelper { colorIndex = (colorIndex + 1) % MAP_MARKERS_COLORS_COUNT; } - latitudes[i] = point.getLatitude(); - longitudes[i] = point.getLongitude(); - pointDescriptions.add(pointDescription); - colorIndexes[i] = colorIndex; - positions[i] = -1 - i; - selections[i] = false; - indexes[i] = 0; + MapMarker marker = new MapMarker(point, pointDescription, colorIndex, false, 0); + if (group != null) { + marker.id = group.getId() + marker.getName(ctx); + if (markersDbHelper.getMarker(marker.id) != null) { + continue; + } + marker.groupName = group.getName(); + marker.groupKey = group.getId(); + } + marker.history = false; + marker.nextKey = MapMarkersDbHelper.TAIL_NEXT_VALUE; + markersDbHelper.addMarker(marker); + mapMarkers.add(marker); + checkAndFixActiveMarkersOrderIfNeeded(); } - /* adding map marker to second topbar's row - if (sortedMapMarkers.size() > 0) { - MapMarker firstMarker = sortedMapMarkers.get(0); - settings.updateMapMarker(firstMarker.getLatitude(), firstMarker.getLongitude(), - firstMarker.pointDescription, firstMarker.colorIndex, -points.size(), firstMarker.selected); - } - */ - settings.insertMapMarkers(latitudes, longitudes, pointDescriptions, colorIndexes, positions, - selections, indexes); - readFromSettings(); } } public void updateMapMarker(MapMarker marker, boolean refresh) { if (marker != null) { - settings.updateMapMarker(marker.getLatitude(), marker.getLongitude(), - marker.pointDescription, marker.colorIndex, marker.selected, marker.creationDate); + markersDbHelper.updateMarker(marker); if (refresh) { - readFromSettings(); refresh(); } } @@ -401,35 +586,24 @@ public class MapMarkersHelper { public void moveMapMarker(@Nullable MapMarker marker, LatLon latLon) { if (marker != null) { - settings.moveMapMarker(new LatLon(marker.getLatitude(), marker.getLongitude()), latLon, - marker.pointDescription, marker.colorIndex, marker.selected, marker.creationDate); - marker.point = new LatLon(latLon.getLatitude(), latLon.getLongitude()); - readFromSettings(); + LatLon point = new LatLon(latLon.getLatitude(), latLon.getLongitude()); + int index = mapMarkers.indexOf(marker); + if (index != -1) { + mapMarkers.get(index).point = point; + } + marker.point = point; + markersDbHelper.updateMarker(marker); + checkAndFixActiveMarkersOrderIfNeeded(); refresh(); } } - public void removeMapMarker(MapMarker marker) { - if (marker != null) { - settings.deleteMapMarker(marker.index); - readFromSettings(); - refresh(); - } - } - - public void addMapMarkerHistory(MapMarker marker) { - if (marker != null) { - settings.insertMapMarkerHistory(marker.getLatitude(), marker.getLongitude(), - marker.pointDescription, marker.colorIndex, marker.creationDate, 0); - readFromSettings(); - refresh(); - } - } - - public void removeMapMarkerHistory(MapMarker marker) { - if (marker != null) { - settings.deleteMapMarkerHistory(marker.index); - readFromSettings(); + public void moveMarkerToTop(MapMarker marker) { + int i = mapMarkers.indexOf(marker); + if (i != -1 && mapMarkers.size() > 1) { + mapMarkers.remove(i); + mapMarkers.add(0, marker); + checkAndFixActiveMarkersOrderIfNeeded(); refresh(); } } @@ -466,7 +640,7 @@ public class MapMarkersHelper { } if (markers != null || markersHistory != null) { - readFromSettings(); + loadMarkers(); refresh(); } } @@ -513,4 +687,28 @@ public class MapMarkersHelper { ctx.getGeocodingLookupService().cancel(latLon); } } + + public void generateGpx() { + final File dir = ctx.getAppPath(IndexConstants.GPX_INDEX_DIR + "/map markers"); + if (!dir.exists()) { + dir.mkdirs(); + } + Date date = new Date(); + String fileName = DateFormat.format("yyyy-MM-dd", date).toString() + "_" + new SimpleDateFormat("HH-mm_EEE", Locale.US).format(date); + File fout = new File(dir, fileName + ".gpx"); + int ind = 1; + while (fout.exists()) { + fout = new File(dir, fileName + "_" + (++ind) + ".gpx"); + } + GPXUtilities.GPXFile file = new GPXUtilities.GPXFile(); + for (MapMarker marker : markersDbHelper.getActiveMarkers()) { + GPXUtilities.WptPt wpt = new GPXUtilities.WptPt(); + wpt.lat = marker.getLatitude(); + wpt.lon = marker.getLongitude(); + wpt.setColor(ctx.getResources().getColor(MapMarker.getColorId(marker.colorIndex))); + wpt.name = marker.getOnlyName(); + file.points.add(wpt); + } + GPXUtilities.writeGpxFile(fout, file, ctx); + } } diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index ca3046da0a..53b1938ad2 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -47,6 +47,7 @@ import net.osmand.plus.helpers.AvoidSpecificRoads; import net.osmand.plus.helpers.WaypointHelper; import net.osmand.plus.inapp.InAppHelper; import net.osmand.plus.mapcontextmenu.other.RoutePreferencesMenu; +import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.poi.PoiFiltersHelper; import net.osmand.plus.render.RendererRegistry; @@ -107,6 +108,7 @@ public class OsmandApplication extends MultiDexApplication { LiveMonitoringHelper liveMonitoringHelper; TargetPointsHelper targetPointsHelper; MapMarkersHelper mapMarkersHelper; + MapMarkersDbHelper mapMarkersDbHelper; WaypointHelper waypointHelper; DownloadIndexesThread downloadIndexesThread; AvoidSpecificRoads avoidSpecificRoads; @@ -615,6 +617,10 @@ public class OsmandApplication extends MultiDexApplication { return mapMarkersHelper; } + public MapMarkersDbHelper getMapMarkersDbHelper() { + return mapMarkersDbHelper; + } + public void showShortToastMessage(final int msgId, final Object... args) { uiHandler.post(new Runnable() { @Override diff --git a/OsmAnd/src/net/osmand/plus/OsmandBackupAgent.java b/OsmAnd/src/net/osmand/plus/OsmandBackupAgent.java index 32b3b91122..791dc15c0e 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandBackupAgent.java +++ b/OsmAnd/src/net/osmand/plus/OsmandBackupAgent.java @@ -6,6 +6,8 @@ import android.app.backup.BackupAgentHelper; import android.app.backup.FileBackupHelper; import android.app.backup.SharedPreferencesBackupHelper; +import net.osmand.plus.mapmarkers.MapMarkersDbHelper; + /** * Requires android API from android-8 */ @@ -25,7 +27,7 @@ public class OsmandBackupAgent extends BackupAgentHelper { SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, prefs); addHelper("osmand.settings", helper); - FileBackupHelper fileBackupHelper = new FileBackupHelper(this, FavouritesDbHelper.FILE_TO_BACKUP); - addHelper(FavouritesDbHelper.FILE_TO_BACKUP, fileBackupHelper); + FileBackupHelper fileBackupHelper = new FileBackupHelper(this, FavouritesDbHelper.FILE_TO_BACKUP, "../databases/" + MapMarkersDbHelper.DB_NAME); + addHelper("osmand.files", fileBackupHelper); } } diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index f2f6b625a2..29a0d165b5 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -855,6 +855,9 @@ public class OsmandSettings { public final OsmandPreference SPEED_LIMIT_EXCEED = new FloatPreference("speed_limit_exceed", 5f).makeProfile(); + public final OsmandPreference SWITCH_MAP_DIRECTION_TO_COMPASS = + new FloatPreference("speed_for_map_to_direction_of_movement", 0f).makeProfile(); + // this value string is synchronized with settings_pref.xml preference name public final OsmandPreference USE_TRACKBALL_FOR_MOVEMENTS = new BooleanPreference("use_trackball_for_movements", true).makeGlobal(); diff --git a/OsmAnd/src/net/osmand/plus/activities/EditFavoriteGroupDialogFragment.java b/OsmAnd/src/net/osmand/plus/activities/EditFavoriteGroupDialogFragment.java index af747429e6..722c0bf019 100644 --- a/OsmAnd/src/net/osmand/plus/activities/EditFavoriteGroupDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/EditFavoriteGroupDialogFragment.java @@ -30,6 +30,7 @@ import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.IconsCache; import net.osmand.plus.MapMarkersHelper; +import net.osmand.plus.MapMarkersHelper.MarkersSyncGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.base.BottomSheetDialogFragment; @@ -188,7 +189,9 @@ public class EditFavoriteGroupDialogFragment extends BottomSheetDialogFragment { points.add(new LatLon(fp.getLatitude(), fp.getLongitude())); names.add(new PointDescription(PointDescription.POINT_TYPE_MAP_MARKER, fp.getName())); } - markersHelper.addMapMarkers(points, names); + MarkersSyncGroup syncGroup = new MarkersSyncGroup(group.name, group.name, MarkersSyncGroup.FAVORITES_TYPE); + markersHelper.addMarkersSyncGroup(syncGroup); + markersHelper.addMapMarkers(points, names, syncGroup); dismiss(); MapActivity.launchMapActivityMoveToTop(getActivity()); } diff --git a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java index d038d93105..e187024fd6 100644 --- a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java @@ -36,6 +36,7 @@ import net.osmand.data.PointDescription; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.MapMarkersHelper; +import net.osmand.plus.MapMarkersHelper.MarkersSyncGroup; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; @@ -57,6 +58,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -80,7 +82,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { private OsmandApplication app; private boolean selectionMode = false; - private Set favoritesSelected = new LinkedHashSet<>(); + private LinkedHashMap> favoritesSelected = new LinkedHashMap<>(); private Set groupsToDelete = new LinkedHashSet<>(); private ActionMode actionMode; Drawable arrowImage; @@ -127,7 +129,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { @Override protected String doInBackground(Void... params) { - helper.delete(groupsToDelete, favoritesSelected); + helper.delete(groupsToDelete, getSelectedFavorites()); favoritesSelected.clear(); groupsToDelete.clear(); return getString(R.string.favourites_delete_multiple_succesful); @@ -206,14 +208,35 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { initListExpandedState(); } + private int getSelectedFavoritesCount() { + int count = 0; + for (Set set : favoritesSelected.values()) { + if (set != null) { + count += set.size(); + } + } + return count; + } + + private Set getSelectedFavorites() { + Set result = new LinkedHashSet<>(); + for (Set set : favoritesSelected.values()) { + if (set != null) { + result.addAll(set); + } + } + return result; + } + public void reloadData() { favouritesAdapter.synchronizeGroups(); favouritesAdapter.notifyDataSetInvalidated(); } private void updateSelectionMode(ActionMode m) { - if (favoritesSelected.size() > 0) { - m.setTitle(favoritesSelected.size() + " " + getMyApplication().getString(R.string.shared_string_selected_lowercase)); + int size = getSelectedFavoritesCount(); + if (size > 0) { + m.setTitle(size + " " + getMyApplication().getString(R.string.shared_string_selected_lowercase)); } else { m.setTitle(""); } @@ -224,11 +247,22 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { if (selectionMode) { CheckBox ch = (CheckBox) v.findViewById(R.id.toggle_item); FavouritePoint model = favouritesAdapter.getChild(groupPosition, childPosition); + FavoriteGroup group = favouritesAdapter.getGroup(groupPosition); ch.setChecked(!ch.isChecked()); if (ch.isChecked()) { - favoritesSelected.add(model); + Set set = favoritesSelected.get(group.name); + if (set != null) { + set.add(model); + } else { + set = new LinkedHashSet<>(); + set.add(model); + favoritesSelected.put(group.name, set); + } } else { - favoritesSelected.remove(model); + Set set = favoritesSelected.get(group.name); + if (set != null) { + set.remove(model); + } } updateSelectionMode(actionMode); } else { @@ -308,14 +342,14 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { public void showProgressBar() { OsmandActionBarActivity activity = getActionBarActivity(); - if(activity != null) { + if (activity != null) { activity.setSupportProgressBarIndeterminateVisibility(true); } } public void hideProgressBar() { OsmandActionBarActivity activity = getActionBarActivity(); - if(activity != null) { + if (activity != null) { activity.setSupportProgressBarIndeterminateVisibility(false); } } @@ -366,20 +400,29 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { } private void selectMapMarkersImpl() { - if(!favoritesSelected.isEmpty()) { + if (getSelectedFavoritesCount() > 0) { if (getSettings().USE_MAP_MARKERS.get()) { MapMarkersHelper markersHelper = getMyApplication().getMapMarkersHelper(); - List points = new ArrayList<>(favoritesSelected.size()); - List names = new ArrayList<>(favoritesSelected.size()); - for (FavouritePoint fp : favoritesSelected) { - points.add(new LatLon(fp.getLatitude(), fp.getLongitude())); - names.add(new PointDescription(PointDescription.POINT_TYPE_MAP_MARKER, fp.getName())); + List points = new LinkedList<>(); + List names = new LinkedList<>(); + for (Map.Entry> entry : favoritesSelected.entrySet()) { + FavoriteGroup favGr = helper.getGroup(entry.getKey()); + MarkersSyncGroup syncGr = new MarkersSyncGroup(favGr.name, favGr.name, MarkersSyncGroup.FAVORITES_TYPE); + if (entry.getValue().size() == favGr.points.size()) { + markersHelper.addMarkersSyncGroup(syncGr); + } + for (FavouritePoint fp : entry.getValue()) { + points.add(new LatLon(fp.getLatitude(), fp.getLongitude())); + names.add(new PointDescription(PointDescription.POINT_TYPE_MAP_MARKER, fp.getName())); + } + markersHelper.addMapMarkers(points, names, syncGr); + points.clear(); + names.clear(); } - markersHelper.addMapMarkers(points, names); MapActivity.launchMapActivityMoveToTop(getActivity()); } else { final TargetPointsHelper targetPointsHelper = getMyApplication().getTargetPointsHelper(); - for (FavouritePoint fp : favoritesSelected) { + for (FavouritePoint fp : getSelectedFavorites()) { targetPointsHelper.navigateToPoint(new LatLon(fp.getLatitude(), fp.getLongitude()), false, targetPointsHelper.getIntermediatePoints().size() + 1, new PointDescription(PointDescription.POINT_TYPE_FAVORITE, fp.getName())); @@ -441,10 +484,11 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { } private void deleteFavoritesAction() { - if (groupsToDelete.size() + favoritesSelected.size() > 0) { + int size = getSelectedFavoritesCount(); + if (groupsToDelete.size() + size > 0) { AlertDialog.Builder b = new AlertDialog.Builder(getActivity()); - b.setMessage(getString(R.string.favorite_delete_multiple, favoritesSelected.size(), groupsToDelete.size())); + b.setMessage(getString(R.string.favorite_delete_multiple, size, groupsToDelete.size())); b.setPositiveButton(R.string.shared_string_delete, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -458,18 +502,18 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { b.show(); } } - + private StringBuilder generateHtmlPrint(List groups) { StringBuilder html = new StringBuilder(); html.append("

My Favorites

"); for (FavoriteGroup group : groups) { - html.append("

"+group.name+"

"); - for(FavouritePoint fp : group.points) { - String url = "geo:"+((float)fp.getLatitude())+","+((float)fp.getLongitude())+"?m="+fp.getName(); + html.append("

" + group.name + "

"); + for (FavouritePoint fp : group.points) { + String url = "geo:" + ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "?m=" + fp.getName(); html.append("

" + fp.getName() + " - " + "geo:" + ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "
"); - - if(!Algorithms.isEmpty(fp.getDescription())) { + + if (!Algorithms.isEmpty(fp.getDescription())) { html.append(": " + fp.getDescription()); } html.append("

"); @@ -521,7 +565,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { @Override protected void onPostExecute(Void res) { hideProgressBar(); - if(getActivity() == null) { + if (getActivity() == null) { // user quit application return; } @@ -763,13 +807,17 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { if (ch.isChecked()) { groupsToDelete.add(model); if (fvs != null) { - favoritesSelected.addAll(fvs); + Set set = favoritesSelected.get(model.name); + if (set != null) { + set.addAll(model.points); + } else { + set = new LinkedHashSet<>(model.points); + favoritesSelected.put(model.name, set); + } } } else { groupsToDelete.remove(model); - if (fvs != null) { - favoritesSelected.removeAll(fvs); - } + favoritesSelected.remove(model.name); } favouritesAdapter.notifyDataSetInvalidated(); updateSelectionMode(actionMode); @@ -820,6 +868,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { ImageView icon = (ImageView) row.findViewById(R.id.favourite_icon); final FavouritePoint model = getChild(groupPosition, childPosition); + final FavoriteGroup group = getGroup(groupPosition); boolean visible = model.isVisible(); row.setTag(model); @@ -864,16 +913,26 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment { final CheckBox ch = (CheckBox) row.findViewById(R.id.toggle_item); if (selectionMode) { ch.setVisibility(View.VISIBLE); - ch.setChecked(favoritesSelected.contains(model)); + ch.setChecked(favoritesSelected.get(group.name) != null && favoritesSelected.get(group.name).contains(model)); row.findViewById(R.id.favourite_icon).setVisibility(View.GONE); ch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ch.isChecked()) { - favoritesSelected.add(model); + Set set = favoritesSelected.get(group.name); + if (set != null) { + set.add(model); + } else { + set = new LinkedHashSet<>(); + set.add(model); + favoritesSelected.put(group.name, set); + } } else { - favoritesSelected.remove(model); + Set set = favoritesSelected.get(group.name); + if (set != null) { + set.remove(model); + } } updateSelectionMode(actionMode); } diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java index 8187f17f61..92f0a4aa9a 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java @@ -614,18 +614,6 @@ public class MapActivityActions implements DialogProvider { }).createItem()); if (settings.USE_MAP_MARKERS.get()) { optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.map_markers, mapActivity) - .setIcon(R.drawable.ic_action_flag_dark) - .setListener(new ContextMenuAdapter.ItemClickListener() { - @Override - public boolean onContextMenuClick(ArrayAdapter adapter, int itemId, int pos, boolean isChecked) { - app.logEvent(mapActivity, "drawer_markers_open"); - MapActivity.clearPrevActivityIntent(); - mapActivity.getDashboard().setDashboardVisibility(true, DashboardType.MAP_MARKERS); - return false; - } - }).createItem()); - - optionsMenuHelper.addItem(new ItemBuilder().setTitle("New map markers") .setIcon(R.drawable.ic_action_flag_dark) .setListener(new ContextMenuAdapter.ItemClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsNavigationActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsNavigationActivity.java index eda15c2989..7978fe9b15 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsNavigationActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsNavigationActivity.java @@ -202,12 +202,14 @@ public class SettingsNavigationActivity extends SettingsBaseActivity { speedNames[i] = speedLimitsKm[i] + " " + getString(R.string.km_h); } registerListPreference(settings.SPEED_LIMIT_EXCEED, screen, speedNames, speedLimitsKm); + registerListPreference(settings.SWITCH_MAP_DIRECTION_TO_COMPASS, screen, speedNames, speedLimitsKm); } else { String[] speedNames = new String[speedLimitsKm.length]; for (int i =0; i 1) { mapView.setRotate(-val); } @@ -201,13 +203,17 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc zoom = autozoom(location); } int currentMapRotation = settings.ROTATE_MAP.get(); + float speedForDirectionOfMovement = settings.SWITCH_MAP_DIRECTION_TO_COMPASS.get(); + boolean smallSpeedForDirectionOfMovement = speedForDirectionOfMovement != 0 && isSmallSpeedForDirectionOfMovement(location, speedForDirectionOfMovement); boolean smallSpeedForCompass = isSmallSpeedForCompass(location); boolean smallSpeedForAnimation = isSmallSpeedForAnimation(location); // boolean virtualBearing = fMode && settings.SNAP_TO_ROAD.get(); showViewAngle = (!location.hasBearing() || smallSpeedForCompass) && (tb != null && tb.containsLatLon(location.getLatitude(), location.getLongitude())); if (currentMapRotation == OsmandSettings.ROTATE_MAP_BEARING) { - if (location.hasBearing() && !smallSpeedForCompass) { + if (smallSpeedForDirectionOfMovement) { + showViewAngle = routePlanningMode; + } else if (location.hasBearing() && !smallSpeedForCompass) { // special case when bearing equals to zero (we don't change anything) if (location.getBearing() != 0f) { rotation = -location.getBearing(); @@ -216,7 +222,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc } else if(currentMapRotation == OsmandSettings.ROTATE_MAP_COMPASS) { showViewAngle = routePlanningMode; // disable compass rotation in that mode } - registerUnregisterSensor(location); + registerUnregisterSensor(location, smallSpeedForDirectionOfMovement); if (settings.ANIMATE_MY_LOCATION.get() && !smallSpeedForAnimation && !movingToMyLocation && settings.WAKE_ON_VOICE_INT.get() == 0) { mapView.getAnimatedDraggingThread().startMoving( @@ -233,7 +239,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc } else if(location != null) { showViewAngle = (!location.hasBearing() || isSmallSpeedForCompass(location)) && (tb != null && tb.containsLatLon(location.getLatitude(), location.getLongitude())); - registerUnregisterSensor(location); + registerUnregisterSensor(location, false); } RoutingHelper routingHelper = app.getRoutingHelper(); followingMode = routingHelper.isFollowingMode(); @@ -252,6 +258,10 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc } } + public static boolean isSmallSpeedForDirectionOfMovement(Location location, float speedToDirectionOfMovement) { + return !location.hasSpeed() || location.getSpeed() < speedToDirectionOfMovement; + } + public static boolean isSmallSpeedForCompass(Location location) { return !location.hasSpeed() || location.getSpeed() < 0.5; } @@ -285,14 +295,15 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc && !settings.CENTER_POSITION_ON_MAP.get() ? OsmandSettings.BOTTOM_CONSTANT : OsmandSettings.CENTER_CONSTANT); } - registerUnregisterSensor(app.getLocationProvider().getLastKnownLocation()); + registerUnregisterSensor(app.getLocationProvider().getLastKnownLocation(), false); } - private void registerUnregisterSensor(net.osmand.Location location) { + private void registerUnregisterSensor(net.osmand.Location location, boolean smallSpeedForDirectionOfMovement) { int currentMapRotation = settings.ROTATE_MAP.get(); boolean registerCompassListener = ((showViewAngle || contextMenu != null) && location != null) - || (currentMapRotation == OsmandSettings.ROTATE_MAP_COMPASS && !routePlanningMode); + || (currentMapRotation == OsmandSettings.ROTATE_MAP_COMPASS && !routePlanningMode) + || (currentMapRotation == OsmandSettings.ROTATE_MAP_BEARING && smallSpeedForDirectionOfMovement); // show point view only if gps enabled if(sensorRegistered != registerCompassListener) { app.getLocationProvider().registerOrUnregisterCompassListener(registerCompassListener); diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashLocationFragment.java b/OsmAnd/src/net/osmand/plus/dashboard/DashLocationFragment.java index 3f13b90922..474a6638bc 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashLocationFragment.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashLocationFragment.java @@ -120,6 +120,12 @@ public abstract class DashLocationFragment extends DashBaseFragment { public static void updateLocationView(boolean useCenter, LatLon fromLoc, Float h, ImageView arrow, int arrowResId, TextView txt, LatLon toLoc, int screenOrientation, OsmandApplication app, Context ctx, boolean paint) { + updateLocationView(useCenter, fromLoc, h, arrow, arrowResId, 0, txt, toLoc, screenOrientation, app, ctx, paint); + } + + public static void updateLocationView(boolean useCenter, LatLon fromLoc, Float h, + ImageView arrow, int arrowResId, int color, TextView txt, LatLon toLoc, + int screenOrientation, OsmandApplication app, Context ctx, boolean paint) { float[] mes = new float[2]; if (fromLoc != null && toLoc != null) { Location.distanceBetween(toLoc.getLatitude(), toLoc.getLongitude(), fromLoc.getLatitude(), fromLoc.getLongitude(), mes); @@ -136,7 +142,7 @@ public abstract class DashLocationFragment extends DashBaseFragment { } else { dd = (DirectionDrawable) arrow.getDrawable(); } - dd.setImage(arrowResId, useCenter ? R.color.color_distance : R.color.color_myloc_distance); + dd.setImage(arrowResId, color == 0 ? useCenter ? R.color.color_distance : R.color.color_myloc_distance : color); if (fromLoc == null || h == null || toLoc == null) { dd.setAngle(0); } else { diff --git a/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java b/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java index 35823dfcba..4b88b2089b 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/MapMarkerDialogHelper.java @@ -354,7 +354,7 @@ public class MapMarkerDialogHelper { @Override public void onClick(DialogInterface dialog, int which) { listAdapter.notifyDataSetInvalidated(); - markersHelper.removeActiveMarkers(); + markersHelper.moveAllActiveMarkersToHistory(); if (markersHelper.getMapMarkersHistory().size() == 0) { mapActivity.getDashboard().hideDashboard(); } else if (helperCallbacks != null) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapMarkerMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapMarkerMenuController.java index 4e0bf8570f..875b8f0fdb 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapMarkerMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapMarkerMenuController.java @@ -10,7 +10,6 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.MapMarkerDialogHelper; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuController; -import net.osmand.plus.mapillary.MapillaryPlugin; import net.osmand.util.Algorithms; public class MapMarkerMenuController extends MenuController { @@ -25,8 +24,7 @@ public class MapMarkerMenuController extends MenuController { leftTitleButtonController = new TitleButtonController() { @Override public void buttonPressed() { - markersHelper.removeMapMarker(getMapMarker().index); - markersHelper.addMapMarkerHistory(getMapMarker()); + markersHelper.moveMapMarkerToHistory(getMapMarker()); getMapActivity().getContextMenu().close(); } }; diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/HistoryMarkerMenuBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/HistoryMarkerMenuBottomSheetDialogFragment.java new file mode 100644 index 0000000000..6d751f9138 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/HistoryMarkerMenuBottomSheetDialogFragment.java @@ -0,0 +1,149 @@ +package net.osmand.plus.mapmarkers; + +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +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.MapMarkersHelper.MapMarker; +import net.osmand.plus.R; +import net.osmand.plus.base.BottomSheetDialogFragment; +import net.osmand.plus.helpers.AndroidUiHelper; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class HistoryMarkerMenuBottomSheetDialogFragment extends BottomSheetDialogFragment { + + public final static String TAG = "HistoryMarkerMenuBottomSheetDialogFragment"; + + public static final String MARKER_POSITION = "marker_position"; + public static final String MARKER_NAME = "marker_name"; + public static final String MARKER_COLOR_INDEX = "marker_color_index"; + public static final String MARKER_VISITED_DATE = "marker_visited_date"; + + private HistoryMarkerMenuFragmentListener listener; + private boolean portrait; + + public void setListener(HistoryMarkerMenuFragmentListener listener) { + this.listener = listener; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + portrait = AndroidUiHelper.isOrientationPortrait(getActivity()); + boolean nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls(); + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + + final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_marker_history_bottom_sheet_dialog, container); + if (portrait) { + AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); + } + + Bundle arguments = getArguments(); + if (arguments != null) { + final int pos = arguments.getInt(MARKER_POSITION); + String markerName = arguments.getString(MARKER_NAME); + int markerColorIndex = arguments.getInt(MARKER_COLOR_INDEX); + long markerVisitedDate = arguments.getLong(MARKER_VISITED_DATE); + ((TextView) mainView.findViewById(R.id.map_marker_title)).setText(markerName); + ((ImageView) mainView.findViewById(R.id.map_marker_icon)).setImageDrawable(getIcon(R.drawable.ic_action_flag_dark, MapMarker.getColorId(markerColorIndex))); + ((TextView) mainView.findViewById(R.id.map_marker_passed_info)).setText(getString(R.string.passed, new SimpleDateFormat("MMM dd", Locale.getDefault()).format(new Date(markerVisitedDate)))); + + mainView.findViewById(R.id.make_active_row).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (listener != null) { + listener.onMakeMarkerActive(pos); + } + dismiss(); + } + }); + mainView.findViewById(R.id.delete_row).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (listener != null) { + listener.onDeleteMarker(pos); + } + dismiss(); + } + }); + } + + ((ImageView) mainView.findViewById(R.id.make_active_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_reset_to_default_dark)); + ((ImageView) mainView.findViewById(R.id.delete_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_delete_dark)); + + 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.history_marker_scroll_view); + int scrollViewHeight = scrollView.getHeight(); + int dividerHeight = AndroidUtils.dpToPx(getContext(), 1); + int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.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, false, + R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark); + } else { + AndroidUtils.setBackground(getActivity(), mainView, false, + 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); + } + } + + interface HistoryMarkerMenuFragmentListener { + void onMakeMarkerActive(int pos); + void onDeleteMarker(int pos); + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersActiveFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersActiveFragment.java index 3b2fb3d96d..ca0af55967 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersActiveFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersActiveFragment.java @@ -49,7 +49,7 @@ public class MapMarkersActiveFragment extends Fragment implements OsmAndCompassL @Override public void onItemClick(View view) { - int pos = recyclerView.indexOfChild(view); + int pos = recyclerView.getChildAdapterPosition(view); MapMarker marker = adapter.getItem(pos); mapActivity.getMyApplication().getSettings().setMapLocationToShow(marker.getLatitude(), marker.getLongitude(), 15, marker.getPointDescription(mapActivity), true, marker); @@ -67,7 +67,9 @@ public class MapMarkersActiveFragment extends Fragment implements OsmAndCompassL public void onDragEnded(RecyclerView.ViewHolder holder) { toPosition = holder.getAdapterPosition(); if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) { - mapActivity.getMyApplication().getMapMarkersHelper().saveMapMarkers(adapter.getItems(), null); + hideSnackbar(); + mapActivity.getMyApplication().getMapMarkersHelper().checkAndFixActiveMarkersOrderIfNeeded(); + adapter.notifyDataSetChanged(); } } }); @@ -121,15 +123,27 @@ public class MapMarkersActiveFragment extends Fragment implements OsmAndCompassL return null; } + void setShowDirectionEnabled(boolean showDirectionEnabled) { + if (adapter != null) { + adapter.setShowDirectionEnabled(showDirectionEnabled); + } + } + void updateAdapter() { if (adapter != null) { adapter.notifyDataSetChanged(); } } + void hideSnackbar() { + if (adapter != null) { + adapter.hideSnackbar(); + } + } + private void updateLocationUi() { final MapActivity mapActivity = (MapActivity) getActivity(); - if (mapActivity != null) { + if (mapActivity != null && adapter != null) { mapActivity.getMyApplication().runInUIThread(new Runnable() { @Override public void run() { @@ -141,7 +155,7 @@ public class MapMarkersActiveFragment extends Fragment implements OsmAndCompassL adapter.setUseCenter(useCenter); adapter.setLocation(useCenter ? mapActivity.getMapLocation() : new LatLon(location.getLatitude(), location.getLongitude())); - adapter.setHeading(useCenter ? -mapActivity.getMapRotate() : heading); + adapter.setHeading(useCenter ? -mapActivity.getMapRotate() : heading != null ? heading : 99); adapter.notifyDataSetChanged(); } }); diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java new file mode 100644 index 0000000000..ba49cfd77d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java @@ -0,0 +1,509 @@ +package net.osmand.plus.mapmarkers; + +import android.support.annotation.Nullable; + +import net.osmand.data.LatLon; +import net.osmand.data.PointDescription; +import net.osmand.plus.MapMarkersHelper.MapMarker; +import net.osmand.plus.MapMarkersHelper.MarkersSyncGroup; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; +import net.osmand.plus.helpers.SearchHistoryHelper; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +public class MapMarkersDbHelper { + + private static final int DB_VERSION = 2; + public static final String DB_NAME = "map_markers_db"; + + private static final String MARKERS_TABLE_NAME = "map_markers"; + private static final String MARKERS_COL_ID = "marker_id"; + private static final String MARKERS_COL_LAT = "marker_lat"; + private static final String MARKERS_COL_LON = "marker_lon"; + private static final String MARKERS_COL_DESCRIPTION = "marker_description"; + private static final String MARKERS_COL_ACTIVE = "marker_active"; + private static final String MARKERS_COL_ADDED = "marker_added"; + private static final String MARKERS_COL_VISITED = "marker_visited"; + private static final String MARKERS_COL_GROUP_NAME = "group_name"; + private static final String MARKERS_COL_GROUP_KEY = "group_key"; + private static final String MARKERS_COL_COLOR = "marker_color"; + private static final String MARKERS_COL_NEXT_KEY = "marker_next_key"; + + private static final String MARKERS_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " + + MARKERS_TABLE_NAME + " (" + + MARKERS_COL_ID + " TEXT PRIMARY KEY, " + + MARKERS_COL_LAT + " double, " + + MARKERS_COL_LON + " double, " + + MARKERS_COL_DESCRIPTION + " TEXT, " + + MARKERS_COL_ACTIVE + " int, " + // 1 = true, 0 = false + MARKERS_COL_ADDED + " long, " + + MARKERS_COL_VISITED + " long, " + + MARKERS_COL_GROUP_NAME + " TEXT, " + + MARKERS_COL_GROUP_KEY + " TEXT, " + + MARKERS_COL_COLOR + " int, " + + MARKERS_COL_NEXT_KEY + " TEXT);"; + + private static final String MARKERS_TABLE_SELECT = "SELECT " + + MARKERS_COL_ID + ", " + + MARKERS_COL_LAT + ", " + + MARKERS_COL_LON + ", " + + MARKERS_COL_DESCRIPTION + ", " + + MARKERS_COL_ACTIVE + ", " + + MARKERS_COL_ADDED + ", " + + MARKERS_COL_VISITED + ", " + + MARKERS_COL_GROUP_NAME + ", " + + MARKERS_COL_GROUP_KEY + ", " + + MARKERS_COL_COLOR + ", " + + MARKERS_COL_NEXT_KEY + + " FROM " + MARKERS_TABLE_NAME; + + private static final String GROUPS_TABLE_NAME = "map_markers_groups"; + private static final String GROUPS_COL_ID = "group_id"; + private static final String GROUPS_COL_NAME = "group_name"; + private static final String GROUPS_COL_TYPE = "group_type"; + + private static final String GROUPS_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " + + GROUPS_TABLE_NAME + " (" + + GROUPS_COL_ID + " TEXT PRIMARY KEY, " + + GROUPS_COL_NAME + " TEXT, " + + GROUPS_COL_TYPE + " int);"; + + private static final String GROUPS_TABLE_SELECT = "SELECT " + + GROUPS_COL_ID + ", " + + GROUPS_COL_NAME + ", " + + GROUPS_COL_TYPE + + " FROM " + GROUPS_TABLE_NAME; + + public static final String TAIL_NEXT_VALUE = "tail_next"; + public static final String HISTORY_NEXT_VALUE = "history_next"; + + private final OsmandApplication context; + + public MapMarkersDbHelper(OsmandApplication context) { + this.context = context; + } + + private SQLiteConnection openConnection(boolean readonly) { + SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); + int version = conn.getVersion(); + if (version == 0 || DB_VERSION != version) { + if (readonly) { + conn.close(); + conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, false); + } + version = conn.getVersion(); + conn.setVersion(DB_VERSION); + if (version == 0) { + onCreate(conn); + } else { + onUpgrade(conn, version, DB_VERSION); + } + } + return conn; + } + + private void onCreate(SQLiteConnection db) { + db.execSQL(MARKERS_TABLE_CREATE); + db.execSQL(GROUPS_TABLE_CREATE); + saveExistingMarkersToDb(); + } + + private void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { + + } + + private void saveExistingMarkersToDb() { + OsmandSettings settings = context.getSettings(); + + List ips = settings.getMapMarkersPoints(); + List desc = settings.getMapMarkersPointDescriptions(ips.size()); + List colors = settings.getMapMarkersColors(ips.size()); + int colorIndex = 0; + for (int i = 0; i < ips.size(); i++) { + if (colors.size() > i) { + colorIndex = colors.get(i); + } + MapMarker marker = new MapMarker(ips.get(i), PointDescription.deserializeFromString(desc.get(i), ips.get(i)), + colorIndex, false, i); + marker.history = false; + addMarker(marker, true); + } + + ips = settings.getMapMarkersHistoryPoints(); + desc = settings.getMapMarkersHistoryPointDescriptions(ips.size()); + colors = settings.getMapMarkersHistoryColors(ips.size()); + for (int i = 0; i < ips.size(); i++) { + if (colors.size() > i) { + colorIndex = colors.get(i); + } + MapMarker marker = new MapMarker(ips.get(i), PointDescription.deserializeFromString(desc.get(i), ips.get(i)), + colorIndex, false, i); + marker.history = true; + addMarker(marker, true); + } + } + + public void addGroup(String id, String name, int type) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL("INSERT INTO " + GROUPS_TABLE_NAME + " VALUES (?, ?, ?)", new Object[]{id, name, type}); + } finally { + db.close(); + } + } + } + + public List getAllGroups() { + List res = new LinkedList<>(); + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(GROUPS_TABLE_SELECT, null); + if (query.moveToFirst()) { + do { + res.add(readSyncGroup(query)); + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + } + return res; + } + + @Nullable + public MarkersSyncGroup getGroup(String id) { + MarkersSyncGroup res = null; + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(GROUPS_TABLE_SELECT + " WHERE " + GROUPS_COL_ID + " = ?", new String[]{id}); + if (query.moveToFirst()) { + res = readSyncGroup(query); + } + query.close(); + } finally { + db.close(); + } + } + return res; + } + + private MarkersSyncGroup readSyncGroup(SQLiteCursor query) { + String id = query.getString(0); + String name = query.getString(1); + int type = query.getInt(2); + + return new MarkersSyncGroup(id, name, type); + } + + public void removeMarkersSyncGroup(String id) { + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + db.execSQL("DELETE FROM " + GROUPS_TABLE_NAME + " WHERE " + GROUPS_COL_ID + " = ?", new Object[]{id}); + } finally { + db.close(); + } + } + } + + public void removeActiveMarkersFromSyncGroup(String syncGroupId) { + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + db.execSQL("DELETE FROM " + MARKERS_TABLE_NAME + + " WHERE " + MARKERS_COL_GROUP_KEY + " = ?" + + " AND " + MARKERS_COL_ACTIVE + " = ?", + new Object[]{syncGroupId, 1}); + } finally { + db.close(); + } + } + } + + public void addMarker(MapMarker marker) { + addMarker(marker, false); + } + + private void addMarker(MapMarker marker, boolean saveExisting) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + insertLast(db, marker, saveExisting); + } finally { + db.close(); + } + } + } + + private void insertLast(SQLiteConnection db, MapMarker marker, boolean saveExisting) { + long currentTime; + if (saveExisting) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.MONTH, -1); + currentTime = cal.getTimeInMillis(); + } else { + currentTime = System.currentTimeMillis(); + } + if (marker.id == null) { + marker.id = String.valueOf(currentTime) + String.valueOf(new Random().nextInt(900) + 100); + } + marker.creationDate = currentTime; + String descr = PointDescription.serializeToString(marker.getOriginalPointDescription()); + int active = marker.history ? 0 : 1; + long visited = saveExisting ? currentTime : 0; + + PointDescription pointDescription = marker.getOriginalPointDescription(); + if (pointDescription != null && !pointDescription.isSearchingAddress(context)) { + SearchHistoryHelper.getInstance(context) + .addNewItemToHistory(marker.getLatitude(), marker.getLongitude(), pointDescription); + } + + if (!marker.history) { + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + MARKERS_COL_NEXT_KEY + " = ? " + + "WHERE " + MARKERS_COL_NEXT_KEY + " = ?", new Object[]{marker.id, TAIL_NEXT_VALUE}); + } + + db.execSQL("INSERT INTO " + MARKERS_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + new Object[]{marker.id, marker.getLatitude(), marker.getLongitude(), descr, active, + currentTime, visited, marker.groupName, marker.groupKey, marker.colorIndex, + marker.history ? HISTORY_NEXT_VALUE : TAIL_NEXT_VALUE}); + } + + public List getMarkersFromGroup(MarkersSyncGroup group) { + List res = new LinkedList<>(); + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(MARKERS_TABLE_SELECT + " WHERE " + MARKERS_COL_GROUP_KEY + " = ?", + new String[]{group.getId()}); + if (query.moveToFirst()) { + do { + res.add(readItem(query)); + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + } + return res; + } + + @Nullable + public MapMarker getMarker(String id) { + MapMarker res = null; + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(MARKERS_TABLE_SELECT + " WHERE " + MARKERS_COL_ID + " = ?", new String[]{id}); + if (query.moveToFirst()) { + res = readItem(query); + } + query.close(); + } finally { + db.close(); + } + } + return res; + } + + public List getActiveMarkers() { + List res = new LinkedList<>(); + HashMap markers = new LinkedHashMap<>(); + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(MARKERS_TABLE_SELECT + " WHERE " + MARKERS_COL_ACTIVE + " = ?", + new String[]{String.valueOf(1)}); + if (query.moveToFirst()) { + do { + MapMarker marker = readItem(query); + markers.put(marker.id, marker); + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + buildLinkedList(markers, res); + } + return res; + } + + private MapMarker readItem(SQLiteCursor query) { + String id = query.getString(0); + double lat = query.getDouble(1); + double lon = query.getDouble(2); + String desc = query.getString(3); + boolean active = query.getInt(4) == 1; + long added = query.getLong(5); + long visited = query.getLong(6); + String groupName = query.getString(7); + String groupKey = query.getString(8); + int colorIndex = query.getInt(9); + String nextKey = query.getString(10); + + LatLon latLon = new LatLon(lat, lon); + MapMarker marker = new MapMarker(latLon, PointDescription.deserializeFromString(desc, latLon), + colorIndex, false, 0); + marker.id = id; + marker.history = !active; + marker.creationDate = added; + marker.visitedDate = visited; + marker.groupName = groupName; + marker.groupKey = groupKey; + marker.nextKey = nextKey; + + return marker; + } + + private void buildLinkedList(HashMap markers, List res) { + if (!markers.isEmpty()) { + int count = 1; + for (MapMarker marker : markers.values()) { + if (!markers.keySet().contains(marker.nextKey) || count == markers.size()) { + res.add(0, marker); + markers.remove(marker.id); + break; + } + count++; + } + buildLinkedList(markers, res); + } + } + + public void updateMarker(MapMarker marker) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String descr = PointDescription.serializeToString(marker.getOriginalPointDescription()); + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + + MARKERS_COL_LAT + " = ?, " + + MARKERS_COL_LON + " = ?, " + + MARKERS_COL_DESCRIPTION + " = ?, " + + MARKERS_COL_COLOR + " = ? " + + "WHERE " + MARKERS_COL_ID + " = ?", + new Object[]{marker.getLatitude(), marker.getLongitude(), descr, marker.colorIndex, marker.id}); + } finally { + db.close(); + } + } + } + + public void changeActiveMarkerPosition(MapMarker moved, @Nullable MapMarker next) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + MARKERS_COL_NEXT_KEY + " = ? " + + "WHERE " + MARKERS_COL_ID + " = ?", new Object[]{next == null ? TAIL_NEXT_VALUE : next.id, moved.id}); + } finally { + db.close(); + } + } + } + + public void moveMarkerToHistory(MapMarker marker) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + marker.visitedDate = System.currentTimeMillis(); + + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + + MARKERS_COL_ACTIVE + " = ?, " + + MARKERS_COL_VISITED + " = ?, " + + MARKERS_COL_NEXT_KEY + " = ? " + + "WHERE " + MARKERS_COL_ID + " = ?", new Object[]{0, marker.visitedDate, HISTORY_NEXT_VALUE, marker.id}); + } finally { + db.close(); + } + } + } + + public void moveAllActiveMarkersToHistory(long timestamp) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + + MARKERS_COL_ACTIVE + " = ?, " + + MARKERS_COL_VISITED + " = ?, " + + MARKERS_COL_NEXT_KEY + " = ? " + + "WHERE " + MARKERS_COL_ACTIVE + " = ?", new Object[]{0, timestamp, HISTORY_NEXT_VALUE, 1}); + } finally { + db.close(); + } + } + } + + public void restoreMapMarkerFromHistory(MapMarker marker) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL("UPDATE " + MARKERS_TABLE_NAME + " SET " + + MARKERS_COL_ACTIVE + " = ? " + + "WHERE " + MARKERS_COL_ID + " = ? " + + "AND " + MARKERS_COL_ACTIVE + " = ?", + new Object[]{1, marker.id, 0}); + } finally { + db.close(); + } + } + } + + public List getMarkersHistory() { + List markers = new LinkedList<>(); + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery(MARKERS_TABLE_SELECT + " WHERE " + MARKERS_COL_ACTIVE + " = ?", + new String[]{String.valueOf(0)}); + if (query.moveToFirst()) { + do { + markers.add(readItem(query)); + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + } + return markers; + } + + public void removeMarker(MapMarker marker, boolean history) { + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + db.execSQL("DELETE FROM " + MARKERS_TABLE_NAME + + " WHERE " + MARKERS_COL_ID + " = ?" + + " AND " + MARKERS_COL_ACTIVE + " = ?", + new Object[]{marker.id, history ? 0 : 1}); + } finally { + db.close(); + } + } + } + + public void clearAllMarkersHistory() { + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + db.execSQL("DELETE FROM " + MARKERS_TABLE_NAME + " WHERE " + MARKERS_COL_ACTIVE + " = ?", + new Object[]{0}); + } finally { + db.close(); + } + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java index 99c05a9550..dc4c5c25f7 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java @@ -4,30 +4,47 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.BottomNavigationView; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; +import android.support.v7.widget.helper.ItemTouchHelper; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import android.widget.Toast; import net.osmand.plus.LockableViewPager; +import net.osmand.plus.MapMarkersHelper; 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.dashboard.DashboardOnMap; +import net.osmand.plus.mapmarkers.ShowDirectionBottomSheetDialogFragment.ShowDirectionFragmentListener; import net.osmand.plus.mapmarkers.MarkerOptionsBottomSheetDialogFragment.MarkerOptionsFragmentListener; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragment { public static final String TAG = "MapMarkersDialogFragment"; + private MapMarkersActiveFragment activeFragment; + private MapMarkersGroupsFragment groupsFragment; + private MapMarkersHistoryFragment historyFragment; + + private Snackbar snackbar; + private LockableViewPager viewPager; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -40,11 +57,37 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + List fragments = getChildFragmentManager().getFragments(); + if (fragments != null) { + for (Fragment fragment : fragments) { + if (fragment instanceof MapMarkersActiveFragment) { + activeFragment = (MapMarkersActiveFragment) fragment; + } else if (fragment instanceof MapMarkersGroupsFragment) { + groupsFragment = (MapMarkersGroupsFragment) fragment; + } else if (fragment instanceof MapMarkersHistoryFragment) { + historyFragment = (MapMarkersHistoryFragment) fragment; + } + } + } + if (activeFragment == null) { + activeFragment = new MapMarkersActiveFragment(); + } + if (groupsFragment == null) { + groupsFragment = new MapMarkersGroupsFragment(); + } + if (historyFragment == null) { + historyFragment = new MapMarkersHistoryFragment(); + } + FragmentManager fragmentManager = getChildFragmentManager(); Fragment markerOptionsFragment = fragmentManager.findFragmentByTag(MarkerOptionsBottomSheetDialogFragment.TAG); if (markerOptionsFragment != null) { ((MarkerOptionsBottomSheetDialogFragment) markerOptionsFragment).setListener(createMarkerOptionsFragmentListener()); } + Fragment showDirectionFragment = fragmentManager.findFragmentByTag(ShowDirectionBottomSheetDialogFragment.TAG); + if (showDirectionFragment != null) { + ((ShowDirectionBottomSheetDialogFragment) showDirectionFragment).setListener(createShowDirectionFragmentListener()); + } View mainView = inflater.inflate(R.layout.fragment_map_markers_dialog, container); @@ -66,7 +109,7 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm } }); - final LockableViewPager viewPager = mainView.findViewById(R.id.map_markers_view_pager); + viewPager = mainView.findViewById(R.id.map_markers_view_pager); viewPager.setSwipeLocked(true); final MapMarkersViewPagerAdapter adapter = new MapMarkersViewPagerAdapter(getChildFragmentManager()); viewPager.setAdapter(adapter); @@ -77,21 +120,33 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.action_active: - ((MapMarkersActiveFragment) adapter.getItem(0)).startLocationUpdate(); + activeFragment.startLocationUpdate(); if (viewPager.getCurrentItem() != 0) { - ((MapMarkersActiveFragment) adapter.getItem(0)).updateAdapter(); + activeFragment.updateAdapter(); + historyFragment.hideSnackbar(); } viewPager.setCurrentItem(0); optionsButton.setVisibility(View.VISIBLE); return true; - case R.id.action_history: - ((MapMarkersActiveFragment) adapter.getItem(0)).stopLocationUpdate(); + case R.id.action_groups: + activeFragment.stopLocationUpdate(); if (viewPager.getCurrentItem() != 1) { - ((MapMarkersHistoryFragment) adapter.getItem(1)).updateAdapter(); + groupsFragment.updateAdapter(); + activeFragment.hideSnackbar(); + historyFragment.hideSnackbar(); } viewPager.setCurrentItem(1); optionsButton.setVisibility(View.GONE); return true; + case R.id.action_history: + activeFragment.stopLocationUpdate(); + if (viewPager.getCurrentItem() != 2) { + historyFragment.updateAdapter(); + activeFragment.hideSnackbar(); + } + viewPager.setCurrentItem(2); + optionsButton.setVisibility(View.GONE); + return true; } return false; } @@ -106,6 +161,9 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm private MarkerOptionsFragmentListener createMarkerOptionsFragmentListener() { return new MarkerOptionsFragmentListener() { + + final MapActivity mapActivity = getMapActivity(); + @Override public void sortByOnClick() { Toast.makeText(getContext(), "Sort by", Toast.LENGTH_SHORT).show(); @@ -113,26 +171,61 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm @Override public void showDirectionOnClick() { - Toast.makeText(getContext(), "Show direction", Toast.LENGTH_SHORT).show(); + ShowDirectionBottomSheetDialogFragment fragment = new ShowDirectionBottomSheetDialogFragment(); + fragment.setListener(createShowDirectionFragmentListener()); + fragment.show(mapActivity.getSupportFragmentManager(), ShowDirectionBottomSheetDialogFragment.TAG); } @Override public void buildRouteOnClick() { - Toast.makeText(getContext(), "Build route", Toast.LENGTH_SHORT).show(); + mapActivity.getDashboard().setDashboardVisibility(true, DashboardOnMap.DashboardType.MAP_MARKERS_SELECTION); + dismiss(); } @Override public void saveAsNewTrackOnClick() { - Toast.makeText(getContext(), "Save as new track", Toast.LENGTH_SHORT).show(); + mapActivity.getMyApplication().getMapMarkersHelper().generateGpx(); } @Override public void moveAllToHistoryOnClick() { - Toast.makeText(getContext(), "Move all to history", Toast.LENGTH_SHORT).show(); + final MapMarkersHelper helper = mapActivity.getMyApplication().getMapMarkersHelper(); + final List markers = new ArrayList<>(helper.getMapMarkers()); + helper.moveAllActiveMarkersToHistory(); + activeFragment.updateAdapter(); + snackbar = Snackbar.make(viewPager, R.string.all_markers_moved_to_history, Snackbar.LENGTH_LONG) + .setAction(R.string.shared_string_undo, new View.OnClickListener() { + @Override + public void onClick(View view) { + helper.restoreMarkersFromHistory(markers); + activeFragment.updateAdapter(); + } + }); + View snackBarView = snackbar.getView(); + TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_action); + tv.setTextColor(ContextCompat.getColor(mapActivity, R.color.color_dialog_buttons_dark)); + snackbar.show(); } }; } + private ShowDirectionFragmentListener createShowDirectionFragmentListener() { + return new ShowDirectionFragmentListener() { + + final MapActivity mapActivity = getMapActivity(); + + @Override + public void onMapMarkersModeChanged(boolean showDirectionEnabled) { + mapActivity.getMapLayers().getMapWidgetRegistry().updateMapMarkersMode(mapActivity); + activeFragment.setShowDirectionEnabled(showDirectionEnabled); + activeFragment.updateAdapter(); + } + }; + } + + private MapActivity getMapActivity() { + return (MapActivity) getActivity(); + } public static boolean showInstance(@NonNull MapActivity mapActivity) { try { @@ -153,7 +246,7 @@ public class MapMarkersDialogFragment extends android.support.v4.app.DialogFragm MapMarkersViewPagerAdapter(FragmentManager fm) { super(fm); - fragments = Arrays.asList(new MapMarkersActiveFragment(), new MapMarkersHistoryFragment()); + fragments = Arrays.asList(activeFragment, groupsFragment, historyFragment); } @Override diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersGroupsFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersGroupsFragment.java new file mode 100644 index 0000000000..328575d030 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersGroupsFragment.java @@ -0,0 +1,37 @@ +package net.osmand.plus.mapmarkers; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapmarkers.adapters.MapMarkersGroupsAdapter; + +public class MapMarkersGroupsFragment extends Fragment { + + public static final String TAG = "MapMarkersGroupsFragment"; + + private MapMarkersGroupsAdapter adapter; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + final RecyclerView recyclerView = new RecyclerView(getContext()); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + final MapActivity mapActivity = (MapActivity) getActivity(); + + adapter = new MapMarkersGroupsAdapter(mapActivity); + return recyclerView; + } + + void updateAdapter() { + if (adapter != null) { + adapter.notifyDataSetChanged(); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHistoryFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHistoryFragment.java index f5ef8026e3..e40938ebd5 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHistoryFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersHistoryFragment.java @@ -1,52 +1,261 @@ package net.osmand.plus.mapmarkers; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; -import net.osmand.data.PointDescription; +import net.osmand.plus.MapMarkersHelper; import net.osmand.plus.MapMarkersHelper.MapMarker; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapmarkers.adapters.MapMarkerDateViewHolder; +import net.osmand.plus.mapmarkers.adapters.MapMarkerItemViewHolder; import net.osmand.plus.mapmarkers.adapters.MapMarkersHistoryAdapter; -public class MapMarkersHistoryFragment extends Fragment { +public class MapMarkersHistoryFragment extends Fragment implements MapMarkersHelper.MapMarkerChangedListener { - MapMarkersHistoryAdapter adapter; + private MapMarkersHistoryAdapter adapter; + private OsmandApplication app; + private Paint backgroundPaint = new Paint(); + private Paint iconPaint = new Paint(); + private Paint textPaint = new Paint(); + private Snackbar snackbar; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + app = getMyApplication(); + } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + final boolean night = !app.getSettings().isLightContent(); + final MapActivity mapActivity = (MapActivity) getActivity(); + + backgroundPaint.setColor(ContextCompat.getColor(getActivity(), night ? R.color.dashboard_divider_dark : R.color.dashboard_divider_light)); + backgroundPaint.setStyle(Paint.Style.FILL_AND_STROKE); + backgroundPaint.setAntiAlias(true); + iconPaint.setAntiAlias(true); + iconPaint.setFilterBitmap(true); + iconPaint.setDither(true); + textPaint.setTextSize(getResources().getDimension(R.dimen.default_desc_text_size)); + textPaint.setFakeBoldText(true); + textPaint.setAntiAlias(true); + + final String delStr = getString(R.string.shared_string_delete).toUpperCase(); + final String activateStr = getString(R.string.local_index_mi_restore).toUpperCase(); + Rect bounds = new Rect(); + + textPaint.getTextBounds(activateStr, 0, activateStr.length(), bounds); + final int activateStrWidth = bounds.width(); + final int textHeight = bounds.height(); + + Fragment historyMarkerMenuFragment = mapActivity.getSupportFragmentManager().findFragmentByTag(HistoryMarkerMenuBottomSheetDialogFragment.TAG); + if (historyMarkerMenuFragment != null) { + ((HistoryMarkerMenuBottomSheetDialogFragment) historyMarkerMenuFragment).setListener(createHistoryMarkerMenuListener()); + } + final RecyclerView recyclerView = new RecyclerView(getContext()); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - final MapActivity mapActivity = (MapActivity) getActivity(); + + ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + private float marginSides = getResources().getDimension(R.dimen.list_content_padding); + private Bitmap deleteBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_delete_dark); + private Bitmap resetBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_reset_to_default_dark); + private boolean iconHidden; + + @Override + public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (viewHolder instanceof MapMarkerDateViewHolder) { + return 0; + } + return super.getSwipeDirs(recyclerView, viewHolder); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { + if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && viewHolder instanceof MapMarkerItemViewHolder) { + if (!iconHidden && isCurrentlyActive) { + ((MapMarkerItemViewHolder) viewHolder).optionsBtn.setVisibility(View.GONE); + iconHidden = true; + } + View itemView = viewHolder.itemView; + int colorIcon; + int colorText; + if (Math.abs(dX) > itemView.getWidth() / 2) { + colorIcon = R.color.map_widget_blue; + colorText = R.color.map_widget_blue; + } else { + colorIcon = night ? 0 : R.color.icon_color; + colorText = R.color.dashboard_subheader_text_light; + } + if (colorIcon != 0) { + iconPaint.setColorFilter(new PorterDuffColorFilter(ContextCompat.getColor(getActivity(), colorIcon), PorterDuff.Mode.SRC_IN)); + } + textPaint.setColor(ContextCompat.getColor(getActivity(), colorText)); + float textMarginTop = ((float) itemView.getHeight() - (float) textHeight) / 2; + if (dX > 0) { + c.drawRect(itemView.getLeft(), itemView.getTop(), dX, itemView.getBottom(), backgroundPaint); + float iconMarginTop = ((float) itemView.getHeight() - (float) deleteBitmap.getHeight()) / 2; + c.drawBitmap(deleteBitmap, itemView.getLeft() + marginSides, itemView.getTop() + iconMarginTop, iconPaint); + c.drawText(delStr, itemView.getLeft() + 2 * marginSides + deleteBitmap.getWidth(), itemView.getTop() + textMarginTop + textHeight, textPaint); + } else { + c.drawRect(itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom(), backgroundPaint); + float iconMarginTop = ((float) itemView.getHeight() - (float) resetBitmap.getHeight()) / 2; + c.drawBitmap(resetBitmap, itemView.getRight() - resetBitmap.getWidth() - marginSides, itemView.getTop() + iconMarginTop, iconPaint); + c.drawText(activateStr, itemView.getRight() - resetBitmap.getWidth() - 2 * marginSides - activateStrWidth, itemView.getTop() + textMarginTop + textHeight, textPaint); + } + } + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + } + + @Override + public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (viewHolder instanceof MapMarkerItemViewHolder) { + ((MapMarkerItemViewHolder) viewHolder).optionsBtn.setVisibility(View.VISIBLE); + iconHidden = false; + } + super.clearView(recyclerView, viewHolder); + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, final int direction) { + final int pos = viewHolder.getAdapterPosition(); + Object item = adapter.getItem(pos); + if (item instanceof MapMarker) { + final MapMarker marker = (MapMarker) item; + int snackbarStringRes; + if (direction == ItemTouchHelper.LEFT) { + app.getMapMarkersHelper().restoreMarkerFromHistory((MapMarker) item, 0); + snackbarStringRes = R.string.marker_moved_to_active; + } else { + app.getMapMarkersHelper().removeMarkerFromHistory((MapMarker) item); + snackbarStringRes = R.string.item_removed; + } + adapter.notifyItemRemoved(pos); + snackbar = Snackbar.make(viewHolder.itemView, snackbarStringRes, Snackbar.LENGTH_LONG) + .setAction(R.string.shared_string_undo, new View.OnClickListener() { + @Override + public void onClick(View view) { + if (direction == ItemTouchHelper.LEFT) { + app.getMapMarkersHelper().moveMapMarkerToHistory(marker); + } else { + app.getMapMarkersHelper().addMarker(marker); + } + } + }); + View snackBarView = snackbar.getView(); + TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_action); + tv.setTextColor(ContextCompat.getColor(mapActivity, R.color.color_dialog_buttons_dark)); + snackbar.show(); + } + } + }; + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); + itemTouchHelper.attachToRecyclerView(recyclerView); adapter = new MapMarkersHistoryAdapter(mapActivity.getMyApplication()); adapter.setAdapterListener(new MapMarkersHistoryAdapter.MapMarkersHistoryAdapterListener() { @Override public void onItemClick(View view) { - int pos = recyclerView.indexOfChild(view); - MapMarker marker = adapter.getItem(pos); - mapActivity.getMyApplication().getSettings().setMapLocationToShow(marker.getLatitude(), marker.getLongitude(), - 15, new PointDescription(PointDescription.POINT_TYPE_LOCATION, marker.getPointDescription(mapActivity).getName()), - false, null); - MapActivity.launchMapActivityMoveToTop(mapActivity); - ((DialogFragment) getParentFragment()).dismiss(); + int pos = recyclerView.getChildAdapterPosition(view); + Object item = adapter.getItem(pos); + if (item instanceof MapMarker) { + MapMarker marker = (MapMarker) item; + HistoryMarkerMenuBottomSheetDialogFragment fragment = new HistoryMarkerMenuBottomSheetDialogFragment(); + Bundle arguments = new Bundle(); + arguments.putInt(HistoryMarkerMenuBottomSheetDialogFragment.MARKER_POSITION, pos); + arguments.putString(HistoryMarkerMenuBottomSheetDialogFragment.MARKER_NAME, marker.getName(mapActivity)); + arguments.putInt(HistoryMarkerMenuBottomSheetDialogFragment.MARKER_COLOR_INDEX, marker.colorIndex); + arguments.putLong(HistoryMarkerMenuBottomSheetDialogFragment.MARKER_VISITED_DATE, marker.visitedDate); + fragment.setArguments(arguments); + fragment.setListener(createHistoryMarkerMenuListener()); + fragment.show(mapActivity.getSupportFragmentManager(), HistoryMarkerMenuBottomSheetDialogFragment.TAG); + } } }); recyclerView.setAdapter(adapter); + app.getMapMarkersHelper().addListener(this); + return recyclerView; } + void hideSnackbar() { + if (snackbar != null && snackbar.isShown()) { + snackbar.dismiss(); + } + } + + private HistoryMarkerMenuBottomSheetDialogFragment.HistoryMarkerMenuFragmentListener createHistoryMarkerMenuListener() { + return new HistoryMarkerMenuBottomSheetDialogFragment.HistoryMarkerMenuFragmentListener() { + @Override + public void onMakeMarkerActive(int pos) { + Object item = adapter.getItem(pos); + if (item instanceof MapMarker) { + app.getMapMarkersHelper().restoreMarkerFromHistory((MapMarker) item, 0); + adapter.notifyItemRemoved(pos); + } + } + + @Override + public void onDeleteMarker(int pos) { + Object item = adapter.getItem(pos); + if (item instanceof MapMarker) { + app.getMapMarkersHelper().removeMarkerFromHistory((MapMarker) item); + adapter.notifyItemRemoved(pos); + } + } + }; + } + + @Override + public void onDestroy() { + app.getMapMarkersHelper().removeListener(this); + super.onDestroy(); + } + void updateAdapter() { if (adapter != null) { + adapter.createHeaders(); adapter.notifyDataSetChanged(); } } + + public OsmandApplication getMyApplication() { + return (OsmandApplication) getActivity().getApplication(); + } + + @Override + public void onMapMarkerChanged(MapMarker mapMarker) { + updateAdapter(); + } + + @Override + public void onMapMarkersChanged() { + updateAdapter(); + } } diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MarkerOptionsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MarkerOptionsBottomSheetDialogFragment.java index 2bcf3d1325..0415556cea 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MarkerOptionsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MarkerOptionsBottomSheetDialogFragment.java @@ -3,6 +3,7 @@ package net.osmand.plus.mapmarkers; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; +import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,6 +14,7 @@ import android.widget.ImageView; import android.widget.TextView; import net.osmand.AndroidUtils; +import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.base.BottomSheetDialogFragment; import net.osmand.plus.helpers.AndroidUiHelper; @@ -32,16 +34,31 @@ public class MarkerOptionsBottomSheetDialogFragment extends BottomSheetDialogFra @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { portrait = AndroidUiHelper.isOrientationPortrait(getActivity()); + boolean nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls(); + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - final View mainView = inflater.inflate(R.layout.fragment_marker_options_bottom_sheet_dialog, container); + final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_marker_options_bottom_sheet_dialog, container); if (portrait) { - AndroidUtils.setBackground(getActivity(), mainView, false, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); + AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); } ((ImageView) mainView.findViewById(R.id.sort_by_icon)) .setImageDrawable(getIcon(R.drawable.ic_sort_waypoint_dark, R.color.on_map_icon_color)); - ((ImageView) mainView.findViewById(R.id.show_direction_icon)) - .setImageDrawable(getIcon(R.drawable.ic_sort_waypoint_dark, R.color.on_map_icon_color)); + OsmandSettings.MapMarkersMode mode = getMyApplication().getSettings().MAP_MARKERS_MODE.get(); + ImageView showDirectionIcon = (ImageView) mainView.findViewById(R.id.show_direction_icon); + int imageResId = 0; + switch (mode) { + case TOOLBAR: + imageResId = R.drawable.ic_action_device_topbar; + break; + case WIDGETS: + imageResId = R.drawable.ic_action_device_widget; + break; + } + showDirectionIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, R.color.on_map_icon_color)); + if (imageResId != 0) { + showDirectionIcon.setImageDrawable(getIcon(imageResId, R.color.dashboard_blue)); + } ((ImageView) mainView.findViewById(R.id.build_route_icon)) .setImageDrawable(getIcon(R.drawable.map_directions, R.color.on_map_icon_color)); ((ImageView) mainView.findViewById(R.id.save_as_new_track_icon)) @@ -49,7 +66,7 @@ public class MarkerOptionsBottomSheetDialogFragment extends BottomSheetDialogFra ((ImageView) mainView.findViewById(R.id.move_all_to_history_icon)) .setImageDrawable(getIcon(R.drawable.ic_action_history2, R.color.on_map_icon_color)); - ((TextView) mainView.findViewById(R.id.show_direction_text_view)).setText("Top bar"); + ((TextView) mainView.findViewById(R.id.show_direction_text_view)).setText(getMyApplication().getSettings().MAP_MARKERS_MODE.get().toHumanString(getActivity())); mainView.findViewById(R.id.sort_by_row).setOnClickListener(new View.OnClickListener() { @Override @@ -113,7 +130,7 @@ public class MarkerOptionsBottomSheetDialogFragment extends BottomSheetDialogFra final View scrollView = mainView.findViewById(R.id.marker_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 cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height); int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight; if (scrollViewHeight > spaceForScrollView) { scrollView.getLayoutParams().height = spaceForScrollView; diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/ShowDirectionBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/ShowDirectionBottomSheetDialogFragment.java new file mode 100644 index 0000000000..43148b2a13 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/ShowDirectionBottomSheetDialogFragment.java @@ -0,0 +1,239 @@ +package net.osmand.plus.mapmarkers; + +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +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.RadioButton; +import android.widget.TextView; + +import net.osmand.AndroidUtils; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.base.BottomSheetDialogFragment; +import net.osmand.plus.helpers.AndroidUiHelper; + +public class ShowDirectionBottomSheetDialogFragment extends BottomSheetDialogFragment { + + public final static String TAG = "ShowDirectionBottomSheetDialogFragment"; + + private ShowDirectionFragmentListener listener; + private boolean portrait; + private View mainView; + private boolean night; + + public void setListener(ShowDirectionFragmentListener listener) { + this.listener = listener; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + portrait = AndroidUiHelper.isOrientationPortrait(getActivity()); + night = !getMyApplication().getSettings().isLightContent(); + final int themeRes = night ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + + mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_marker_show_direction_bottom_sheet_dialog, container); + if (portrait) { + AndroidUtils.setBackground(getActivity(), mainView, night, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); + } + + OsmandSettings.MapMarkersMode mode = getMyApplication().getSettings().MAP_MARKERS_MODE.get(); + highlightSelectedItem(mode, true); + + 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 { + ImageView topBarImage = (ImageView) mainView.findViewById(R.id.top_bar_image); + ImageView widgetImage = (ImageView) mainView.findViewById(R.id.widget_image); + if (night) { + topBarImage.setImageResource(R.drawable.img_help_markers_topbar_night); + widgetImage.setImageResource(R.drawable.img_help_markers_widgets_night); + } else { + topBarImage.setImageResource(R.drawable.img_help_markers_topbar_day); + widgetImage.setImageResource(R.drawable.img_help_markers_widgets_day); + } + + mainView.findViewById(R.id.top_bar_image_text).setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + return false; + } + }); + topBarImage.setOnClickListener(showDirectionOnClickListener); + + mainView.findViewById(R.id.widget_image_text).setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + return false; + } + }); + widgetImage.setOnClickListener(showDirectionOnClickListener); + } + + if (night) { + ((TextView) mainView.findViewById(R.id.show_direction_title)).setTextColor(getResources().getColor(R.color.ctx_menu_info_text_dark)); + } + + ImageView topBarIcon = (ImageView) mainView.findViewById(R.id.top_bar_icon); + topBarIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, R.color.on_map_icon_color)); + topBarIcon.setImageDrawable(getIcon(R.drawable.ic_action_device_topbar, R.color.dashboard_blue)); + + ImageView widgetIcon = (ImageView) mainView.findViewById(R.id.widget_icon); + widgetIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, R.color.on_map_icon_color)); + widgetIcon.setImageDrawable(getIcon(R.drawable.ic_action_device_widget, R.color.dashboard_blue)); + + ImageView noneIcon = (ImageView) mainView.findViewById(R.id.none_icon); + noneIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, R.color.on_map_icon_color)); + + mainView.findViewById(R.id.top_bar_row).setOnClickListener(showDirectionOnClickListener); + mainView.findViewById(R.id.widget_row).setOnClickListener(showDirectionOnClickListener); + mainView.findViewById(R.id.none_row).setOnClickListener(showDirectionOnClickListener); + + 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.marker_show_direction_scroll_view); + int scrollViewHeight = scrollView.getHeight(); + int dividerHeight = AndroidUtils.dpToPx(getContext(), 1); + int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.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, false, + R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark); + } else { + AndroidUtils.setBackground(getActivity(), mainView, false, + 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); + } + } + + private void highlightSelectedItem(OsmandSettings.MapMarkersMode mode, boolean check) { + int iconBgColor = check ? R.color.dashboard_blue : R.color.on_map_icon_color; + int iconColor = check ? R.color.color_dialog_buttons_dark : R.color.dashboard_blue; + int textColor = ContextCompat.getColor(getContext(), check ? R.color.dashboard_blue : night ? R.color.color_white : R.color.color_black); + switch (mode) { + case TOOLBAR: + ((RadioButton) mainView.findViewById(R.id.top_bar_radio_button)).setChecked(check); + ImageView topBarIcon = (ImageView) mainView.findViewById(R.id.top_bar_icon); + if (check) { + mainView.findViewById(R.id.top_bar_row).setBackgroundColor(ContextCompat.getColor(getContext(), R.color.show_direction_menu_selected_item_bg)); + } else { + mainView.findViewById(R.id.top_bar_row).setBackgroundResource(0); + } + ((TextView) mainView.findViewById(R.id.top_bar_text)).setTextColor(textColor); + topBarIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, iconBgColor)); + topBarIcon.setImageDrawable(getIcon(R.drawable.ic_action_device_topbar, iconColor)); + break; + case WIDGETS: + ((RadioButton) mainView.findViewById(R.id.widget_radio_button)).setChecked(check); + ImageView widgetIcon = (ImageView) mainView.findViewById(R.id.widget_icon); + if (check) { + mainView.findViewById(R.id.widget_row).setBackgroundColor(ContextCompat.getColor(getContext(), R.color.show_direction_menu_selected_item_bg)); + } else { + mainView.findViewById(R.id.widget_row).setBackgroundResource(0); + } + ((TextView) mainView.findViewById(R.id.widget_text)).setTextColor(textColor); + widgetIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, iconBgColor)); + widgetIcon.setImageDrawable(getIcon(R.drawable.ic_action_device_widget, iconColor)); + break; + case NONE: + ((RadioButton) mainView.findViewById(R.id.none_radio_button)).setChecked(check); + ImageView noneIcon = (ImageView) mainView.findViewById(R.id.none_icon); + if (check) { + mainView.findViewById(R.id.none_row).setBackgroundColor(ContextCompat.getColor(getContext(), R.color.show_direction_menu_selected_item_bg)); + } else { + mainView.findViewById(R.id.none_row).setBackgroundResource(0); + } + ((TextView) mainView.findViewById(R.id.none_text)).setTextColor(textColor); + noneIcon.setBackgroundDrawable(getIcon(R.drawable.ic_action_device_top, iconBgColor)); + break; + } + } + + private View.OnClickListener showDirectionOnClickListener = new View.OnClickListener() { + + @Override + public void onClick(View view) { + OsmandSettings.MapMarkersMode previousMode = getMyApplication().getSettings().MAP_MARKERS_MODE.get(); + highlightSelectedItem(previousMode, false); + boolean showDirectionEnabled = false; + switch (view.getId()) { + case R.id.top_bar_image: + case R.id.top_bar_row: + getMyApplication().getSettings().MAP_MARKERS_MODE.set(OsmandSettings.MapMarkersMode.TOOLBAR); + highlightSelectedItem(OsmandSettings.MapMarkersMode.TOOLBAR, true); + showDirectionEnabled = true; + break; + case R.id.widget_image: + case R.id.widget_row: + getMyApplication().getSettings().MAP_MARKERS_MODE.set(OsmandSettings.MapMarkersMode.WIDGETS); + highlightSelectedItem(OsmandSettings.MapMarkersMode.WIDGETS, true); + showDirectionEnabled = true; + break; + case R.id.none_row: + getMyApplication().getSettings().MAP_MARKERS_MODE.set(OsmandSettings.MapMarkersMode.NONE); + highlightSelectedItem(OsmandSettings.MapMarkersMode.NONE, true); + showDirectionEnabled = false; + break; + } + if (listener != null) { + listener.onMapMarkersModeChanged(showDirectionEnabled); + } + dismiss(); + } + }; + + interface ShowDirectionFragmentListener { + void onMapMarkersModeChanged(boolean showDirectionEnabled); + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerDateViewHolder.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerDateViewHolder.java new file mode 100644 index 0000000000..7347d46604 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerDateViewHolder.java @@ -0,0 +1,20 @@ +package net.osmand.plus.mapmarkers.adapters; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageButton; +import android.widget.TextView; + +import net.osmand.plus.R; + +public class MapMarkerDateViewHolder extends RecyclerView.ViewHolder { + + final TextView date; + final ImageButton optionsBtn; + + public MapMarkerDateViewHolder(View itemView) { + super(itemView); + date = itemView.findViewById(R.id.date_title); + optionsBtn = itemView.findViewById(R.id.date_options_button); + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerItemViewHolder.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerItemViewHolder.java index d3042e2090..8b41e6d81c 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerItemViewHolder.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkerItemViewHolder.java @@ -10,24 +10,36 @@ import net.osmand.plus.R; public class MapMarkerItemViewHolder extends RecyclerView.ViewHolder { + final View mainLayout; final ImageView iconDirection; final ImageView iconReorder; final ImageView icon; final TextView title; final TextView distance; + final View flagIconLeftSpace; + final View leftPointSpace; final TextView point; + final View rightPointSpace; final TextView description; - final ImageButton optionsBtn; + public final ImageButton optionsBtn; + final View divider; + final View bottomShadow; public MapMarkerItemViewHolder(View view) { super(view); + mainLayout = view.findViewById(R.id.main_layout); iconDirection = (ImageView) view.findViewById(R.id.map_marker_direction_icon); iconReorder = (ImageView) view.findViewById(R.id.map_marker_reorder_icon); icon = (ImageView) view.findViewById(R.id.map_marker_icon); title = (TextView) view.findViewById(R.id.map_marker_title); distance = (TextView) view.findViewById(R.id.map_marker_distance); + flagIconLeftSpace = view.findViewById(R.id.flag_icon_left_space); + leftPointSpace = view.findViewById(R.id.map_marker_left_point_space); point = (TextView) view.findViewById(R.id.map_marker_point_text_view); + rightPointSpace = view.findViewById(R.id.map_marker_right_point_space); description = (TextView) view.findViewById(R.id.map_marker_description); optionsBtn = (ImageButton) view.findViewById(R.id.map_marker_options_button); + divider = view.findViewById(R.id.divider); + bottomShadow = view.findViewById(R.id.bottom_shadow); } } diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java index 20cfc06e1a..d531c4d1f7 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersActiveAdapter.java @@ -1,22 +1,29 @@ package net.osmand.plus.mapmarkers.adapters; import android.support.design.widget.Snackbar; +import android.support.v4.content.ContextCompat; import android.support.v4.view.MotionEventCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; import net.osmand.data.LatLon; import net.osmand.plus.IconsCache; import net.osmand.plus.MapMarkersHelper.MapMarker; +import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.dashboard.DashLocationFragment; +import java.text.SimpleDateFormat; import java.util.Collections; +import java.util.Date; import java.util.List; +import java.util.Locale; public class MapMarkersActiveAdapter extends RecyclerView.Adapter implements MapMarkersItemTouchHelperCallback.ItemTouchHelperAdapter { @@ -24,15 +31,24 @@ public class MapMarkersActiveAdapter extends RecyclerView.Adapter markers; private MapMarkersActiveAdapterListener listener; + private Snackbar snackbar; + private boolean showDirectionEnabled; private LatLon location; private Float heading; private boolean useCenter; private int screenOrientation; + private boolean night; public MapMarkersActiveAdapter(MapActivity mapActivity) { this.mapActivity = mapActivity; markers = mapActivity.getMyApplication().getMapMarkersHelper().getMapMarkers(); + night = !mapActivity.getMyApplication().getSettings().isLightContent(); + showDirectionEnabled = mapActivity.getMyApplication().getSettings().MAP_MARKERS_MODE.get() != OsmandSettings.MapMarkersMode.NONE; + } + + public void setShowDirectionEnabled(boolean showDirectionEnabled) { + this.showDirectionEnabled = showDirectionEnabled; } public void setAdapterListener(MapMarkersActiveAdapterListener listener) { @@ -56,7 +72,7 @@ public class MapMarkersActiveAdapter extends RecyclerView.Adapter 1) { + notifyItemChanged(1); + } else if (position == getItemCount()) { + notifyItemChanged(position - 1); + } - Snackbar.make(holder.itemView, R.string.item_removed, Snackbar.LENGTH_LONG) + snackbar = Snackbar.make(holder.itemView, mapActivity.getString(R.string.marker_moved_to_history), Snackbar.LENGTH_LONG) .setAction(R.string.shared_string_undo, new View.OnClickListener() { @Override public void onClick(View view) { - undone[0] = true; - mapActivity.getMyApplication().getMapMarkersHelper().addMapMarker(marker, position); + mapActivity.getMyApplication().getMapMarkersHelper().restoreMarkerFromHistory(marker, position); notifyItemInserted(position); - } - }) - .addCallback(new Snackbar.Callback() { - @Override - public void onDismissed(Snackbar transientBottomBar, int event) { - if (!undone[0]) { - mapActivity.getMyApplication().getMapMarkersHelper().addMapMarkerHistory(marker); + if (showDirectionEnabled && position < 2 && getItemCount() > 2) { + notifyItemChanged(2); + } else if (position == getItemCount() - 1) { + notifyItemChanged(position - 1); } } - }).show(); + }); + View snackBarView = snackbar.getView(); + TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_action); + tv.setTextColor(ContextCompat.getColor(mapActivity, R.color.color_dialog_buttons_dark)); + snackbar.show(); } }); DashLocationFragment.updateLocationView(useCenter, location, - heading, holder.iconDirection, holder.distance, - marker.getLatitude(), marker.getLongitude(), - screenOrientation, mapActivity.getMyApplication(), mapActivity); + heading, markerImageViewToUpdate, drawableResToUpdate, pos < 2 ? markerColor : 0, + holder.distance, markerLatLon, + screenOrientation, mapActivity.getMyApplication(), mapActivity, true); } @Override @@ -143,6 +207,12 @@ public class MapMarkersActiveAdapter extends RecyclerView.Adapter { + + private MapActivity mapActivity; + private List markers; + private boolean night; + + public MapMarkersGroupsAdapter(MapActivity mapActivity) { + this.mapActivity = mapActivity; + markers = mapActivity.getMyApplication().getMapMarkersHelper().getMapMarkers(); + night = !mapActivity.getMyApplication().getSettings().isLightContent(); + } + + @Override + public MapMarkerItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.map_marker_item_new, viewGroup, false); + return new MapMarkerItemViewHolder(view); + } + + @Override + public void onBindViewHolder(MapMarkerItemViewHolder mapMarkerItemViewHolder, int i) { + IconsCache iconsCache = mapActivity.getMyApplication().getIconsCache(); + MapMarkersHelper.MapMarker marker = markers.get(i); + } + + @Override + public int getItemCount() { + return markers.size(); + } + + public MapMarkersHelper.MapMarker getItem(int position) { + return markers.get(position); + } + + public List getItems() { + return markers; + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java index 173774b4e7..c035fe1032 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/adapters/MapMarkersHistoryAdapter.java @@ -10,17 +10,76 @@ import net.osmand.plus.MapMarkersHelper.MapMarker; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; +import java.util.Locale; -public class MapMarkersHistoryAdapter extends RecyclerView.Adapter { +public class MapMarkersHistoryAdapter extends RecyclerView.Adapter { + + private static final int DATE_TYPE = 1; + private static final int MARKER_TYPE = 2; + + private static final int TODAY_HEADER = 56; + private static final int YESTERDAY_HEADER = 57; + private static final int LAST_SEVEN_DAYS_HEADER = 58; + private static final int THIS_YEAR_HEADER = 59; private OsmandApplication app; - private List markers; + private List items = new ArrayList<>(); private MapMarkersHistoryAdapterListener listener; public MapMarkersHistoryAdapter(OsmandApplication app) { this.app = app; - markers = app.getMapMarkersHelper().getMapMarkersHistory(); + createHeaders(); + } + + public void createHeaders() { + items.clear(); + + List markersHistory = app.getMapMarkersHelper().getMapMarkersHistory(); + + int previousHeader = -1; + int monthsDisplayed = 0; + + Calendar currentDateCalendar = Calendar.getInstance(); + currentDateCalendar.setTimeInMillis(System.currentTimeMillis()); + int currentDay = currentDateCalendar.get(Calendar.DAY_OF_YEAR); + int currentMonth = currentDateCalendar.get(Calendar.MONTH); + int currentYear = currentDateCalendar.get(Calendar.YEAR); + Calendar markerCalendar = Calendar.getInstance(); + for (int i = 0; i < markersHistory.size(); i++) { + MapMarker marker = markersHistory.get(i); + markerCalendar.setTimeInMillis(marker.visitedDate); + int markerDay = markerCalendar.get(Calendar.DAY_OF_YEAR); + int markerMonth = markerCalendar.get(Calendar.MONTH); + int markerYear = markerCalendar.get(Calendar.YEAR); + if (markerYear == currentYear) { + if (markerDay == currentDay && previousHeader != TODAY_HEADER) { + items.add(TODAY_HEADER); + previousHeader = TODAY_HEADER; + } else if (markerDay == currentDay - 1 && previousHeader != YESTERDAY_HEADER) { + items.add(YESTERDAY_HEADER); + previousHeader = YESTERDAY_HEADER; + } else if (currentDay - markerDay >= 2 && currentDay - markerDay <= 8 && previousHeader != LAST_SEVEN_DAYS_HEADER) { + items.add(LAST_SEVEN_DAYS_HEADER); + previousHeader = LAST_SEVEN_DAYS_HEADER; + } else if (currentDay - markerDay > 8 && monthsDisplayed < 3 && previousHeader != markerMonth) { + items.add(markerMonth); + previousHeader = markerMonth; + monthsDisplayed += 1; + } else if (currentMonth - markerMonth >= 4 && previousHeader != THIS_YEAR_HEADER) { + items.add(THIS_YEAR_HEADER); + previousHeader = THIS_YEAR_HEADER; + } + } else if (previousHeader != markerYear) { + items.add(markerYear); + previousHeader = markerYear; + } + items.add(marker); + } } public void setAdapterListener(MapMarkersHistoryAdapterListener listener) { @@ -28,52 +87,109 @@ public class MapMarkersHistoryAdapter extends RecyclerView.Adapter spaceForScrollView) { scrollView.getLayoutParams().height = spaceForScrollView; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java index 568e083cbf..91e143c1eb 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java @@ -102,7 +102,7 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends BottomSheetDialogFr 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 cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height); int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight; if (scrollViewHeight > spaceForScrollView) { scrollView.getLayoutParams().height = spaceForScrollView; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java index 595f701073..b196f1410c 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectedPointBottomSheetDialogFragment.java @@ -167,7 +167,7 @@ public class SelectedPointBottomSheetDialogFragment extends BottomSheetDialogFra 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 cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height); int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight; if (scrollViewHeight > spaceForScrollView) { scrollView.getLayoutParams().height = spaceForScrollView; diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java index 54ceae5c4c..9e135db20b 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackPointFragment.java @@ -44,6 +44,7 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.IconsCache; import net.osmand.plus.MapMarkersHelper; +import net.osmand.plus.MapMarkersHelper.MarkersSyncGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; @@ -607,7 +608,10 @@ public class TrackPointFragment extends OsmandExpandableListFragment { names.add(new PointDescription(PointDescription.POINT_TYPE_MAP_MARKER, i.name)); } } - markersHelper.addMapMarkers(points, names); + File gpx = getGpxDataItem().getFile(); + MarkersSyncGroup syncGroup = new MarkersSyncGroup(gpx.getAbsolutePath(), trimExtension(gpx.getName()), MarkersSyncGroup.GPX_TYPE); + markersHelper.addMarkersSyncGroup(syncGroup); + markersHelper.addMapMarkers(points, names, syncGroup); MapActivity.launchMapActivityMoveToTop(getActivity()); } else { final TargetPointsHelper targetPointsHelper = getMyApplication().getTargetPointsHelper(); @@ -626,6 +630,14 @@ public class TrackPointFragment extends OsmandExpandableListFragment { } } + private String trimExtension(String src) { + int index = src.lastIndexOf('.'); + if (index != -1) { + return src.substring(0, index); + } + return src; + } + private void enterFavoritesMode() { actionMode = getActionBarActivity().startSupportActionMode(new ActionMode.Callback() { diff --git a/OsmAnd/src/net/osmand/plus/views/MapMarkersLayer.java b/OsmAnd/src/net/osmand/plus/views/MapMarkersLayer.java index 296a8de611..8107ee7ba7 100644 --- a/OsmAnd/src/net/osmand/plus/views/MapMarkersLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/MapMarkersLayer.java @@ -493,16 +493,7 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi @Override public void setSelectedObject(Object o) { if (o instanceof MapMarker) { - MapMarkersHelper markersHelper = map.getMyApplication().getMapMarkersHelper(); - MapMarker marker = (MapMarker) o; - List mapMarkers = markersHelper.getMapMarkers(); - int i = mapMarkers.indexOf(marker); - if (i != -1) { - mapMarkers.remove(i); - mapMarkers.add(0, marker); - markersHelper.saveMapMarkers(mapMarkers, null); - marker.index = 0; - } + map.getMyApplication().getMapMarkersHelper().moveMarkerToTop((MapMarker) o); } } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java index 9cce9c0a6d..c294f3d18b 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java @@ -131,9 +131,7 @@ public class MapMarkersWidgetsFactory { private void removeMarker(int index) { if (helper.getMapMarkers().size() > index) { - MapMarker marker = helper.getMapMarkers().get(index); - helper.removeMapMarker(marker.index); - helper.addMapMarkerHistory(marker); + helper.moveMapMarkerToHistory(helper.getMapMarkers().get(index)); } } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java index 64316febc4..db172d577f 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java @@ -345,16 +345,7 @@ public class MapWidgetRegistry { @Override public void onClick(DialogInterface dialog, int which) { settings.MAP_MARKERS_MODE.set(MapMarkersMode.values()[which]); - for (MapWidgetRegInfo info : rightWidgetSet) { - if ("map_marker_1st".equals(info.key) || "map_marker_2nd".equals(info.key)) { - setVisibility(info, settings.MAP_MARKERS_MODE.get().isWidgets(), false); - } - } - MapInfoLayer mil = map.getMapLayers().getMapInfoLayer(); - if (mil != null) { - mil.recreateControls(); - } - map.refreshMap(); + updateMapMarkersMode(map); dialog.dismiss(); cm.getItem(pos).setDescription(settings.MAP_MARKERS_MODE.get().toHumanString(map)); ad.notifyDataSetChanged(); @@ -367,6 +358,19 @@ public class MapWidgetRegistry { } } + public void updateMapMarkersMode(MapActivity mapActivity) { + for (MapWidgetRegInfo info : rightWidgetSet) { + if ("map_marker_1st".equals(info.key) || "map_marker_2nd".equals(info.key)) { + setVisibility(info, settings.MAP_MARKERS_MODE.get().isWidgets(), false); + } + } + MapInfoLayer mil = mapActivity.getMapLayers().getMapInfoLayer(); + if (mil != null) { + mil.recreateControls(); + } + mapActivity.refreshMap(); + } + private void addControlId(final MapActivity map, ContextMenuAdapter cm, @StringRes int stringId, OsmandPreference pref) { cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(stringId, map)