From efb4ddb03e1661cd3ec32bb162534b210638292e Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 15:17:19 +0300 Subject: [PATCH 01/14] [router] Added new route type "Ruler" Signed-off-by: S. Kozyr --- map/routing_manager.cpp | 36 +++++++++-- routing/CMakeLists.txt | 2 + routing/async_router.cpp | 20 +++--- routing/router.cpp | 3 + routing/router.hpp | 1 + routing/ruler_router.cpp | 129 +++++++++++++++++++++++++++++++++++++++ routing/ruler_router.hpp | 23 +++++++ 7 files changed, 200 insertions(+), 14 deletions(-) create mode 100644 routing/ruler_router.cpp create mode 100644 routing/ruler_router.hpp diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index fd1fd4f467..9f778e3f9d 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -9,6 +9,7 @@ #include "routing/route.hpp" #include "routing/routing_callbacks.hpp" #include "routing/routing_helpers.hpp" +#include "routing/ruler_router.hpp" #include "routing/speed_camera.hpp" #include "storage/country_info_getter.hpp" @@ -200,6 +201,7 @@ VehicleType GetVehicleType(RouterType routerType) case RouterType::Bicycle: return VehicleType::Bicycle; case RouterType::Vehicle: return VehicleType::Car; case RouterType::Transit: return VehicleType::Transit; + case RouterType::Ruler: return VehicleType::Transit; case RouterType::Count: CHECK(false, ("Invalid type", routerType)); return VehicleType::Count; } UNREACHABLE(); @@ -219,7 +221,7 @@ RoadWarningMarkType GetRoadType(RoutingOptions::Road road) } drape_ptr CreateDrapeSubroute(vector const & segments, m2::PointD const & startPt, - double baseDistance, double baseDepth, bool isTransit) + double baseDistance, double baseDepth, bool isTransit, bool isRuler) { auto subroute = make_unique_dp(); subroute->m_baseDistance = baseDistance; @@ -247,6 +249,15 @@ drape_ptr CreateDrapeSubroute(vector const & segment return nullptr; } + if (isRuler) + { + auto const subrouteLen = segments.back().GetDistFromBeginningMerc() - baseDistance; + subroute->m_headFakeDistance = -kBias; + subroute->m_tailFakeDistance = subrouteLen + kBias; + subroute->m_polyline = m2::PolylineD(std::move(points)); + return subroute; + } + // We support visualization of fake edges only in the head and in the tail of subroute. auto constexpr kInvalidId = std::numeric_limits::max(); auto firstReal = kInvalidId; @@ -292,7 +303,7 @@ drape_ptr CreateDrapeSubroute(vector const & segment subroute->m_tailFakeDistance = tailLen; } - subroute->m_polyline = m2::PolylineD(points); + subroute->m_polyline = m2::PolylineD(std::move(points)); return subroute; } } // namespace @@ -401,7 +412,7 @@ void RoutingManager::OnBuildRouteReady(Route const & route, RouterResultCode cod // Validate route (in case of bicycle routing it can be invalid). ASSERT(route.IsValid(), ()); - if (route.IsValid()) + if (route.IsValid() && m_currentRouterType != routing::RouterType::Ruler) { m2::RectD routeRect = route.GetPoly().GetLimitRect(); routeRect.Scale(kRouteScaleMultiplier); @@ -479,7 +490,8 @@ RouterType RoutingManager::GetLastUsedRouter() const { case RouterType::Pedestrian: case RouterType::Bicycle: - case RouterType::Transit: return routerType; + case RouterType::Transit: + case RouterType::Ruler: return routerType; default: return RouterType::Vehicle; } } @@ -517,7 +529,11 @@ void RoutingManager::SetRouterImpl(RouterType type) auto regionsFinder = make_unique(countryFileGetter, localFileChecker, numMwmIds, dataSource); - auto router = make_unique(vehicleType, m_loadAltitudes, m_callbacks.m_countryParentNameGetterFn, + std::unique_ptr router; + if (type == RouterType::Ruler) + router = make_unique(); + else + router = make_unique(vehicleType, m_loadAltitudes, m_callbacks.m_countryParentNameGetterFn, countryFileGetter, getMwmRectByName, numMwmIds, MakeNumMwmTree(*numMwmIds, m_callbacks.m_countryInfoGetter()), m_routingSession, dataSource); @@ -651,6 +667,7 @@ bool RoutingManager::InsertRoute(Route const & route) RoadWarningsCollection roadWarnings; bool const isTransitRoute = (m_currentRouterType == RouterType::Transit); + bool const isRulerRoute = (m_currentRouterType == RouterType::Ruler); shared_ptr transitRouteDisplay; if (isTransitRoute) { @@ -668,7 +685,8 @@ bool RoutingManager::InsertRoute(Route const & route) auto const startPt = route.GetSubrouteAttrs(subrouteIndex).GetStart().GetPoint(); auto subroute = CreateDrapeSubroute(segments, startPt, distance, - static_cast(subroutesCount - subrouteIndex - 1), isTransitRoute); + static_cast(subroutesCount - subrouteIndex - 1), + isTransitRoute, isRulerRoute); if (!subroute) continue; distance = segments.back().GetDistFromBeginningMerc(); @@ -702,6 +720,12 @@ bool RoutingManager::InsertRoute(Route const & route) FillTurnsDistancesForRendering(segments, subroute->m_baseDistance, subroute->m_turns); break; } + case RouterType::Ruler: + { + subroute->m_routeType = df::RouteType::Ruler; + subroute->AddStyle(df::SubrouteStyle(df::kRouteRuler, df::RoutePattern(16.0, 2.0))); + break; + } default: CHECK(false, ("Unknown router type")); } diff --git a/routing/CMakeLists.txt b/routing/CMakeLists.txt index 0dc40f83c8..6911fc0383 100644 --- a/routing/CMakeLists.txt +++ b/routing/CMakeLists.txt @@ -139,6 +139,8 @@ set(SRC routing_session.hpp routing_settings.cpp routing_settings.hpp + ruler_router.cpp + ruler_router.hpp segment.cpp segment.hpp segmented_route.cpp diff --git a/routing/async_router.cpp b/routing/async_router.cpp index 1b9679d2c8..161fc51028 100644 --- a/routing/async_router.cpp +++ b/routing/async_router.cpp @@ -371,17 +371,21 @@ void AsyncRouter::CalculateRoute() [delegateProxy, route, code]() { delegateProxy->OnReady(route, code); }); } - bool const needAbsentRegions = (code != RouterResultCode::Cancelled); + bool const needAbsentRegions = (code != RouterResultCode::Cancelled && + route->GetRouterId() != "ruler-router"); std::set absent; - if (absentRegionsFinder && needAbsentRegions) - absentRegionsFinder->GetAbsentRegions(absent); - - absent.insert(route->GetAbsentCountries().cbegin(), route->GetAbsentCountries().cend()); - if (!absent.empty()) + if (needAbsentRegions) { - code = RouterResultCode::NeedMoreMaps; - LOG(LDEBUG, ("Absent regions:", absent)); + if (absentRegionsFinder) + absentRegionsFinder->GetAbsentRegions(absent); + + absent.insert(route->GetAbsentCountries().cbegin(), route->GetAbsentCountries().cend()); + if (!absent.empty()) + { + code = RouterResultCode::NeedMoreMaps; + LOG(LDEBUG, ("Absent regions:", absent)); + } } elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time diff --git a/routing/router.cpp b/routing/router.cpp index f05e70ca60..fb76876bf7 100644 --- a/routing/router.cpp +++ b/routing/router.cpp @@ -10,6 +10,7 @@ std::string ToString(RouterType type) case RouterType::Pedestrian: return "pedestrian"; case RouterType::Bicycle: return "bicycle"; case RouterType::Transit: return "transit"; + case RouterType::Ruler: return "ruler"; case RouterType::Count: return "count"; } ASSERT(false, ()); @@ -26,6 +27,8 @@ RouterType FromString(std::string const & str) return RouterType::Bicycle; if (str == "transit") return RouterType::Transit; + if (str == "ruler" || str == "helicopter") // TODO: "helicopter" is left for Beta version compatibility. Remove after ruler release. + return RouterType::Ruler; ASSERT(false, ("Incorrect routing string:", str)); return RouterType::Vehicle; diff --git a/routing/router.hpp b/routing/router.hpp index 1d5220f4f6..e6c0b87750 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -43,6 +43,7 @@ enum class RouterType Pedestrian, /// For A star pedestrian routing. Bicycle, /// For A star bicycle routing. Transit, /// For A star pedestrian + transit routing. + Ruler, /// For simple straight line router. Count /// Number of router types. }; diff --git a/routing/ruler_router.cpp b/routing/ruler_router.cpp new file mode 100644 index 0000000000..f7d31d8c06 --- /dev/null +++ b/routing/ruler_router.cpp @@ -0,0 +1,129 @@ +#include "routing/ruler_router.hpp" +#include "routing/route.hpp" +#include "routing/routing_helpers.hpp" + +namespace routing +{ +using namespace std; + +void RulerRouter::ClearState() +{ +} + +void RulerRouter::SetGuides(GuidesTracks && guides) { /*m_guides = GuidesConnections(guides);*/ } + + +/* Ruler router doesn't read roads graph and uses only checkpoints to build a route. + + 1-----------2 + / \ + / \ + / F + S + + For example we need to build route from start (S) to finish (F) with intermediate + points (1) and (2). + Target route should have parameters: + + m_geometry = [S, S, 1, 1, 2, 2, F, F] + m_routeSegments = [S, 1, 1, 2, 2, F, F] + m_subroutes = + +-------+--------+-----------------+---------------+ + | start | finish | beginSegmentIdx | endSegmentIdx | + +-------+--------+-----------------+---------------+ + | S | 1 | 0 | 2 | + | 1 | 1 | 1 | 2 | + | 1 | 2 | 2 | 4 | + | 2 | 2 | 3 | 4 | + | 2 | F | 4 | 6 | + | 2 | F | 4 | 6 | + +-------+--------+-----------------+---------------+ + + Constraints: + * m_geometry.size() == 2 * checkpoints.size() + * m_routeSegments.size() == m_geometry.size()-1 + * m_subroutes.size() == m_routeSegments.size()-1 + + */ +RouterResultCode RulerRouter::CalculateRoute(Checkpoints const & checkpoints, + m2::PointD const & startDirection, + bool adjustToPrevRoute, + RouterDelegate const & delegate, Route & route) +{ + vector const & points = checkpoints.GetPoints(); + vector routeSegments; + vector times; + size_t const count = points.size(); + ASSERT(count > 0, ()); + + times.reserve(count*2-1); + Segment const segment(kFakeNumMwmId, 0, 0, false); + + auto const ToPointWA = [](m2::PointD const & p) + { + return geometry::PointWithAltitude(p, 0 /* altitude */); + }; + + for (size_t i = 0; i < count; ++i) + { + turns::TurnItem turn(i, turns::PedestrianDirection::None); + geometry::PointWithAltitude const junction = ToPointWA(points[i]); + RouteSegment::RoadNameInfo const roadNameInfo; + + auto routeSegment = RouteSegment(segment, turn, junction, roadNameInfo); + routeSegments.emplace_back(segment, turn, junction, roadNameInfo); + times.push_back(0); + + if (i == count - 1) + turn = turns::TurnItem(i+1, turns::PedestrianDirection::ReachedYourDestination); + else if (i == 0) + continue; + + routeSegments.emplace_back(segment, turn, junction, roadNameInfo); + times.push_back(0); + } + + FillSegmentInfo(times, routeSegments); + route.SetRouteSegments(std::move(routeSegments)); + + vector subroutes; + for(size_t i = 1; i < count; ++i) + { + if (i < count-1) + { + // Note: endSegmentIdx in decreased in Route::IsSubroutePassed(size_t) method. See routing/route.cpp:448 + subroutes.emplace_back(ToPointWA(points[i-1]), ToPointWA(points[i]), i*2-2, i*2); + subroutes.emplace_back(ToPointWA(points[i-1]), ToPointWA(points[i]), i*2-1, i*2); + } + else + { + // Duplicate last subroute attrs. + subroutes.emplace_back(ToPointWA(points[i-1]), ToPointWA(points[i+1]), i*2-2, i*2); + subroutes.emplace_back(ToPointWA(points[i-1]), ToPointWA(points[i+1]), i*2-2, i*2); + } + } + + route.SetCurrentSubrouteIdx(checkpoints.GetPassedIdx()); + route.SetSubroteAttrs(std::move(subroutes)); + + vector routeGeometry; + for (auto p: points) + { + routeGeometry.push_back(p); + routeGeometry.push_back(p); + } + + route.SetGeometry(routeGeometry.begin(), routeGeometry.end()); + + return RouterResultCode::NoError; +} + +bool RulerRouter::FindClosestProjectionToRoad(m2::PointD const & point, + m2::PointD const & direction, double radius, + EdgeProj & proj) +{ + //TODO + return false; +} + +} // namespace routing diff --git a/routing/ruler_router.hpp b/routing/ruler_router.hpp new file mode 100644 index 0000000000..5355b2d510 --- /dev/null +++ b/routing/ruler_router.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "routing/router.hpp" +#include + +namespace routing +{ + +class RulerRouter : public IRouter +{ + std::string GetName() const override { return {"ruler-router"}; } + void ClearState() override; + void SetGuides(GuidesTracks && guides) override; + RouterResultCode CalculateRoute(Checkpoints const & checkpoints, + m2::PointD const & startDirection, bool adjustToPrevRoute, + RouterDelegate const & delegate, Route & route) override; + bool FindClosestProjectionToRoad(m2::PointD const & point, m2::PointD const & direction, + double radius, EdgeProj & proj) override; + + // Do we need guides in this router? + //GuidesConnections m_guides; +}; +} // namespace routing -- 2.45.3 From 45be2493db6655ab12f937e4f2598cc3a0cd20d4 Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 15:20:10 +0300 Subject: [PATCH 02/14] [drape] Ruler route is drawn on top of buildings and has custom colors. Signed-off-by: S. Kozyr --- data/colors.txt | 2 ++ data/drules_proto_clear.txt | 4 ++++ data/drules_proto_dark.txt | 4 ++++ data/drules_proto_vehicle_clear.txt | 4 ++++ data/drules_proto_vehicle_dark.txt | 4 ++++ data/styles/clear/style-clear/style.mapcss | 2 ++ data/styles/clear/style-night/style.mapcss | 2 ++ data/styles/vehicle/style-clear/style.mapcss | 2 ++ data/styles/vehicle/style-night/style.mapcss | 2 ++ drape_frontend/frontend_renderer.cpp | 2 +- drape_frontend/route_renderer.cpp | 13 +++++++++++-- drape_frontend/route_renderer.hpp | 2 ++ drape_frontend/route_shape.hpp | 3 ++- 13 files changed, 42 insertions(+), 4 deletions(-) diff --git a/data/colors.txt b/data/colors.txt index 43c3bd1185..ee5c2672dd 100644 --- a/data/colors.txt +++ b/data/colors.txt @@ -313,6 +313,7 @@ 436207616 437326080 442260561 +442905727 444234362 451800027 452984831 @@ -367,6 +368,7 @@ 1300793480 1301043238 1301133440 +1301433013 1304608947 1306780114 1308576652 diff --git a/data/drules_proto_clear.txt b/data/drules_proto_clear.txt index 8cea0cb280..e9b727d5ca 100644 --- a/data/drules_proto_clear.txt +++ b/data/drules_proto_clear.txt @@ -104992,6 +104992,10 @@ colors { name: "RoutePreview" color: 3003121664 } + value { + name: "RouteRuler" + color: 442905727 + } value { name: "RouteTrafficG0" color: 10167040 diff --git a/data/drules_proto_dark.txt b/data/drules_proto_dark.txt index 5ccfbe244a..6fb75ebf1c 100644 --- a/data/drules_proto_dark.txt +++ b/data/drules_proto_dark.txt @@ -105079,6 +105079,10 @@ colors { name: "RoutePreview" color: 3019898879 } + value { + name: "RouteRuler" + color: 1301433013 + } value { name: "RouteTrafficG0" color: 6164237 diff --git a/data/drules_proto_vehicle_clear.txt b/data/drules_proto_vehicle_clear.txt index 5b48316f63..77a8db1659 100644 --- a/data/drules_proto_vehicle_clear.txt +++ b/data/drules_proto_vehicle_clear.txt @@ -74571,6 +74571,10 @@ colors { name: "RoutePreview" color: 3003121664 } + value { + name: "RouteRuler" + color: 857551774 + } value { name: "RouteTrafficG0" color: 10167040 diff --git a/data/drules_proto_vehicle_dark.txt b/data/drules_proto_vehicle_dark.txt index 593deb0ebc..8b5f2aa239 100644 --- a/data/drules_proto_vehicle_dark.txt +++ b/data/drules_proto_vehicle_dark.txt @@ -74948,6 +74948,10 @@ colors { name: "RoutePreview" color: 3019898879 } + value { + name: "RouteRuler" + color: 1308604747 + } value { name: "RouteTrafficG0" color: 6164237 diff --git a/data/styles/clear/style-clear/style.mapcss b/data/styles/clear/style-clear/style.mapcss index 338e3c114a..b4ac9186ea 100644 --- a/data/styles/clear/style-clear/style.mapcss +++ b/data/styles/clear/style-clear/style.mapcss @@ -36,6 +36,8 @@ colors RoutePedestrian-opacity: 0.8; RouteBicycle-color: #9C27B0; RouteBicycle-opacity: 0.8; + RouteRuler-color: #66347F; + RouteRuler-opacity: 0.9; RoutePreview-color: #000000; RoutePreview-opacity: 0.3; RouteMaskCar-color: #000000; diff --git a/data/styles/clear/style-night/style.mapcss b/data/styles/clear/style-night/style.mapcss index dc1da1d58e..a66b39e474 100644 --- a/data/styles/clear/style-night/style.mapcss +++ b/data/styles/clear/style-night/style.mapcss @@ -36,6 +36,8 @@ colors RoutePedestrian-opacity: 0.7; RouteBicycle-color: #FF4B8C; RouteBicycle-opacity: 0.7; + RouteRuler-color: #924ab5; + RouteRuler-opacity: 0.7; RoutePreview-color: #FFFFFF; RoutePreview-opacity: 0.3; RouteMaskCar-color: #000000; diff --git a/data/styles/vehicle/style-clear/style.mapcss b/data/styles/vehicle/style-clear/style.mapcss index 1c7bc14404..1ea44c0a29 100644 --- a/data/styles/vehicle/style-clear/style.mapcss +++ b/data/styles/vehicle/style-clear/style.mapcss @@ -36,6 +36,8 @@ colors RoutePedestrian-opacity: 0.8; RouteBicycle-color: #9C27B0; RouteBicycle-opacity: 0.8; + RouteRuler-color: #1D339E; + RouteRuler-opacity: 0.8; RoutePreview-color: #000000; RoutePreview-opacity: 0.3; RouteMaskCar-color: #000000; diff --git a/data/styles/vehicle/style-night/style.mapcss b/data/styles/vehicle/style-night/style.mapcss index fd3fa97c52..15f4579130 100644 --- a/data/styles/vehicle/style-night/style.mapcss +++ b/data/styles/vehicle/style-night/style.mapcss @@ -36,6 +36,8 @@ colors RoutePedestrian-opacity: 0.7; RouteBicycle-color: #FF4B8C; RouteBicycle-opacity: 0.7; + RouteRuler-color: #FFB94B; + RouteRuler-opacity: 0.7; RoutePreview-color: #FFFFFF; RoutePreview-opacity: 0.3; RouteMaskCar-color: #000000; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 9de12aaf60..a29bc30b03 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1433,7 +1433,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView, bool activeFram Render2dLayer(modelView); RenderUserMarksLayer(modelView, DepthLayer::UserLineLayer); - if (m_buildingsFramebuffer->IsSupported()) + if (m_buildingsFramebuffer->IsSupported() && !m_routeRenderer->IsRulerRoute()) { RenderTrafficLayer(modelView); if (!HasTransitRouteData()) diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 86cd564b66..8b7d1ad3aa 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -17,6 +17,7 @@ std::string const kRouteColor = "Route"; std::string const kRouteOutlineColor = "RouteOutline"; std::string const kRoutePedestrian = "RoutePedestrian"; std::string const kRouteBicycle = "RouteBicycle"; +std::string const kRouteRuler = "RouteRuler"; std::string const kRoutePreview = "RoutePreview"; std::string const kRouteMaskCar = "RouteMaskCar"; std::string const kRouteFirstSegmentArrowsMaskCar = "RouteFirstSegmentArrowsMaskCar"; @@ -797,10 +798,18 @@ void RouteRenderer::SetSubrouteVisibility(dp::DrapeID id, bool isVisible) bool RouteRenderer::HasTransitData() const { for (auto const & subroute : m_subroutes) - { if (subroute.m_subroute->m_routeType == RouteType::Transit) return true; - } + + return false; +} + +bool RouteRenderer::IsRulerRoute() const +{ + for (auto const & subroute : m_subroutes) + if (subroute.m_subroute->m_routeType == RouteType::Ruler) + return true; + return false; } diff --git a/drape_frontend/route_renderer.hpp b/drape_frontend/route_renderer.hpp index 5a1b2ab7ce..3bd4d0d668 100644 --- a/drape_frontend/route_renderer.hpp +++ b/drape_frontend/route_renderer.hpp @@ -24,6 +24,7 @@ extern std::string const kRouteColor; extern std::string const kRouteOutlineColor; extern std::string const kRoutePedestrian; extern std::string const kRouteBicycle; +extern std::string const kRouteRuler; extern std::string const kTransitStopInnerMarkerColor; class RouteRenderer final @@ -98,6 +99,7 @@ public: void SetSubrouteVisibility(dp::DrapeID id, bool isVisible); bool HasTransitData() const; + bool IsRulerRoute() const; bool HasData() const; bool HasPreviewData() const; diff --git a/drape_frontend/route_shape.hpp b/drape_frontend/route_shape.hpp index 76a4efb8e6..0380d5441d 100644 --- a/drape_frontend/route_shape.hpp +++ b/drape_frontend/route_shape.hpp @@ -46,7 +46,8 @@ enum class RouteType : uint8_t Pedestrian, Bicycle, Taxi, - Transit + Transit, + Ruler }; struct RoutePattern -- 2.45.3 From 35d4e158457a36050bdba7e79e38ba08a25d194b Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 15:20:51 +0300 Subject: [PATCH 03/14] In route preview mode user can continue route polyline by single tap. Signed-off-by: S. Kozyr --- map/framework.cpp | 26 ++++++++++++++++++++++++++ map/routing_manager.cpp | 24 ++++++++++++++++++++++++ map/routing_manager.hpp | 1 + 3 files changed, 51 insertions(+) diff --git a/map/framework.cpp b/map/framework.cpp index 4fb8133c81..b223fbe554 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2043,6 +2043,32 @@ void Framework::DeactivateHotelSearchMark() void Framework::OnTapEvent(place_page::BuildInfo const & buildInfo) { auto placePageInfo = BuildPlacePageInfo(buildInfo); + bool isRoutePoint = placePageInfo.has_value() && placePageInfo->IsRoutePoint(); + + if (m_routingManager.IsRoutingActive() + && m_routingManager.GetCurrentRouterType() == routing::RouterType::Ruler + && !buildInfo.m_isLongTap + && !isRoutePoint) + { + DeactivateMapSelection(true /* notifyUI */); + + // Continue route to the point + RouteMarkData data; + data.m_title = placePageInfo ? placePageInfo->GetTitle() : std::string(); + data.m_subTitle = std::string(); + data.m_pointType = RouteMarkType::Finish; + data.m_intermediateIndex = m_routingManager.GetRoutePointsCount(); + data.m_isMyPosition = false; + data.m_position = buildInfo.m_mercator; + + m_routingManager.ContinueRouteToPoint(std::move(data)); + + // Refresh route + m_routingManager.RemoveRoute(false /* deactivateFollowing */); + m_routingManager.BuildRoute(); + + return; + } if (placePageInfo) { diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 9f778e3f9d..c902d2a98c 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -862,6 +862,30 @@ void RoutingManager::AddRoutePoint(RouteMarkData && markData) ReorderIntermediatePoints(); } +void RoutingManager::ContinueRouteToPoint(RouteMarkData && markData) +{ + ASSERT(m_bmManager != nullptr, ()); + ASSERT(markData.m_pointType == RouteMarkType::Finish, ("New route point should have type RouteMarkType::Finish")); + RoutePointsLayout routePoints(*m_bmManager); + + // Finish point is now Intermediate point + RouteMarkPoint * finishMarkData = routePoints.GetRoutePointForEdit(RouteMarkType::Finish); + finishMarkData->SetRoutePointType(RouteMarkType::Intermediate); + finishMarkData->SetIntermediateIndex(routePoints.GetRoutePointsCount()-1); + + if (markData.m_isMyPosition) + { + RouteMarkPoint const * mark = routePoints.GetMyPositionPoint(); + if (mark) + routePoints.RemoveRoutePoint(mark->GetRoutePointType(), mark->GetIntermediateIndex()); + } + + markData.m_intermediateIndex = routePoints.GetRoutePointsCount(); + markData.m_isVisible = !markData.m_isMyPosition; + routePoints.AddRoutePoint(move(markData)); + ReorderIntermediatePoints(); +} + void RoutingManager::RemoveRoutePoint(RouteMarkType type, size_t intermediateIndex) { ASSERT(m_bmManager != nullptr, ()); diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp index 6995010828..2b42c5781d 100644 --- a/map/routing_manager.hpp +++ b/map/routing_manager.hpp @@ -226,6 +226,7 @@ public: void GenerateNotifications(std::vector & notifications); void AddRoutePoint(RouteMarkData && markData); + void ContinueRouteToPoint(RouteMarkData && markData); std::vector GetRoutePoints() const; size_t GetRoutePointsCount() const; void RemoveRoutePoint(RouteMarkType type, size_t intermediateIndex = 0); -- 2.45.3 From 2b6561d30bd4244368821b3ff0e45c9cfd07ae3c Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 21:53:36 +0300 Subject: [PATCH 04/14] [strings] placepage_distance is now available in Android Signed-off-by: S. Kozyr --- data/strings/strings.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/strings/strings.txt b/data/strings/strings.txt index 0eaae0a004..408e2300a9 100644 --- a/data/strings/strings.txt +++ b/data/strings/strings.txt @@ -5710,7 +5710,7 @@ zh-Hant = 它可讓您記錄特定期間所行經的路徑,並在地圖上看到該路徑。請注意:啟用此項功能會增加電池使用量。在時間間隔過期後,會從地圖中自動移除行進路線。 [placepage_distance] - tags = ios + tags = android,ios en = Distance af = Afstand ar = المسافة -- 2.45.3 From 386c12720a8f3db2399a2a2f69bc9741745181f1 Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 21:54:37 +0300 Subject: [PATCH 05/14] [strings] Regenerated strings Signed-off-by: S. Kozyr --- android/res/values-ar/strings.xml | 1 + android/res/values-be/strings.xml | 1 + android/res/values-ca/strings.xml | 1 + android/res/values-cs/strings.xml | 1 + android/res/values-da/strings.xml | 1 + android/res/values-de/strings.xml | 1 + android/res/values-es/strings.xml | 1 + android/res/values-et/strings.xml | 1 + android/res/values-eu/strings.xml | 1 + android/res/values-fa/strings.xml | 1 + android/res/values-fi/strings.xml | 1 + android/res/values-fr/strings.xml | 1 + android/res/values-hu/strings.xml | 1 + android/res/values-in/strings.xml | 1 + android/res/values-it/strings.xml | 1 + android/res/values-iw/strings.xml | 1 + android/res/values-ja/strings.xml | 1 + android/res/values-ko/strings.xml | 1 + android/res/values-mr/strings.xml | 1 + android/res/values-nb/strings.xml | 1 + android/res/values-nl/strings.xml | 1 + android/res/values-pl/strings.xml | 1 + android/res/values-pt-rBR/strings.xml | 1 + android/res/values-pt/strings.xml | 1 + android/res/values-ro/strings.xml | 1 + android/res/values-ru/strings.xml | 1 + android/res/values-sk/strings.xml | 1 + android/res/values-sv/strings.xml | 1 + android/res/values-th/strings.xml | 1 + android/res/values-tr/strings.xml | 1 + android/res/values-uk/strings.xml | 1 + android/res/values-vi/strings.xml | 1 + android/res/values-zh-rTW/strings.xml | 1 + android/res/values-zh/strings.xml | 1 + android/res/values/strings.xml | 1 + 35 files changed, 35 insertions(+) diff --git a/android/res/values-ar/strings.xml b/android/res/values-ar/strings.xml index a8923fb9fc..0878e695bf 100644 --- a/android/res/values-ar/strings.xml +++ b/android/res/values-ar/strings.xml @@ -240,6 +240,7 @@ 6 ساعات 12 ساعة 1 يوم + المسافة مشاهدة على الخريطة القائمة diff --git a/android/res/values-be/strings.xml b/android/res/values-be/strings.xml index e32d5d9138..185f87d83e 100644 --- a/android/res/values-be/strings.xml +++ b/android/res/values-be/strings.xml @@ -238,6 +238,7 @@ 6 гадзін 12 гадзін 1 дзень + Адлегласць Паглядзець на мапе Вэб-сайт diff --git a/android/res/values-ca/strings.xml b/android/res/values-ca/strings.xml index 6509b9173c..318cc5023f 100644 --- a/android/res/values-ca/strings.xml +++ b/android/res/values-ca/strings.xml @@ -229,6 +229,7 @@ 6 hores 12 hores 1 dia + Distància Veure al mapa Menú diff --git a/android/res/values-cs/strings.xml b/android/res/values-cs/strings.xml index 1fddef10a8..b195fb12c3 100644 --- a/android/res/values-cs/strings.xml +++ b/android/res/values-cs/strings.xml @@ -224,6 +224,7 @@ 6 hodin 12 hodin 1 den + Vzdálenost Zobrazit na mapě Webové stránky diff --git a/android/res/values-da/strings.xml b/android/res/values-da/strings.xml index e2f8fe4bab..0e8c0cba0b 100644 --- a/android/res/values-da/strings.xml +++ b/android/res/values-da/strings.xml @@ -220,6 +220,7 @@ 6 timer 12 timer 1 dag + Afstand Vis på kortet Hjemmeside diff --git a/android/res/values-de/strings.xml b/android/res/values-de/strings.xml index 77273b732d..c232779a57 100644 --- a/android/res/values-de/strings.xml +++ b/android/res/values-de/strings.xml @@ -237,6 +237,7 @@ 6 Stunden 12 Stunden 1 Tag + Entfernung Auf der Karte ansehen Webseite diff --git a/android/res/values-es/strings.xml b/android/res/values-es/strings.xml index d18079ce8a..bec07608b8 100644 --- a/android/res/values-es/strings.xml +++ b/android/res/values-es/strings.xml @@ -237,6 +237,7 @@ 6 horas 12 horas 1 día + Distancia Ver en el mapa Menú diff --git a/android/res/values-et/strings.xml b/android/res/values-et/strings.xml index 4ade70e815..7f76b663df 100644 --- a/android/res/values-et/strings.xml +++ b/android/res/values-et/strings.xml @@ -229,6 +229,7 @@ 6 tundi 12 tundi 1 päev + Kaugus Vaata kaardil Veebileht diff --git a/android/res/values-eu/strings.xml b/android/res/values-eu/strings.xml index a48ae6563c..c2dd253ec7 100644 --- a/android/res/values-eu/strings.xml +++ b/android/res/values-eu/strings.xml @@ -237,6 +237,7 @@ 6 ordu 12 ordu egun 1 + Distantzia Ikusi mapan Menua diff --git a/android/res/values-fa/strings.xml b/android/res/values-fa/strings.xml index 2e84f208e8..8e6016bd80 100644 --- a/android/res/values-fa/strings.xml +++ b/android/res/values-fa/strings.xml @@ -213,6 +213,7 @@ 6 ساعت 12 ساعت 1 روز + مسافت مشاهده بر روی نقشه وب سایت diff --git a/android/res/values-fi/strings.xml b/android/res/values-fi/strings.xml index c3542f46f2..077a680c4f 100644 --- a/android/res/values-fi/strings.xml +++ b/android/res/values-fi/strings.xml @@ -239,6 +239,7 @@ 6 tuntia 12 tuntia 1 päivä + Etäisyys Näytä kartalla Menu diff --git a/android/res/values-fr/strings.xml b/android/res/values-fr/strings.xml index ea676004b5..715c9996c4 100644 --- a/android/res/values-fr/strings.xml +++ b/android/res/values-fr/strings.xml @@ -239,6 +239,7 @@ 6 heures 12 heures 1 jour + Distance Voir sur la carte Menu diff --git a/android/res/values-hu/strings.xml b/android/res/values-hu/strings.xml index 9188a13972..727afeebf5 100644 --- a/android/res/values-hu/strings.xml +++ b/android/res/values-hu/strings.xml @@ -234,6 +234,7 @@ 6 óra 12 óra 1 nap + Távolság Megtekintés a térképen Honlap diff --git a/android/res/values-in/strings.xml b/android/res/values-in/strings.xml index c95119f35a..31598c9d1b 100644 --- a/android/res/values-in/strings.xml +++ b/android/res/values-in/strings.xml @@ -222,6 +222,7 @@ 6 jam 12 jam 1 hari + Jarak Tampilkan pada peta Situs Web diff --git a/android/res/values-it/strings.xml b/android/res/values-it/strings.xml index 8f4ea392ae..c370266b13 100644 --- a/android/res/values-it/strings.xml +++ b/android/res/values-it/strings.xml @@ -225,6 +225,7 @@ 6 ore 12 ore 1 giorno + Distanza Visualizza sulla mappa Sito web diff --git a/android/res/values-iw/strings.xml b/android/res/values-iw/strings.xml index af51fb157b..81610d5c3e 100644 --- a/android/res/values-iw/strings.xml +++ b/android/res/values-iw/strings.xml @@ -172,6 +172,7 @@ הצג על המסך מבנים תלת מימדיים כבויים במצב חיסכון בחשמל + מרחק ראה במפה תוֹשׁדָחֲ diff --git a/android/res/values-ja/strings.xml b/android/res/values-ja/strings.xml index 0214f1f5af..957cbf2d25 100644 --- a/android/res/values-ja/strings.xml +++ b/android/res/values-ja/strings.xml @@ -218,6 +218,7 @@ 6時間 12時間 1日 + 距離 地図に表示 ウェブサイト diff --git a/android/res/values-ko/strings.xml b/android/res/values-ko/strings.xml index 550c1ee84a..28fc0d629a 100644 --- a/android/res/values-ko/strings.xml +++ b/android/res/values-ko/strings.xml @@ -220,6 +220,7 @@ 6시간 12시간 1일 + 거리 지도 보기 웹사이트 diff --git a/android/res/values-mr/strings.xml b/android/res/values-mr/strings.xml index 4c5374d4ac..9386aa4f90 100644 --- a/android/res/values-mr/strings.xml +++ b/android/res/values-mr/strings.xml @@ -213,6 +213,7 @@ ६ तास १२ तास १ दिवस + अंतर नकाशावर पहा संकेतस्थळ diff --git a/android/res/values-nb/strings.xml b/android/res/values-nb/strings.xml index 71f31b3832..150296c1e7 100644 --- a/android/res/values-nb/strings.xml +++ b/android/res/values-nb/strings.xml @@ -239,6 +239,7 @@ 6 timer 12 timer 1 dag + Avstand Vis på kartet Meny diff --git a/android/res/values-nl/strings.xml b/android/res/values-nl/strings.xml index 5342bb9e29..dd786151d2 100644 --- a/android/res/values-nl/strings.xml +++ b/android/res/values-nl/strings.xml @@ -237,6 +237,7 @@ 6 uur 12 uur 1 dag + Afstand Op kaart bekijken Website diff --git a/android/res/values-pl/strings.xml b/android/res/values-pl/strings.xml index 1028273130..cab770122a 100644 --- a/android/res/values-pl/strings.xml +++ b/android/res/values-pl/strings.xml @@ -237,6 +237,7 @@ 6 godzin 12 godzin 1 dzień + Dystans Wyświetl na mapie Menu diff --git a/android/res/values-pt-rBR/strings.xml b/android/res/values-pt-rBR/strings.xml index f95d535aac..af26ff7a9f 100644 --- a/android/res/values-pt-rBR/strings.xml +++ b/android/res/values-pt-rBR/strings.xml @@ -235,6 +235,7 @@ 6 horas 12 horas 1 dia + Distância Ver no mapa Site diff --git a/android/res/values-pt/strings.xml b/android/res/values-pt/strings.xml index 70b7d596a7..f70a9e976f 100644 --- a/android/res/values-pt/strings.xml +++ b/android/res/values-pt/strings.xml @@ -225,6 +225,7 @@ 6 horas 12 horas 1 dia + Distância Ver no mapa Site diff --git a/android/res/values-ro/strings.xml b/android/res/values-ro/strings.xml index 56ffd26526..0db52e6bbb 100644 --- a/android/res/values-ro/strings.xml +++ b/android/res/values-ro/strings.xml @@ -225,6 +225,7 @@ 6 ore 12 ore 1 zi + Distanță Vezi pe hartă Site web diff --git a/android/res/values-ru/strings.xml b/android/res/values-ru/strings.xml index 8c57d7444c..548d62eec2 100644 --- a/android/res/values-ru/strings.xml +++ b/android/res/values-ru/strings.xml @@ -240,6 +240,7 @@ 6 часов 12 часов 1 сутки + Расстояние Посмотреть на карте Меню diff --git a/android/res/values-sk/strings.xml b/android/res/values-sk/strings.xml index eb40cc562b..4b0390da47 100644 --- a/android/res/values-sk/strings.xml +++ b/android/res/values-sk/strings.xml @@ -220,6 +220,7 @@ 6 hodín 12 hodín 1 deň + Vzdialenosť Zobraziť na mape Webové stránky diff --git a/android/res/values-sv/strings.xml b/android/res/values-sv/strings.xml index 63554e39a6..dfc48273ba 100644 --- a/android/res/values-sv/strings.xml +++ b/android/res/values-sv/strings.xml @@ -218,6 +218,7 @@ 6 timmar 12 timmar 1 dag + Avstånd Visa på kartan Webbplats diff --git a/android/res/values-th/strings.xml b/android/res/values-th/strings.xml index f3c9b581f9..ccee81d82e 100644 --- a/android/res/values-th/strings.xml +++ b/android/res/values-th/strings.xml @@ -222,6 +222,7 @@ 6 ชั่วโมง 12 ชั่วโมง 1 วัน + ระยะห่าง ดูบนแผนที่ เว็บไซต์ diff --git a/android/res/values-tr/strings.xml b/android/res/values-tr/strings.xml index 91829c1766..d57363ffec 100644 --- a/android/res/values-tr/strings.xml +++ b/android/res/values-tr/strings.xml @@ -239,6 +239,7 @@ 6 saat 12 saat 1 gün + Mesafe Haritada görüntüle Web Sitesi diff --git a/android/res/values-uk/strings.xml b/android/res/values-uk/strings.xml index 808e1f7c31..291007ad46 100644 --- a/android/res/values-uk/strings.xml +++ b/android/res/values-uk/strings.xml @@ -233,6 +233,7 @@ 6 годин 12 годин 1 день + Відстань Подивитись на мапі Меню diff --git a/android/res/values-vi/strings.xml b/android/res/values-vi/strings.xml index 53ce37a3b4..0e18ebbff9 100644 --- a/android/res/values-vi/strings.xml +++ b/android/res/values-vi/strings.xml @@ -220,6 +220,7 @@ 6 giờ 12 giờ 1 ngày + Khoảng cách Xem trên bản đồ Trang web diff --git a/android/res/values-zh-rTW/strings.xml b/android/res/values-zh-rTW/strings.xml index 5c91bf1f2c..684f78d926 100644 --- a/android/res/values-zh-rTW/strings.xml +++ b/android/res/values-zh-rTW/strings.xml @@ -225,6 +225,7 @@ 6小時 12小時 1天 + 距离 在地圖上查看 網站 diff --git a/android/res/values-zh/strings.xml b/android/res/values-zh/strings.xml index 742497a15a..9c3d875572 100644 --- a/android/res/values-zh/strings.xml +++ b/android/res/values-zh/strings.xml @@ -224,6 +224,7 @@ 6小时 12小时 1天 + 距离 在地图上查看 网站 diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 14007d0f72..928ab80a85 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -240,6 +240,7 @@ 6 hours 12 hours 1 day + Distance View on map Menu -- 2.45.3 From 810c9853c59d42b383ae4b3ee3e9742e68512260 Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 21:55:37 +0300 Subject: [PATCH 06/14] [Android] Added new routing type. Showing detailed ruler route info in bottom panel Signed-off-by: S. Kozyr --- android/jni/app/organicmaps/Framework.cpp | 1 + android/res/drawable/ic_ruler_route.xml | 31 ++++++++ .../layout/routing_bottom_panel_transit.xml | 2 +- android/res/layout/routing_plan.xml | 15 ++++ android/res/values/font_sizes.xml | 1 + android/res/values/themes-attrs.xml | 1 + android/res/values/themes-base.xml | 2 + android/src/app/organicmaps/Framework.java | 3 +- .../routing/RoutingBottomMenuController.java | 73 ++++++++++++++++--- .../routing/RoutingController.java | 13 ++-- .../routing/RoutingPlanController.java | 68 ++++++++++++----- .../organicmaps/routing/TransitStepInfo.java | 15 +++- .../organicmaps/routing/TransitStepType.java | 3 +- .../organicmaps/routing/TransitStepView.java | 8 ++ 14 files changed, 195 insertions(+), 41 deletions(-) create mode 100644 android/res/drawable/ic_ruler_route.xml diff --git a/android/jni/app/organicmaps/Framework.cpp b/android/jni/app/organicmaps/Framework.cpp index 407e73e852..4fd22617f4 100644 --- a/android/jni/app/organicmaps/Framework.cpp +++ b/android/jni/app/organicmaps/Framework.cpp @@ -1425,6 +1425,7 @@ Java_app_organicmaps_Framework_nativeSetRouter(JNIEnv * env, jclass, jint router case 1: type = Type::Pedestrian; break; case 2: type = Type::Bicycle; break; case 3: type = Type::Transit; break; + case 4: type = Type::Ruler; break; default: assert(false); break; } g_framework->GetRoutingManager().SetRouter(type); diff --git a/android/res/drawable/ic_ruler_route.xml b/android/res/drawable/ic_ruler_route.xml new file mode 100644 index 0000000000..c502863276 --- /dev/null +++ b/android/res/drawable/ic_ruler_route.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/android/res/layout/routing_bottom_panel_transit.xml b/android/res/layout/routing_bottom_panel_transit.xml index 22156f22ad..cce2c490be 100644 --- a/android/res/layout/routing_bottom_panel_transit.xml +++ b/android/res/layout/routing_bottom_panel_transit.xml @@ -46,7 +46,7 @@ android:id="@+id/transit_recycler_view" android:layout_marginTop="@dimen/margin_half_plus" android:layout_alignParentStart="true" - android:layout_below="@id/total_distance" + android:layout_below="@id/total_time" android:layout_width="match_parent" android:layout_height="wrap_content"/> diff --git a/android/res/layout/routing_plan.xml b/android/res/layout/routing_plan.xml index 1ca805f769..23382f782f 100644 --- a/android/res/layout/routing_plan.xml +++ b/android/res/layout/routing_plan.xml @@ -73,6 +73,14 @@ android:layout_marginEnd="12dp" tools:button="@drawable/ic_bike" tools:buttonTint="?iconTintLight" /> + + + + diff --git a/android/res/values/font_sizes.xml b/android/res/values/font_sizes.xml index 63aee99c7a..c118412a70 100644 --- a/android/res/values/font_sizes.xml +++ b/android/res/values/font_sizes.xml @@ -51,6 +51,7 @@ 20sp 16sp 14sp + 20sp 56sp 17sp diff --git a/android/res/values/themes-attrs.xml b/android/res/values/themes-attrs.xml index a5bd6ca2cb..d5b1c19b8c 100644 --- a/android/res/values/themes-attrs.xml +++ b/android/res/values/themes-attrs.xml @@ -42,6 +42,7 @@ + diff --git a/android/res/values/themes-base.xml b/android/res/values/themes-base.xml index da9956219d..79aeb84d0d 100644 --- a/android/res/values/themes-base.xml +++ b/android/res/values/themes-base.xml @@ -87,6 +87,7 @@ @drawable/back_arrow @color/black_4 + @color/black_4 @drawable/dot_divider @drawable/ic_layers_traffic_active @drawable/ic_layers_subway_active @@ -221,6 +222,7 @@ @drawable/back_arrow @color/white_4 + @color/white_4 @drawable/dot_divider_night @drawable/ic_layers_traffic_active_night @drawable/ic_layers_subway_active_night diff --git a/android/src/app/organicmaps/Framework.java b/android/src/app/organicmaps/Framework.java index 1b84662aab..7cbb8d1ab5 100644 --- a/android/src/app/organicmaps/Framework.java +++ b/android/src/app/organicmaps/Framework.java @@ -46,7 +46,7 @@ public class Framework public static final int MAP_STYLE_VEHICLE_DARK = 4; @Retention(RetentionPolicy.SOURCE) - @IntDef({ ROUTER_TYPE_VEHICLE, ROUTER_TYPE_PEDESTRIAN, ROUTER_TYPE_BICYCLE, ROUTER_TYPE_TRANSIT }) + @IntDef({ ROUTER_TYPE_VEHICLE, ROUTER_TYPE_PEDESTRIAN, ROUTER_TYPE_BICYCLE, ROUTER_TYPE_TRANSIT, ROUTER_TYPE_RULER }) public @interface RouterType {} @@ -54,6 +54,7 @@ public class Framework public static final int ROUTER_TYPE_PEDESTRIAN = 1; public static final int ROUTER_TYPE_BICYCLE = 2; public static final int ROUTER_TYPE_TRANSIT = 3; + public static final int ROUTER_TYPE_RULER = 4; @Retention(RetentionPolicy.SOURCE) @IntDef({DO_AFTER_UPDATE_NOTHING, DO_AFTER_UPDATE_AUTO_UPDATE, DO_AFTER_UPDATE_ASK_FOR_UPDATE}) diff --git a/android/src/app/organicmaps/routing/RoutingBottomMenuController.java b/android/src/app/organicmaps/routing/RoutingBottomMenuController.java index 35ab883c59..90c31c84a0 100644 --- a/android/src/app/organicmaps/routing/RoutingBottomMenuController.java +++ b/android/src/app/organicmaps/routing/RoutingBottomMenuController.java @@ -29,13 +29,17 @@ import androidx.recyclerview.widget.RecyclerView; import app.organicmaps.Framework; import app.organicmaps.R; +import app.organicmaps.bookmarks.data.DistanceAndAzimut; import app.organicmaps.location.LocationHelper; +import app.organicmaps.util.Distance; import app.organicmaps.widget.recycler.DotDividerItemDecoration; import app.organicmaps.widget.recycler.MultilineLayoutManager; import app.organicmaps.util.Graphics; import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.UiUtils; +import java.util.LinkedList; +import java.util.List; import java.util.Locale; final class RoutingBottomMenuController implements View.OnClickListener @@ -135,9 +139,11 @@ final class RoutingBottomMenuController implements View.OnClickListener void showAltitudeChartAndRoutingDetails() { - UiUtils.hide(mError, mActionFrame, mTransitFrame); + UiUtils.hide(mError, mActionFrame, mAltitudeChart, mAltitudeDifference, mTransitFrame); - showRouteAltitudeChart(); + if (!RoutingController.get().isVehicleRouterType() && + !RoutingController.get().isRulerRouterType()) + showRouteAltitudeChart(); showRoutingDetails(); UiUtils.show(mAltitudeChartFrame); } @@ -172,6 +178,53 @@ final class RoutingBottomMenuController implements View.OnClickListener distanceView.setText(info.getTotalPedestrianDistance() + " " + info.getTotalPedestrianDistanceUnits()); } + @SuppressLint("SetTextI18n") + void showRulerInfo(@NonNull RouteMarkData[] points, Distance totalLength) + { + UiUtils.hide(mError, mAltitudeChartFrame, mActionFrame, mAltitudeChartFrame); + showStartButton(false); + UiUtils.show(mTransitFrame); + RecyclerView rv = mTransitFrame.findViewById(R.id.transit_recycler_view); + if (points.length > 2) + { + UiUtils.show(rv); + TransitStepAdapter adapter = new TransitStepAdapter(); + rv.setLayoutManager(new MultilineLayoutManager()); + rv.setNestedScrollingEnabled(false); + rv.removeItemDecoration(mTransitViewDecorator); + rv.addItemDecoration(mTransitViewDecorator); + rv.setAdapter(adapter); + adapter.setItems(pointsToRulerSteps(points)); + } + else + UiUtils.hide(rv); // Show only distance between start and finish + + TextView totalTimeView = mTransitFrame.findViewById(R.id.total_time); + totalTimeView.setText(mContext.getString(R.string.placepage_distance) + ": " + + totalLength.mDistanceStr + " " + totalLength.getUnitsStr(mContext)); + + UiUtils.hide(mTransitFrame, R.id.dot); + UiUtils.hide(mTransitFrame, R.id.pedestrian_icon); + UiUtils.hide(mTransitFrame, R.id.total_distance); + } + + // Create steps info to use in TransitStepAdapter. + private List pointsToRulerSteps(RouteMarkData[] points) + { + List transitSteps = new LinkedList<>(); + for (int i = 1; i < points.length; i++) + { + RouteMarkData segmentStart = points[i - 1]; + RouteMarkData segmentEnd = points[i]; + DistanceAndAzimut dist = Framework.nativeGetDistanceAndAzimuthFromLatLon(segmentStart.mLat, segmentStart.mLon, segmentEnd.mLat, segmentEnd.mLon, 0); + if (i > 1) + transitSteps.add(TransitStepInfo.intermediatePoint(i - 2)); + transitSteps.add(TransitStepInfo.ruler(dist.getDistance().mDistanceStr, dist.getDistance().getUnitsStr(mContext))); + } + + return transitSteps; + } + void showAddStartFrame() { UiUtils.hide(mError, mTransitFrame); @@ -206,15 +259,17 @@ final class RoutingBottomMenuController implements View.OnClickListener UiUtils.hide(mActionFrame); } - void setStartButton() + void setStartButton(boolean show) { - mStart.setText(mContext.getText(R.string.p2p_start)); - mStart.setOnClickListener(v -> { - if (mListener != null) - mListener.onRoutingStart(); - }); + if (show) { + mStart.setText(mContext.getText(R.string.p2p_start)); + mStart.setOnClickListener(v -> { + if (mListener != null) + mListener.onRoutingStart(); + }); + } - showStartButton(true); + showStartButton(show); } private void showError(@NonNull String message) diff --git a/android/src/app/organicmaps/routing/RoutingController.java b/android/src/app/organicmaps/routing/RoutingController.java index 2461fb5664..5ac320a141 100644 --- a/android/src/app/organicmaps/routing/RoutingController.java +++ b/android/src/app/organicmaps/routing/RoutingController.java @@ -603,6 +603,11 @@ public class RoutingController implements Initializable return mLastRouterType == Framework.ROUTER_TYPE_VEHICLE; } + boolean isRulerRouterType() + { + return mLastRouterType == Framework.ROUTER_TYPE_RULER; + } + public boolean isNavigating() { return mState == State.NAVIGATION; @@ -815,22 +820,14 @@ public class RoutingController implements Initializable } if (isSamePoint) - { - Logger.d(TAG, "setEndPoint: skip the same end point"); return false; - } if (point != null && point.sameAs(startPoint)) { if (endPoint == null) - { - Logger.d(TAG, "setEndPoint: skip because end point is empty"); return false; - } - Logger.d(TAG, "setEndPoint: swap with starting point"); startPoint = endPoint; - } endPoint = point; diff --git a/android/src/app/organicmaps/routing/RoutingPlanController.java b/android/src/app/organicmaps/routing/RoutingPlanController.java index f3ca006bf4..8c895613cd 100644 --- a/android/src/app/organicmaps/routing/RoutingPlanController.java +++ b/android/src/app/organicmaps/routing/RoutingPlanController.java @@ -39,6 +39,8 @@ public class RoutingPlanController extends ToolbarController private final WheelProgressView mProgressTransit; @NonNull private final WheelProgressView mProgressBicycle; + @NonNull + private final WheelProgressView mProgressRuler; // @NonNull // private final WheelProgressView mProgressTaxi; @@ -93,6 +95,7 @@ public class RoutingPlanController extends ToolbarController mProgressPedestrian = progressFrame.findViewById(R.id.progress_pedestrian); mProgressTransit = progressFrame.findViewById(R.id.progress_transit); mProgressBicycle = progressFrame.findViewById(R.id.progress_bicycle); + mProgressRuler = progressFrame.findViewById(R.id.progress_ruler); // mProgressTaxi = (WheelProgressView) progressFrame.findViewById(R.id.progress_taxi); mRoutingBottomMenuController = RoutingBottomMenuController.newInstance(requireActivity(), mFrame, listener); @@ -128,12 +131,13 @@ public class RoutingPlanController extends ToolbarController { setupRouterButton(R.id.vehicle, R.drawable.ic_car, this::onVehicleModeSelected); setupRouterButton(R.id.pedestrian, R.drawable.ic_pedestrian, this::onPedestrianModeSelected); - setupRouterButton(R.id.bicycle, R.drawable.ic_bike, this::onBicycleModeSelected); // setupRouterButton(R.id.taxi, R.drawable.ic_taxi, this::onTaxiModeSelected); - setupRouterButton(R.id.transit, R.drawable.ic_transit, v -> onTransitModeSelected()); + setupRouterButton(R.id.transit, R.drawable.ic_transit, this::onTransitModeSelected); + setupRouterButton(R.id.bicycle, R.drawable.ic_bike, this::onBicycleModeSelected); + setupRouterButton(R.id.ruler, R.drawable.ic_ruler_route, this::onRulerModeSelected); } - private void onTransitModeSelected() + private void onTransitModeSelected(@NonNull View v) { RoutingController.get().setRouterType(Framework.ROUTER_TYPE_TRANSIT); } @@ -143,6 +147,11 @@ public class RoutingPlanController extends ToolbarController RoutingController.get().setRouterType(Framework.ROUTER_TYPE_BICYCLE); } + private void onRulerModeSelected(@NonNull View v) + { + RoutingController.get().setRouterType(Framework.ROUTER_TYPE_RULER); + } + private void onPedestrianModeSelected(@NonNull View v) { RoutingController.get().setRouterType(Framework.ROUTER_TYPE_PEDESTRIAN); @@ -188,39 +197,53 @@ public class RoutingPlanController extends ToolbarController return; } - mRoutingBottomMenuController.setStartButton(); + if (isRulerType()) + { + RoutingInfo routingInfo = RoutingController.get().getCachedRoutingInfo(); + if (routingInfo != null) + mRoutingBottomMenuController.showRulerInfo(Framework.nativeGetRoutePoints(), routingInfo.distToTarget); + return; + } + + boolean showStartButton = !RoutingController.get().isRulerRouterType(); + mRoutingBottomMenuController.setStartButton(showStartButton); mRoutingBottomMenuController.showAltitudeChartAndRoutingDetails(); } public void updateBuildProgress(int progress, @Framework.RouterType int router) { UiUtils.invisible(mProgressVehicle, mProgressPedestrian, mProgressTransit, - mProgressBicycle); + mProgressBicycle, mProgressRuler); WheelProgressView progressView; - if (router == Framework.ROUTER_TYPE_VEHICLE) + switch(router) { + case Framework.ROUTER_TYPE_VEHICLE: mRouterTypes.check(R.id.vehicle); progressView = mProgressVehicle; - } - else if (router == Framework.ROUTER_TYPE_PEDESTRIAN) - { + break; + case Framework.ROUTER_TYPE_PEDESTRIAN: mRouterTypes.check(R.id.pedestrian); progressView = mProgressPedestrian; - } -// else if (router == Framework.ROUTER_TYPE_TAXI) -// { -// mRouterTypes.check(R.id.taxi); -// progressView = mProgressTaxi; -// } - else if (router == Framework.ROUTER_TYPE_TRANSIT) - { + break; + //case Framework.ROUTER_TYPE_TAXI: + // { + // mRouterTypes.check(R.id.taxi); + // progressView = mProgressTaxi; + // } + case Framework.ROUTER_TYPE_TRANSIT: mRouterTypes.check(R.id.transit); progressView = mProgressTransit; - } - else - { + break; + case Framework.ROUTER_TYPE_BICYCLE: mRouterTypes.check(R.id.bicycle); progressView = mProgressBicycle; + break; + case Framework.ROUTER_TYPE_RULER: + mRouterTypes.check(R.id.ruler); + progressView = mProgressRuler; + break; + default: + throw new IllegalArgumentException("unknown router: " + router); } RoutingToolbarButton button = mRouterTypes @@ -246,6 +269,11 @@ public class RoutingPlanController extends ToolbarController return RoutingController.get().isTransitType(); } + private boolean isRulerType() + { + return RoutingController.get().isRulerRouterType(); + } + void saveRoutingPanelState(@NonNull Bundle outState) { mRoutingBottomMenuController.saveRoutingPanelState(outState); diff --git a/android/src/app/organicmaps/routing/TransitStepInfo.java b/android/src/app/organicmaps/routing/TransitStepInfo.java index 64b3a517fb..9bcff82c4d 100644 --- a/android/src/app/organicmaps/routing/TransitStepInfo.java +++ b/android/src/app/organicmaps/routing/TransitStepInfo.java @@ -18,10 +18,11 @@ public class TransitStepInfo private static final int TRANSIT_TYPE_TRAIN = 3; private static final int TRANSIT_TYPE_LIGHT_RAIL = 4; private static final int TRANSIT_TYPE_MONORAIL = 5; + private static final int TRANSIT_TYPE_RULER = 6; @Retention(RetentionPolicy.SOURCE) @IntDef({ TRANSIT_TYPE_INTERMEDIATE_POINT, TRANSIT_TYPE_PEDESTRIAN, TRANSIT_TYPE_SUBWAY, - TRANSIT_TYPE_TRAIN, TRANSIT_TYPE_LIGHT_RAIL, TRANSIT_TYPE_MONORAIL }) + TRANSIT_TYPE_TRAIN, TRANSIT_TYPE_LIGHT_RAIL, TRANSIT_TYPE_MONORAIL, TRANSIT_TYPE_RULER}) @interface TransitType {} @NonNull @@ -48,6 +49,18 @@ public class TransitStepInfo mIntermediateIndex = intermediateIndex; } + @NonNull + public static TransitStepInfo intermediatePoint(int intermediateIndex) + { + return new TransitStepInfo(TRANSIT_TYPE_INTERMEDIATE_POINT, null, null, 0, null, 0, intermediateIndex); + } + + @NonNull + public static TransitStepInfo ruler(@NonNull String distance, @NonNull String distanceUnits) + { + return new TransitStepInfo(TRANSIT_TYPE_RULER, distance, distanceUnits, 0, null, 0, -1); + } + @NonNull public TransitStepType getType() { diff --git a/android/src/app/organicmaps/routing/TransitStepType.java b/android/src/app/organicmaps/routing/TransitStepType.java index 4aea7389b8..bf1ffd9a6d 100644 --- a/android/src/app/organicmaps/routing/TransitStepType.java +++ b/android/src/app/organicmaps/routing/TransitStepType.java @@ -12,7 +12,8 @@ public enum TransitStepType SUBWAY(R.drawable.ic_20px_route_planning_metro), TRAIN(R.drawable.ic_20px_route_planning_train), LIGHT_RAIL(R.drawable.ic_20px_route_planning_lightrail), - MONORAIL(R.drawable.ic_20px_route_planning_monorail); + MONORAIL(R.drawable.ic_20px_route_planning_monorail), + RULER(R.drawable.ic_ruler_route); @DrawableRes private final int mDrawable; diff --git a/android/src/app/organicmaps/routing/TransitStepView.java b/android/src/app/organicmaps/routing/TransitStepView.java index 5955557530..87d5116828 100644 --- a/android/src/app/organicmaps/routing/TransitStepView.java +++ b/android/src/app/organicmaps/routing/TransitStepView.java @@ -85,6 +85,12 @@ public class TransitStepView extends View implements MultilineLayoutManager.Sque mDrawable = null; mText = String.valueOf(info.getIntermediateIndex() + 1); } + else if (mStepType == TransitStepType.RULER) + { + mDrawable = null; + mText = info.getDistance() + " " + info.getDistanceUnits(); + mTextPaint.setColor(Color.BLACK); + } else { mDrawable = ResourcesCompat.getDrawable(getResources(), mStepType.getDrawable(), null); @@ -101,6 +107,8 @@ public class TransitStepView extends View implements MultilineLayoutManager.Sque { case PEDESTRIAN: return ThemeUtils.getColor(context, R.attr.transitPedestrianBackground); + case RULER: + return ThemeUtils.getColor(context, R.attr.transitRulerBackground); case INTERMEDIATE_POINT: return ThemeUtils.getColor(context, R.attr.colorPrimary); default: -- 2.45.3 From bd584809a11c86770869d6e5bcd30fdb45641376 Mon Sep 17 00:00:00 2001 From: "S. Kozyr" Date: Sat, 26 Aug 2023 21:56:28 +0300 Subject: [PATCH 07/14] [iOS] Added new routing type. Showing detailed ruler route info in bottom panel Signed-off-by: S. Kozyr --- .../MWMNavigationDashboardManager+Entity.h | 3 +- .../MWMNavigationDashboardManager+Entity.mm | 52 ++++++++++++++--- .../MWMNavigationDashboardManager.mm | 17 ++++-- .../Views/RoutePreview/MWMRoutePreview.mm | 3 +- .../RoutePreview/MWMiPadRoutePreview.xib | 13 ++--- .../RoutePreview/MWMiPhoneRoutePreview.xib | 54 ++++++++---------- .../BaseRoutePreviewStatus.swift | 1 + .../TransportRoutePreviewStatus.swift | 3 + .../TransportRuler.swift | 36 ++++++++++++ .../TransportTransitSteps/TransportRuler.xib | 56 +++++++++++++++++++ .../TransportTransitStepsCollectionView.swift | 4 +- .../TransportTransitTrain.swift | 1 + .../Views/RoutePreview/RouteStartButton.swift | 5 ++ iphone/Maps/Core/Routing/MWMCoreRouterType.h | 2 + iphone/Maps/Core/Routing/MWMRouter.mm | 3 +- .../Core/Routing/MWMRouterTransitStepInfo.h | 12 ++-- .../Core/Routing/MWMRouterTransitStepInfo.mm | 11 ---- .../Maps/Core/Routing/MWMRouterTransitType.h | 3 +- iphone/Maps/Core/Routing/MWMRouterType.h | 1 + .../ic_ruler_route.imageset/Contents.json | 12 ++++ .../ic_ruler_route.svg | 13 +++++ .../Contents.json | 12 ++++ .../ic_ruler_route_highlighted.svg | 11 ++++ .../Contents.json | 12 ++++ .../ic_ruler_route_selected.svg | 12 ++++ iphone/Maps/Maps.xcodeproj/project.pbxproj | 8 +++ .../routing/routing.xcodeproj/project.pbxproj | 8 +++ 27 files changed, 294 insertions(+), 74 deletions(-) create mode 100644 iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/RoutePreviewStatus/TransportTransitSteps/TransportRuler.swift create mode 100644 iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/RoutePreviewStatus/TransportTransitSteps/TransportRuler.xib create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route.imageset/ic_ruler_route.svg create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route_highlighted.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route_highlighted.imageset/ic_ruler_route_highlighted.svg create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route_selected.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/NavigationDashboard/ic_ruler_route_selected.imageset/ic_ruler_route_selected.svg diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.h b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.h index bbc1346f52..76c35e3290 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.h +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.h @@ -1,4 +1,5 @@ #import "MWMNavigationDashboardManager.h" +#import "MWMRoutePoint.h" #import "MWMRouterType.h" namespace routing { @@ -9,7 +10,7 @@ struct TransitRouteInfo; @interface MWMNavigationDashboardManager (Entity) -- (void)updateFollowingInfo:(routing::FollowingInfo const &)info type:(MWMRouterType)type; +- (void)updateFollowingInfo:(routing::FollowingInfo const &)info routePoints:(NSArray *)points type:(MWMRouterType)type; - (void)updateTransitInfo:(TransitRouteInfo const &)info; @end diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.mm b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.mm index 419434c207..2305c41e5f 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.mm +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager+Entity.mm @@ -6,6 +6,7 @@ #import "SwiftBridge.h" #import +#include #include "routing/following_info.hpp" #include "routing/turns.hpp" @@ -69,10 +70,13 @@ UIImage *image(routing::turns::PedestrianDirection t) { } NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString *distanceUnits, - NSDictionary *primaryAttributes, NSDictionary *secondaryAttributes, BOOL isWalk) { - NSString *eta = [NSDateComponentsFormatter etaStringFrom:time]; - auto result = [[NSMutableAttributedString alloc] initWithString:eta attributes:primaryAttributes]; - [result appendAttributedString:MWMNavigationDashboardEntity.estimateDot]; + NSDictionary *primaryAttributes, NSDictionary *secondaryAttributes, BOOL isWalk, BOOL showEta) { + auto result = [[NSMutableAttributedString alloc] initWithString:@""]; + if (showEta) { + NSString *eta = [NSDateComponentsFormatter etaStringFrom:time]; + [result appendAttributedString:[[NSMutableAttributedString alloc] initWithString:eta attributes:primaryAttributes]]; + [result appendAttributedString:MWMNavigationDashboardEntity.estimateDot]; + } if (isWalk) { UIFont *font = primaryAttributes[NSFontAttributeName]; @@ -95,6 +99,32 @@ NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString * return result; } + +NSArray *buildRouteTransitSteps(NSArray *points) { + NSMutableArray *steps = [NSMutableArray arrayWithCapacity:[points count]*2-1]; + auto const numPoints = [points count]; + for (int i = 0; i < numPoints-1; i++) { + MWMRoutePoint* segmentStart = points[i]; + MWMRoutePoint* segmentEnd = points[i+1]; + auto const distance = platform::Distance::CreateFormatted( + ms::DistanceOnEarth(segmentStart.latitude, segmentStart.longitude, segmentEnd.latitude, segmentEnd.longitude)); + + MWMRouterTransitStepInfo* segmentInfo = [[MWMRouterTransitStepInfo alloc] init]; + segmentInfo.type = MWMRouterTransitTypeRuler; + segmentInfo.distance = @(distance.GetDistanceString().c_str()); + segmentInfo.distanceUnits = @(distance.GetUnitsString().c_str()); + steps[i*2] = segmentInfo; + + if (i < numPoints-2) { + MWMRouterTransitStepInfo* stopInfo = [[MWMRouterTransitStepInfo alloc] init]; + stopInfo.type = MWMRouterTransitTypeIntermediatePoint; + stopInfo.intermediateIndex = i; + steps[i*2+1] = stopInfo; + } + } + + return steps; +} } // namespace @interface MWMNavigationDashboardEntity () @@ -155,7 +185,7 @@ NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString * @implementation MWMNavigationDashboardManager (Entity) -- (void)updateFollowingInfo:(routing::FollowingInfo const &)info type:(MWMRouterType)type { +- (void)updateFollowingInfo:(routing::FollowingInfo const &)info routePoints:(NSArray *)points type:(MWMRouterType)type { if ([MWMRouter isRouteFinished]) { [MWMRouter stopRouting]; AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); @@ -163,6 +193,8 @@ NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString * } if (auto entity = self.entity) { + BOOL showEta = (type != MWMRouterTypeRuler); + entity.isValid = YES; entity.timeToTarget = info.m_time; entity.targetDistance = @(info.m_distToTarget.GetDistanceString().c_str()); @@ -174,7 +206,11 @@ NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString * entity.speedLimitMps = info.m_speedLimitMps; entity.estimate = estimate(entity.timeToTarget, entity.targetDistance, entity.targetUnits, - self.etaAttributes, self.etaSecondaryAttributes, NO); + self.etaAttributes, self.etaSecondaryAttributes, NO, showEta); + if (type == MWMRouterTypeRuler && [points count] > 2) + entity.transitSteps = buildRouteTransitSteps(points); + else + entity.transitSteps = [[NSArray alloc] init]; if (type == MWMRouterTypePedestrian) { entity.turnImage = image(info.m_pedestrianTurn); @@ -200,8 +236,8 @@ NSAttributedString *estimate(NSTimeInterval time, NSString *distance, NSString * entity.isValid = YES; entity.estimate = estimate(info.m_totalTimeInSec, @(info.m_totalPedestrianDistanceStr.c_str()), - @(info.m_totalPedestrianUnitsSuffix.c_str()), self.etaAttributes, self.etaSecondaryAttributes, YES); - NSMutableArray *transitSteps = [@[] mutableCopy]; + @(info.m_totalPedestrianUnitsSuffix.c_str()), self.etaAttributes, self.etaSecondaryAttributes, YES, YES); + NSMutableArray *transitSteps = [NSMutableArray new]; for (auto const &stepInfo : info.m_steps) [transitSteps addObject:[[MWMRouterTransitStepInfo alloc] initWithStepInfo:stepInfo]]; entity.transitSteps = transitSteps; diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager.mm b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager.mm index 1b0f753654..ce4485b091 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager.mm +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/MWMNavigationDashboardManager.mm @@ -82,7 +82,7 @@ NSString *const kNavigationControlViewXibName = @"NavigationControlView"; if (!entity.isValid) return; [_navigationInfoView onNavigationInfoUpdated:entity]; - if ([MWMRouter type] == MWMRouterTypePublicTransport) + if ([MWMRouter type] == MWMRouterTypePublicTransport || [MWMRouter type] == MWMRouterTypeRuler) [_transportRoutePreviewStatus onNavigationInfoUpdated:entity]; else [_baseRoutePreviewStatus onNavigationInfoUpdated:entity]; @@ -172,17 +172,24 @@ NSString *const kNavigationControlViewXibName = @"NavigationControlView"; - (void)stateReady { // TODO: Here assert sometimes fires with _state = MWMNavigationDashboardStateReady, if app was stopped while navigating and then restarted. - NSAssert(_state == MWMNavigationDashboardStatePlanning, @"Invalid state change (ready)"); + // Also in ruler mode when new point is added by single tap on the map state MWMNavigationDashboardStatePlanning is skipped and we get _state = MWMNavigationDashboardStateReady. + NSAssert(_state == MWMNavigationDashboardStatePlanning || _state == MWMNavigationDashboardStateReady, @"Invalid state change (ready)"); [self setRouteBuilderProgress:100.]; [self updateGoButtonTitle]; auto const isTransport = ([MWMRouter type] == MWMRouterTypePublicTransport); - if (isTransport) + auto const isRuler = ([MWMRouter type] == MWMRouterTypeRuler); + if (isTransport || isRuler) [self.transportRoutePreviewStatus showReady]; else [self.baseRoutePreviewStatus showReady]; - self.goButtonsContainer.hidden = isTransport; + self.goButtonsContainer.hidden = (isTransport || isRuler); for (MWMRouteStartButton *button in self.goButtons) - [button stateReady]; + { + if (isRuler) + [button stateHidden]; + else + [button stateReady]; + } } - (void)onRouteStart { diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMRoutePreview.mm b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMRoutePreview.mm index 1536ed3c0a..b9a12b74d1 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMRoutePreview.mm +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMRoutePreview.mm @@ -18,7 +18,7 @@ static CGFloat const kDrivingOptionsHeight = 48; @property(weak, nonatomic) IBOutlet UIView * contentView; @property(weak, nonatomic) IBOutlet UIView * pedestrian; @property(weak, nonatomic) IBOutlet UIView * publicTransport; -@property(weak, nonatomic) IBOutlet UIView * helicopter; +@property(weak, nonatomic) IBOutlet UIView * ruler; @property(weak, nonatomic) IBOutlet UIView * vehicle; @property(strong, nonatomic) IBOutlet NSLayoutConstraint * drivingOptionHeightConstraint; @property(strong, nonatomic) IBOutlet UIButton * drivingOptionsButton; @@ -73,6 +73,7 @@ static CGFloat const kDrivingOptionsHeight = 48; imageName:@"ic_train" routerType:MWMRouterTypePublicTransport]; [self addProgress:self.bicycle imageName:@"ic_bike" routerType:MWMRouterTypeBicycle]; + [self addProgress:self.ruler imageName:@"ic_ruler_route" routerType:MWMRouterTypeRuler]; } - (void)addProgress:(UIView *)parentView diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPadRoutePreview.xib b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPadRoutePreview.xib index 9870f1e607..a2466c75e3 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPadRoutePreview.xib +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPadRoutePreview.xib @@ -1,9 +1,9 @@ - + - + @@ -109,10 +109,10 @@ - + - + @@ -139,9 +139,6 @@ - - - @@ -457,9 +454,9 @@ + - diff --git a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPhoneRoutePreview.xib b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPhoneRoutePreview.xib index 282404ff77..b0f8a102e7 100644 --- a/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPhoneRoutePreview.xib +++ b/iphone/Maps/Classes/CustomViews/NavigationDashboard/Views/RoutePreview/MWMiPhoneRoutePreview.xib @@ -1,9 +1,9 @@ - + - + @@ -47,17 +47,17 @@ - + - + - + @@ -82,7 +82,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -98,17 +98,17 @@ - + - - + + - + @@ -142,17 +142,6 @@ - - - - - - - - - - - @@ -198,7 +187,7 @@ - + @@ -209,7 +198,7 @@ - + @@ -239,8 +228,8 @@ - @@ -400,7 +392,7 @@ - + @@ -412,8 +404,8 @@ -