diff --git a/geometry/screenbase.cpp b/geometry/screenbase.cpp index 8faefb96dd..cd81c273f9 100644 --- a/geometry/screenbase.cpp +++ b/geometry/screenbase.cpp @@ -208,6 +208,14 @@ void ScreenBase::GetTouchRect(m2::PointD const & pixPoint, double pixRadius, glbRect = m2::AnyRectD(PtoG(pixPoint), m_Angle, m2::RectD(-r, -r, r, r)); } +void ScreenBase::GetTouchRect(m2::PointD const & pixPoint, double pxWidth, + double pxHeight, m2::AnyRectD & glbRect) const +{ + double const width = pxWidth * m_Scale; + double const height = pxHeight * m_Scale; + glbRect = m2::AnyRectD(PtoG(pixPoint), m_Angle, m2::RectD(-width, -height, width, height)); +} + bool IsPanningAndRotate(ScreenBase const & s1, ScreenBase const & s2) { m2::RectD const & r1 = s1.GlobalRect().GetLocalRect(); diff --git a/geometry/screenbase.hpp b/geometry/screenbase.hpp index 4fc5c51703..f820df3671 100644 --- a/geometry/screenbase.hpp +++ b/geometry/screenbase.hpp @@ -102,6 +102,8 @@ public: void PtoG(m2::RectD const & pr, m2::RectD & gr) const; void GetTouchRect(m2::PointD const & pixPoint, double pixRadius, m2::AnyRectD & glbRect) const; + void GetTouchRect(const m2::PointD & pixPoint, double pxWidth, + double pxHeight, m2::AnyRectD & glbRect) const; MatrixT const & GtoPMatrix() const { return m_GtoP; } MatrixT const & PtoGMatrix() const { return m_PtoG; } diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index d6b5350361..f83519edf3 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -323,14 +323,15 @@ namespace class BestUserMarkFinder { public: - BestUserMarkFinder(m2::AnyRectD const & rect) - : m_rect(rect) + BestUserMarkFinder(BookmarkManager::TouchRectHolder const & rectHolder) + : m_rectHolder(rectHolder) , m_d(numeric_limits::max()) , m_mark(NULL) {} void operator()(UserMarkContainer const * container) { - UserMark const * findedMark = container->FindMarkInRect(m_rect, m_d); + m2::AnyRectD const & rect = m_rectHolder.GetTouchArea(container->GetType()); + UserMark const * findedMark = container->FindMarkInRect(rect, m_d); if (findedMark != NULL) m_mark = findedMark; } @@ -338,15 +339,39 @@ namespace UserMark const * GetFindedMark() const { return m_mark; } private: - m2::AnyRectD const & m_rect; + BookmarkManager::TouchRectHolder const & m_rectHolder; double m_d; UserMark const * m_mark; }; + + class SimpleTouchRectHolder : public BookmarkManager::TouchRectHolder + { + public: + SimpleTouchRectHolder(m2::AnyRectD const & rect) + : m_rect(rect) + { + } + + m2::AnyRectD const & GetTouchArea(UserMarkContainer::Type type) const + { + UNUSED_VALUE(type); + return m_rect; + } + + private: + m2::AnyRectD const & m_rect; + }; } UserMark const * BookmarkManager::FindNearestUserMark(m2::AnyRectD const & rect) const { - BestUserMarkFinder finder(rect); + SimpleTouchRectHolder holder(rect); + return FindNearestUserMark(holder); +} + +UserMark const * BookmarkManager::FindNearestUserMark(TouchRectHolder & holder) const +{ + BestUserMarkFinder finder(holder); for_each(m_categories.begin(), m_categories.end(), bind(&BestUserMarkFinder::operator(), &finder, _1)); finder(FindUserMarksContainer(UserMarkContainer::API_MARK)); finder(FindUserMarksContainer(UserMarkContainer::SEARCH_MARK)); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 53092f8204..37caa8cb10 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -62,7 +62,14 @@ public: void ActivateMark(UserMark const * mark, bool needAnim); bool UserMarkHasActive() const; + class TouchRectHolder + { + public: + virtual m2::AnyRectD const & GetTouchArea(UserMarkContainer::Type type) const = 0; + }; + UserMark const * FindNearestUserMark(m2::AnyRectD const & rect) const; + UserMark const * FindNearestUserMark(TouchRectHolder & holder) const; /// Additional layer methods void UserMarksSetVisible(UserMarkContainer::Type type, bool isVisible); diff --git a/map/framework.cpp b/map/framework.cpp index f113a415fd..a8aa7d0015 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -66,6 +66,11 @@ Framework::FixedPosition::FixedPosition() } #endif +namespace +{ + static const int BM_TOUCH_PIXEL_INCREASE = 20; +} + void Framework::AddMap(string const & file) { LOG(LINFO, ("Loading map:", file)); @@ -1622,6 +1627,34 @@ bool Framework::HasActiveUserMark() const return m_bmManager.UserMarkHasActive(); } +namespace +{ + class MainTouchRectHolder : public BookmarkManager::TouchRectHolder + { + public: + MainTouchRectHolder(m2::AnyRectD const & defaultRect, m2::AnyRectD const & bmRect) + : m_defRect(defaultRect) + , m_bmRect(bmRect) + { + } + + m2::AnyRectD const & GetTouchArea(UserMarkContainer::Type type) const + { + switch (type) + { + case UserMarkContainer::BOOKMARK_MARK: + return m_bmRect; + default: + return m_defRect; + } + } + + private: + m2::AnyRectD const & m_defRect; + m2::AnyRectD const & m_bmRect; + }; +} + UserMark const * Framework::GetUserMark(m2::PointD const & pxPoint, bool isLongPress) { DisconnectMyPositionUpdate(); @@ -1644,7 +1677,12 @@ UserMark const * Framework::GetUserMark(m2::PointD const & pxPoint, bool isLongP } } - UserMark const * mark = m_bmManager.FindNearestUserMark(rect); + m2::AnyRectD bmSearchRect; + double pxWidth = TOUCH_PIXEL_RADIUS * GetVisualScale(); + double pxHeight = (TOUCH_PIXEL_RADIUS + BM_TOUCH_PIXEL_INCREASE) * GetVisualScale(); + m_navigator.GetTouchRect(pxPoint + m2::PointD(0, BM_TOUCH_PIXEL_INCREASE), pxWidth, pxHeight, bmSearchRect); + MainTouchRectHolder holder(rect, bmSearchRect); + UserMark const * mark = m_bmManager.FindNearestUserMark(holder); if (m_bmManager.UserMarkHasActive() && !isLongPress) return mark; diff --git a/map/map_tests/bookmarks_test.cpp b/map/map_tests/bookmarks_test.cpp index d0ac70526c..f445f515c5 100644 --- a/map/map_tests/bookmarks_test.cpp +++ b/map/map_tests/bookmarks_test.cpp @@ -218,6 +218,7 @@ namespace { m2::AnyRectD rect; fm.GetNavigator().GetTouchRect(fm.GtoP(pt), 20, rect); + return fm.GetBookmarkManager().FindNearestUserMark(rect); } diff --git a/map/navigator.cpp b/map/navigator.cpp index 8d5d48b881..633a4bfec2 100644 --- a/map/navigator.cpp +++ b/map/navigator.cpp @@ -130,6 +130,13 @@ void Navigator::GetTouchRect(m2::PointD const & pixPoint, double pixRadius, m2:: m_Screen.GetTouchRect(ShiftPoint(pixPoint), pixRadius, glbRect); } +void Navigator::GetTouchRect(m2::PointD const & pixPoint, + double pxWidth, double pxHeight, + m2::AnyRectD & glbRect) const +{ + m_Screen.GetTouchRect(ShiftPoint(pixPoint), pxWidth, pxHeight, glbRect); +} + bool Navigator::CanShrinkInto(ScreenBase const & screen, m2::RectD const & boundRect) { m2::RectD clipRect = screen.ClipRect(); diff --git a/map/navigator.hpp b/map/navigator.hpp index d145cb4be5..8b0974a975 100644 --- a/map/navigator.hpp +++ b/map/navigator.hpp @@ -35,6 +35,9 @@ public: m2::PointD PtoG(m2::PointD const & pt) const; void GetTouchRect(m2::PointD const & pixPoint, double pixRadius, m2::AnyRectD & glbRect) const; + void GetTouchRect(const m2::PointD & pixPoint, + double pxWidth, double pxHeight, + m2::AnyRectD & glbRect) const; void StartDrag(m2::PointD const & pt, double timeInSec); void DoDrag(m2::PointD const & pt, double timeInSec);