From 369d5da2473f4d4c3de6fb3feb0907eab54fd41d Mon Sep 17 00:00:00 2001 From: ExMix Date: Tue, 13 May 2014 13:31:41 +0300 Subject: [PATCH] [core] new way of bookmark, search results and api points store --- .../maps/bookmarks/data/BookmarkManager.cpp | 8 - .../maps/bookmarks/data/BookmarkManager.java | 2 - base/stl_add.hpp | 6 + graphics/depth_constants.hpp | 7 +- map/bookmark.cpp | 68 ++- map/bookmark.hpp | 122 ++++-- map/bookmark_manager.cpp | 145 +++++-- map/bookmark_manager.hpp | 35 +- map/events.hpp | 15 + map/framework.cpp | 356 ++++------------ map/framework.hpp | 52 +-- map/mwm_url.cpp | 102 +++-- map/mwm_url.hpp | 52 +-- map/user_mark.cpp | 69 ++++ map/user_mark.hpp | 114 +++++ map/user_mark_container.cpp | 390 ++++++++++++++++++ map/user_mark_container.hpp | 114 +++++ 17 files changed, 1113 insertions(+), 544 deletions(-) create mode 100644 map/user_mark.cpp create mode 100644 map/user_mark.hpp create mode 100644 map/user_mark_container.cpp create mode 100644 map/user_mark_container.hpp diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index c9ceeddb50..ff92bb334a 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -71,14 +71,6 @@ extern "C" } } - JNIEXPORT jobject JNICALL - Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_getBookmark( - JNIEnv * env, jobject thiz, jdouble px, jdouble py) - { - BookmarkAndCategory const bac = frm()->GetBookmark(m2::PointD(px, py)); - return jni::GetNewPoint(env, m2::PointI(bac.first, bac.second)); - } - JNIEXPORT jstring JNICALL Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_saveToKMZFile( JNIEnv * env, jobject thiz, jint catID, jstring tmpPath) diff --git a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java index 917c0b03b7..867be1c28e 100644 --- a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java +++ b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java @@ -87,8 +87,6 @@ public class BookmarkManager return new ArrayList(BookmarkIconManager.getAll().values()); } - public static native Point getBookmark(double px, double py); - public Bookmark getBookmark(Pair catAndBmk) { return getBookmark(catAndBmk.first, catAndBmk.second); diff --git a/base/stl_add.hpp b/base/stl_add.hpp index 95e4430483..c749e2fc65 100644 --- a/base/stl_add.hpp +++ b/base/stl_add.hpp @@ -139,6 +139,12 @@ GetRangeDeletor(TContainer & cont, TDeletor const & deletor) return impl::DeleteRangeFunctor(cont, deletor); } +template +void DeleteRange(TContainer & cont, TDeletor const & deletor) +{ + (void)GetRangeDeletor(cont, deletor)(); +} + struct NoopFunctor { template void operator () (T const &) const diff --git a/graphics/depth_constants.hpp b/graphics/depth_constants.hpp index 5183bd1ddd..609fd957c6 100644 --- a/graphics/depth_constants.hpp +++ b/graphics/depth_constants.hpp @@ -18,7 +18,8 @@ namespace graphics static const int balloonBaseDepth = countryStatusDepth - (balloonContentInc + 10); static const int locationDepth = balloonBaseDepth - 10; - static const int activePinDepth = locationDepth - 10; - static const int poiAndBookmarkDepth = activePinDepth - 10; - static const int tracksDepth = poiAndBookmarkDepth - 10; + static const int poiDepth = locationDepth - 10; + static const int bookmarkDepth = poiDepth; + static const int tracksDepth = bookmarkDepth - 10; + static const int activePinDepth = tracksDepth - 10; } diff --git a/map/bookmark.cpp b/map/bookmark.cpp index 47dee82551..9752fc739a 100644 --- a/map/bookmark.cpp +++ b/map/bookmark.cpp @@ -1,6 +1,8 @@ #include "bookmark.hpp" #include "track.hpp" +#include "../graphics/depth_constants.hpp" + #include "../indexer/mercator.hpp" #include "../coding/file_reader.hpp" @@ -27,34 +29,24 @@ Track const * BookmarkCategory::GetTrack(size_t index) const return (index < m_tracks.size() ? m_tracks[index] : 0); } -void BookmarkCategory::AddBookmark(Bookmark const & bm) +void BookmarkCategory::AddBookmark(m2::PointD const & ptOrg, BookmarkCustomData const & bm) { - Bookmark * p = new Bookmark(bm); - m_bookmarks.push_back(p); + UserMark * mark = base_t::GetController().CreateUserMark(ptOrg); + mark->InjectCustomData(new BookmarkCustomData(bm)); } -void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm) +void BookmarkCategory::ReplaceBookmark(size_t index, BookmarkCustomData const & bm) { - ASSERT_LESS ( index, m_bookmarks.size(), () ); - if (index < m_bookmarks.size()) - { - Bookmark * p = new Bookmark(bm); - AssignPrivateParams(index, *p); - - delete m_bookmarks[index]; - m_bookmarks[index] = p; - } + Controller c = base_t::GetController(); + ASSERT_LESS (index, c.GetUserMarkCount(), ()); + if (index < c.GetUserMarkCount()) + base_t::GetController().EditUserMark(index, new BookmarkCustomData(bm)); } -void BookmarkCategory::AssignPrivateParams(size_t index, Bookmark & bm) const +BookmarkCategory::BookmarkCategory(const string & name, Framework & framework) + : base_t(UserMarkContainer::BOOKMARK_MARK, graphics::bookmarkDepth, framework) + , m_name(name) { - ASSERT_LESS ( index, m_bookmarks.size(), () ); - if (index < m_bookmarks.size()) - { - Bookmark const * p = m_bookmarks[index]; - bm.SetTimeStamp(p->GetTimeStamp()); - bm.SetScale(p->GetScale()); - } } BookmarkCategory::~BookmarkCategory() @@ -65,8 +57,7 @@ BookmarkCategory::~BookmarkCategory() void BookmarkCategory::ClearBookmarks() { - for_each(m_bookmarks.begin(), m_bookmarks.end(), DeleteFunctor()); - m_bookmarks.clear(); + base_t::Clear(); } void BookmarkCategory::ClearTracks() @@ -95,7 +86,9 @@ template void DeleteItem(vector & v, size_t i) void BookmarkCategory::DeleteBookmark(size_t index) { - DeleteItem(m_bookmarks, index); + base_t::Controller c = base_t::GetController(); + ASSERT_LESS(index, c.GetUserMarkCount(), ()); + c.DeleteUserMark(index); } void BookmarkCategory::DeleteTrack(size_t index) @@ -103,14 +96,21 @@ void BookmarkCategory::DeleteTrack(size_t index) DeleteItem(m_tracks, index); } +size_t BookmarkCategory::GetBookmarksCount() const +{ + return base_t::GetController().GetUserMarkCount(); +} + Bookmark const * BookmarkCategory::GetBookmark(size_t index) const { - return (index < m_bookmarks.size() ? m_bookmarks[index] : 0); + base_t::Controller const & c = base_t::GetController(); + return (Bookmark *)(index < c.GetUserMarkCount() ? c.GetUserMark(index) : 0); } Bookmark * BookmarkCategory::GetBookmark(size_t index) { - return (index < m_bookmarks.size() ? m_bookmarks[index] : 0); + base_t::Controller & c = base_t::GetController(); + return (Bookmark *)(index < c.GetUserMarkCount() ? c.GetUserMark(index) : 0); } namespace @@ -344,13 +344,7 @@ namespace if (MakeValid()) { if (POINT == m_geometryType) - { - Bookmark bm(m_org, m_name, m_type); - bm.SetTimeStamp(m_timeStamp); - bm.SetDescription(m_description); - bm.SetScale(m_scale); - m_category.AddBookmark(bm); - } + m_category.AddBookmark(m_org, BookmarkCustomData(m_name, m_type, m_description, m_scale, m_timeStamp)); else if (LINE == m_geometryType) { Track track(m_points); @@ -509,9 +503,9 @@ bool BookmarkCategory::LoadFromKML(ReaderPtr const & reader) } } -BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file) +BookmarkCategory * BookmarkCategory::CreateFromKMLFile(string const & file, Framework & framework) { - auto_ptr cat(new BookmarkCategory("")); + auto_ptr cat(new BookmarkCategory("", framework)); try { if (cat->LoadFromKML(new FileReader(file))) @@ -620,9 +614,9 @@ void BookmarkCategory::SaveToKML(ostream & s) s << " " << (IsVisible() ? "1" : "0") <<"\n"; - for (size_t i = 0; i < m_bookmarks.size(); ++i) + for (size_t i = 0; i < GetBookmarksCount(); ++i) { - Bookmark const * bm = m_bookmarks[i]; + Bookmark const * bm = GetBookmark(i); s << " \n"; s << " "; SaveStringWithCDATA(s, bm->GetName()); diff --git a/map/bookmark.hpp b/map/bookmark.hpp index 35030e7189..ada4544caf 100644 --- a/map/bookmark.hpp +++ b/map/bookmark.hpp @@ -1,5 +1,8 @@ #pragma once +#include "user_mark.hpp" +#include "user_mark_container.hpp" + #include "../coding/reader.hpp" #include "../geometry/point2d.hpp" @@ -14,61 +17,106 @@ class Track; - -class Bookmark +class BookmarkCustomData : public UserCustomData { - m2::PointD m_org; - string m_name; - string m_description; - string m_type; ///< Now it stores bookmark color (category style). - double m_scale; ///< Viewport scale. -1.0 - is a default value (no scale set). - time_t m_timeStamp; - public: - Bookmark() : m_scale(-1.0), m_timeStamp(my::INVALID_TIME_STAMP) {} - Bookmark(m2::PointD const & org, string const & name, string const & type) - : m_org(org), m_name(name), m_type(type), m_scale(-1.0), m_timeStamp(my::INVALID_TIME_STAMP) + BookmarkCustomData(string const & name, string const & type, + string const & description = "", double scale = -1.0, + time_t timeStamp = my::INVALID_TIME_STAMP) + : m_name(name) + , m_description(description) + , m_type(type) + , m_scale(scale) + , m_timeStamp(timeStamp) { } - m2::PointD const & GetOrg() const { return m_org; } + virtual Type GetType() const { return BOOKMARK; } + string const & GetName() const { return m_name; } - //void SetName(string const & name) { m_name = name; } - /// @return Now its a bookmark color - name of icon file - string const & GetType() const { return m_type; } - //void SetType(string const & type) { m_type = type; } - m2::RectD GetViewport() const { return m2::RectD(m_org, m_org); } + void SetName(const string & name) { m_name = name; } string const & GetDescription() const { return m_description; } - void SetDescription(string const & description) { m_description = description; } + void SetDescription(const string & description) { m_description = description; } - /// @return my::INVALID_TIME_STAMP if bookmark has no timestamp - time_t GetTimeStamp() const { return m_timeStamp; } - void SetTimeStamp(time_t timeStamp) { m_timeStamp = timeStamp; } + string const & GetTypeName() const { return m_type; } + void SetTypeName(const string & type) { m_type = type; } - double GetScale() const { return m_scale; } + double const & GetScale() const { return m_scale; } void SetScale(double scale) { m_scale = scale; } + + time_t const & GetTimeStamp() const { return m_timeStamp; } + void SetTimeStamp(const time_t & timeStamp) { m_timeStamp = timeStamp; } + +private: + string m_name; + string m_description; + string m_type; ///< Now it stores bookmark color (category style). + double m_scale; ///< Viewport scale. -1.0 - is a default value (no scale set). + time_t m_timeStamp; }; -class BookmarkCategory : private noncopyable +class Bookmark : public UserMark { +public: + Bookmark(UserMarkContainer * container) + : UserMark(m2::PointD(0.0, 0.0), container) + { + Inject(); + } + + m2::PointD const & GetOrg() const { return UserMark::GetOrg(); } + string const & GetName() const { return GetData()->GetName(); } + //void SetName(string const & name) { m_name = name; } + /// @return Now its a bookmark color - name of icon file + string const & GetType() const { return GetData()->GetTypeName(); } + //void SetType(string const & type) { m_type = type; } + m2::RectD GetViewport() const { return m2::RectD(GetOrg(), GetOrg()); } + + string const & GetDescription() const { return GetData()->GetDescription(); } + void SetDescription(string const & description) { GetData()->SetDescription(description); } + + /// @return my::INVALID_TIME_STAMP if bookmark has no timestamp + time_t GetTimeStamp() const { return GetData()->GetTimeStamp(); } + void SetTimeStamp(time_t timeStamp) { GetData()->SetTimeStamp(timeStamp); } + + double GetScale() const { return GetData()->GetScale(); } + void SetScale(double scale) { GetData()->SetScale(scale); } + +private: + void Inject(m2::PointD const & org = m2::PointD(), string const & name = "", + string const & type = "", string const & descr = "", + double scale = -1, time_t timeStamp = my::INVALID_TIME_STAMP) + { + InjectCustomData(new BookmarkCustomData(name, descr, type, scale, timeStamp)); + } + + BookmarkCustomData * GetData() + { + return static_cast(&GetCustomData()); + } + + BookmarkCustomData const * GetData() const + { + return static_cast(&GetCustomData()); + } +}; + +class BookmarkCategory : public UserMarkContainer +{ + typedef UserMarkContainer base_t; /// @name Data //@{ - vector m_bookmarks; + /// TODO move track into UserMarkContainer as a IDrawable custom data vector m_tracks; //@} string m_name; - bool m_visible; /// Stores file name from which category was loaded string m_file; - /// This function is called when bookmark is editing or replacing. - /// We need to assign private params to the newly created bookmark from the old one. - void AssignPrivateParams(size_t index, Bookmark & bm) const; - public: - BookmarkCategory(string const & name) : m_name(name), m_visible(true) {} + BookmarkCategory(string const & name, Framework & framework); ~BookmarkCategory(); void ClearBookmarks(); @@ -78,8 +126,8 @@ public: /// @name Theese functions are called from Framework only. //@{ - void AddBookmark(Bookmark const & bm); - void ReplaceBookmark(size_t index, Bookmark const & bm); + void AddBookmark(m2::PointD const & ptOrg, BookmarkCustomData const & bm); + void ReplaceBookmark(size_t index, BookmarkCustomData const & bm); //@} /// @name Tracks routine. @@ -91,18 +139,14 @@ public: void DeleteTrack(size_t index); //@} - void SetVisible(bool isVisible) { m_visible = isVisible; } - bool IsVisible() const { return m_visible; } - void SetName(string const & name) { m_name = name; } string const & GetName() const { return m_name; } string const & GetFileName() const { return m_file; } - inline size_t GetBookmarksCount() const { return m_bookmarks.size(); } + size_t GetBookmarksCount() const; Bookmark const * GetBookmark(size_t index) const; Bookmark * GetBookmark(size_t index); - void DeleteBookmark(size_t index); /// @name Theese fuctions are public for unit tests only. @@ -116,7 +160,7 @@ public: bool SaveToKMLFile(); /// @return 0 in the case of error - static BookmarkCategory * CreateFromKMLFile(string const & file); + static BookmarkCategory * CreateFromKMLFile(string const & file, Framework & framework); /// Get valid file name from input (remove illegal symbols). static string RemoveInvalidSymbols(string const & name); diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 551f84172a..e679715f51 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -1,5 +1,8 @@ #include "bookmark_manager.hpp" #include "framework.hpp" +#include "user_mark.hpp" + +#include "../graphics/depth_constants.hpp" #include "../platform/platform.hpp" #include "../platform/settings.hpp" @@ -16,16 +19,24 @@ BookmarkManager::BookmarkManager(Framework & f) - : m_framework(f), m_bmScreen(0), m_lastScale(1.0) + : m_framework(f) + , m_activeMark(NULL) + , m_bmScreen(0) + , m_lastScale(1.0) { - m_additionalPoiLayer = new BookmarkCategory(""); + m_userMarkLayers.reserve(2); + m_userMarkLayers.push_back(new UserMarkContainer(UserMarkContainer::SEARCH_MARK, graphics::activePinDepth, m_framework)); + m_userMarkLayers.push_back(new UserMarkContainer(UserMarkContainer::API_MARK, graphics::activePinDepth, m_framework)); + UserMarkContainer::InitPoiSelectionMark(FindUserMarksContainer(UserMarkContainer::SEARCH_MARK)); } BookmarkManager::~BookmarkManager() { - delete m_additionalPoiLayer; + for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), DeleteFunctor()); + m_userMarkLayers.clear(); + ClearItems(); - DeleteScreen(); + ResetScreen(); } namespace @@ -116,6 +127,7 @@ public: void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptr const & e) const { + /// TODO cutomize draw in UserMarkContainer for user Draw method Navigator const & navigator = m_framework.GetNavigator(); InformationDisplay & informationDisplay = m_framework.GetInformationDisplay(); ScreenBase const & screen = navigator.Screen(); @@ -141,7 +153,7 @@ void BookmarkManager::DrawCategory(BookmarkCategory const * cat, shared_ptrGetOrg(); if (glbRect.IsPointInside(org)) - informationDisplay.drawPlacemark(pDrawer, bm->GetType().c_str(), navigator.GtoP(org)); + informationDisplay.drawPlacemark(pDrawer, bm->GetType().c_str(), navigator.GtoP(org) + m2::PointD(0.0, 4.0)); } } @@ -167,18 +179,18 @@ void BookmarkManager::LoadBookmarks() void BookmarkManager::LoadBookmark(string const & filePath) { - BookmarkCategory * cat = BookmarkCategory::CreateFromKMLFile(filePath); + BookmarkCategory * cat = BookmarkCategory::CreateFromKMLFile(filePath, m_framework); if (cat) m_categories.push_back(cat); } -size_t BookmarkManager::AddBookmark(size_t categoryIndex, Bookmark & bm) +size_t BookmarkManager::AddBookmark(size_t categoryIndex, const m2::PointD & ptOrg, BookmarkCustomData & bm) { bm.SetTimeStamp(time(0)); bm.SetScale(m_framework.GetDrawScale()); BookmarkCategory * pCat = m_categories[categoryIndex]; - pCat->AddBookmark(bm); + pCat->AddBookmark(ptOrg, bm); pCat->SetVisible(true); pCat->SaveToKMLFile(); @@ -189,7 +201,7 @@ size_t BookmarkManager::AddBookmark(size_t categoryIndex, Bookmark & bm) return (pCat->GetBookmarksCount() - 1); } -void BookmarkManager::ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm) +void BookmarkManager::ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm) { BookmarkCategory * pCat = m_categories[catIndex]; pCat->ReplaceBookmark(bmIndex, bm); @@ -208,7 +220,7 @@ size_t BookmarkManager::LastEditedBMCategory() } if (m_categories.empty()) - m_categories.push_back(new BookmarkCategory(m_framework.GetStringsBundle().GetString("my_places"))); + m_categories.push_back(new BookmarkCategory(m_framework.GetStringsBundle().GetString("my_places"), m_framework)); return 0; } @@ -225,7 +237,7 @@ BookmarkCategory * BookmarkManager::GetBmCategory(size_t index) const size_t BookmarkManager::CreateBmCategory(string const & name) { - m_categories.push_back(new BookmarkCategory(name)); + m_categories.push_back(new BookmarkCategory(name, m_framework)); return (m_categories.size()-1); } @@ -259,15 +271,15 @@ void BookmarkManager::DrawItems(shared_ptr const & e) const graphics::Screen * pScreen = e->drawer()->screen(); pScreen->beginFrame(); + PaintOverlayEvent event(e->drawer(), screen); + for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), bind(&UserMarkContainer::Draw, _1, event)); + for (size_t i = 0; i < m_categories.size(); ++i) { if (m_categories[i]->IsVisible()) DrawCategory(m_categories[i], e); } - if (m_additionalPoiLayer->IsVisible()) - DrawCategory(m_additionalPoiLayer, e); - pScreen->endFrame(); } @@ -293,48 +305,103 @@ bool BookmarkManager::DeleteBmCategory(size_t index) return false; } -void BookmarkManager::AdditionalPoiLayerSetInvisible() +void BookmarkManager::ActivateMark(UserMark const * mark) { - m_additionalPoiLayer->SetVisible(false); + if (m_activeMark != NULL) + { + m_activeMark->Diactivate(); + m_activeMark = NULL; + } + + if (mark == NULL) + return; + + m_activeMark = mark; + /// TODO remove this hack when resctuct Bookmark drawing code. + /// now it's need to activate bookmark element + UserCustomData const & data = m_activeMark->GetCustomData(); + if (data.GetType() == UserCustomData::BOOKMARK) + { + m_activeMark = UserMarkContainer::UserMarkForPoi(mark->GetOrg()); + BookmarkCustomData const & bookmarkData = static_cast(data); + search::AddressInfo addrInfo; + m_framework.GetAddressInfoForGlobalPoint(mark->GetOrg(), addrInfo); + UserMark * hackMark = const_cast(m_activeMark); + hackMark->InjectCustomData(new PoiCustomData(bookmarkData.GetName(), + bookmarkData.GetTypeName(), + addrInfo.FormatNameAndAddress())); + } + + m_activeMark->Activate(); } -void BookmarkManager::AdditionalPoiLayerSetVisible() +UserMark const * BookmarkManager::FindNearestUserMark(const m2::AnyRectD & rect) { - m_additionalPoiLayer->SetVisible(true); + double d = numeric_limits::max(); + UserMark const * mark = FindUserMarksContainer(UserMarkContainer::API_MARK)->FindMarkInRect(rect, d); + if (mark != NULL) + return mark; + + mark = FindUserMarksContainer(UserMarkContainer::SEARCH_MARK)->FindMarkInRect(rect, d); + for (size_t i = 0; i < GetBmCategoriesCount(); ++i) + { + BookmarkCategory * category = GetBmCategory(i); + if (!category->IsVisible()) + continue; + + for (size_t j = 0; j < category->GetBookmarksCount(); ++ j) + { + Bookmark const * bookmark = category->GetBookmark(j); + m2::PointD bmOrg = bookmark->GetOrg(); + if (rect.IsPointInside(bmOrg)) + { + double currentD = rect.GetGlobalRect().Center().SquareLength(bmOrg); + if (currentD < d) + { + mark = bookmark; + d = currentD; + } + } + } + } + + return mark; } -void BookmarkManager::AdditionalPoiLayerAddPoi(Bookmark const & bm) +void BookmarkManager::UserMarksSetVisible(UserMarkContainer::Type type, bool isVisible) { - m_additionalPoiLayer->AddBookmark(bm); + FindUserMarksContainer(type)->SetVisible(isVisible); } -Bookmark const * BookmarkManager::AdditionalPoiLayerGetBookmark(size_t index) const +bool BookmarkManager::UserMarksIsVisible(UserMarkContainer::Type type) const { - return m_additionalPoiLayer->GetBookmark(index); + return FindUserMarksContainer(type)->IsVisible(); } -Bookmark * BookmarkManager::AdditionalPoiLayerGetBookmark(size_t index) +UserMark * BookmarkManager::UserMarksAddMark(UserMarkContainer::Type type, const m2::PointD & ptOrg) { - return m_additionalPoiLayer->GetBookmark(index); + return FindUserMarksContainer(type)->GetController().CreateUserMark(ptOrg); } -void BookmarkManager::AdditionalPoiLayerClear() +void BookmarkManager::UserMarksClear(UserMarkContainer::Type type) { - m_additionalPoiLayer->ClearBookmarks(); + FindUserMarksContainer(type)->Clear(); } -bool BookmarkManager::IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const +UserMarkContainer::Controller & BookmarkManager::UserMarksGetController(UserMarkContainer::Type type) { - return (bm.first == additionalLayerCategory && bm.second >= 0); + return FindUserMarksContainer(type)->GetController(); } void BookmarkManager::SetScreen(graphics::Screen * screen) { - DeleteScreen(); + ResetScreen(); m_bmScreen = screen; + for_each(m_userMarkLayers.begin(), m_userMarkLayers.end(), + bind(&UserMarkContainer::SetScreen, _1, m_bmScreen)); } -void BookmarkManager::DeleteScreen() +void BookmarkManager::ResetScreen() { if (m_bmScreen) { @@ -343,7 +410,23 @@ void BookmarkManager::DeleteScreen() for (size_t j = 0; j < m_categories[i]->GetTracksCount(); ++j) m_categories[i]->GetTrack(j)->DeleteDisplayList(); - delete m_bmScreen; + for (size_t i = 0; i < m_userMarkLayers.size(); ++i) + m_userMarkLayers[i]->SetScreen(0); + m_bmScreen = 0; } } + +UserMarkContainer const * BookmarkManager::FindUserMarksContainer(UserMarkContainer::Type type) const +{ + ASSERT(type >= 0 && type < m_userMarkLayers.size(), ()); + ASSERT(m_userMarkLayers[(size_t)type]->GetType() == type, ()); + return m_userMarkLayers[(size_t)type]; +} + +UserMarkContainer * BookmarkManager::FindUserMarksContainer(UserMarkContainer::Type type) +{ + ASSERT(type >= 0 && type < m_userMarkLayers.size(), ()); + ASSERT(m_userMarkLayers[(size_t)type]->GetType() == type, ()); + return m_userMarkLayers[(size_t)type]; +} diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 4248f81587..dd1011c624 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -1,9 +1,6 @@ #pragma once #include "bookmark.hpp" - - -/// Special number for additional layer category. -const int additionalLayerCategory = -2; +#include "user_mark_container.hpp" class Framework; class PaintEvent; @@ -18,7 +15,8 @@ class BookmarkManager : private noncopyable Framework & m_framework; - BookmarkCategory * m_additionalPoiLayer; + vector m_userMarkLayers; + UserMark const * m_activeMark; graphics::Screen * m_bmScreen; mutable double m_lastScale; @@ -41,8 +39,8 @@ public: void LoadBookmark(string const & filePath); /// Client should know where it adds bookmark - size_t AddBookmark(size_t categoryIndex, Bookmark & bm); - void ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm); + size_t AddBookmark(size_t categoryIndex, m2::PointD const & ptOrg, BookmarkCustomData & bm); + void ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm); size_t LastEditedBMCategory(); string LastEditedBMType() const; @@ -60,17 +58,20 @@ public: void DeleteBmCategory(CategoryIter i); bool DeleteBmCategory(size_t index); + void ActivateMark(UserMark const * mark); + UserMark const * FindNearestUserMark(m2::AnyRectD const & rect); + /// Additional layer methods - void AdditionalPoiLayerSetInvisible(); - void AdditionalPoiLayerSetVisible(); - void AdditionalPoiLayerAddPoi(Bookmark const & bm); - Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const; - Bookmark * AdditionalPoiLayerGetBookmark(size_t index); - void AdditionalPoiLayerClear(); - bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const; - bool AdditionalLayerIsVisible() const { return m_additionalPoiLayer->IsVisible(); } - size_t AdditionalLayerNumberOfPoi() const { return m_additionalPoiLayer->GetBookmarksCount(); } + void UserMarksSetVisible(UserMarkContainer::Type type, bool isVisible); + bool UserMarksIsVisible(UserMarkContainer::Type type) const; + UserMark * UserMarksAddMark(UserMarkContainer::Type type, m2::PointD const & ptOrg); + void UserMarksClear(UserMarkContainer::Type type); + UserMarkContainer::Controller & UserMarksGetController(UserMarkContainer::Type type); void SetScreen(graphics::Screen * screen); - void DeleteScreen(); + void ResetScreen(); + +private: + UserMarkContainer const * FindUserMarksContainer(UserMarkContainer::Type type) const; + UserMarkContainer * FindUserMarksContainer(UserMarkContainer::Type type); }; diff --git a/map/events.hpp b/map/events.hpp index fc07c1f915..5a6fdecbcf 100644 --- a/map/events.hpp +++ b/map/events.hpp @@ -1,6 +1,7 @@ #pragma once #include "../base/commands_queue.hpp" +#include "../geometry/screenbase.hpp" #include "../geometry/point2d.hpp" @@ -61,3 +62,17 @@ public: bool isEmptyDrawing() const; void setIsEmptyDrawing(bool flag); }; + +class PaintOverlayEvent +{ +public: + PaintOverlayEvent(Drawer * drawer, ScreenBase const & modelView) + : m_drawer(drawer), m_modelView(modelView) {} + + ScreenBase const & GetModelView() const { return m_modelView; } + Drawer * GetDrawer() const { return m_drawer; } + +private: + Drawer * m_drawer; + ScreenBase m_modelView; +}; diff --git a/map/framework.cpp b/map/framework.cpp index bbd587d8e0..70f7741038 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -193,6 +193,8 @@ Framework::Framework() if (isBenchmarkingEnabled) m_benchmarkEngine = new BenchmarkEngine(this); + m_ParsedMapApi.SetController(&m_bmManager.UserMarksGetController(UserMarkContainer::API_MARK)); + // Init strings bundle. m_stringsBundle.SetDefaultString("country_status_added_to_queue", "^is added to the downloading queue"); m_stringsBundle.SetDefaultString("country_status_downloading", "Downloading^^%"); @@ -334,12 +336,12 @@ void Framework::LoadBookmarks() m_bmManager.LoadBookmarks(); } -size_t Framework::AddBookmark(size_t categoryIndex, Bookmark & bm) +size_t Framework::AddBookmark(size_t categoryIndex, const m2::PointD & ptOrg, BookmarkCustomData & bm) { - return m_bmManager.AddBookmark(categoryIndex, bm); + return m_bmManager.AddBookmark(categoryIndex, ptOrg, bm); } -void Framework::ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm) +void Framework::ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm) { m_bmManager.ReplaceBookmark(catIndex, bmIndex, bm); } @@ -373,71 +375,6 @@ bool Framework::DeleteBmCategory(size_t index) return m_bmManager.DeleteBmCategory(index); } -BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint) const -{ - return GetBookmark(pxPoint, GetVisualScale()); -} - -BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint, double visualScale) const -{ - // Get the global rect of touching area. - m2::AnyRectD rect; - m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * visualScale, rect); - m2::PointD const center = rect.GlobalCenter(); - - int retBookmarkCategory = -1; - int retBookmark = -1; - double minD = numeric_limits::max(); - bool returnBookmarkIsVisible = false; - - if (m_bmManager.AdditionalLayerIsVisible()) - { - for (size_t i = 0; i < m_bmManager.AdditionalLayerNumberOfPoi(); ++i) - { - m2::PointD const pt = m_bmManager.AdditionalPoiLayerGetBookmark(i)->GetOrg(); - if (rect.IsPointInside(pt)) - { - double const d = center.SquareLength(pt); - if (d < minD) - { - retBookmarkCategory = static_cast(additionalLayerCategory); - retBookmark = static_cast(i); - minD = d; - } - } - } - } - - for (size_t i = 0; i < m_bmManager.GetBmCategoriesCount(); ++i) - { - bool const currentCategoryIsVisible = m_bmManager.GetBmCategory(i)->IsVisible(); - if (!currentCategoryIsVisible && returnBookmarkIsVisible) - continue; - - size_t const count = m_bmManager.GetBmCategory(i)->GetBookmarksCount(); - for (size_t j = 0; j < count; ++j) - { - Bookmark const * bm = m_bmManager.GetBmCategory(i)->GetBookmark(j); - m2::PointD const pt = bm->GetOrg(); - - if (rect.IsPointInside(pt)) - { - double const d = center.SquareLength(pt); - if ((currentCategoryIsVisible && !returnBookmarkIsVisible) || - (d < minD)) - { - retBookmarkCategory = static_cast(i); - retBookmark = static_cast(j); - minD = d; - returnBookmarkIsVisible = m_bmManager.GetBmCategory(i)->IsVisible(); - } - } - } - } - - return make_pair(retBookmarkCategory, retBookmark); -} - void Framework::ShowBookmark(BookmarkAndCategory const & bnc) { StopLocationFollow(); @@ -541,51 +478,6 @@ bool Framework::AddBookmarksFile(string const & filePath) return true; } -void Framework::AdditionalPoiLayerSetInvisible() -{ - m_bmManager.AdditionalPoiLayerSetInvisible(); -} - -void Framework::AdditionalPoiLayerSetVisible() -{ - m_bmManager.AdditionalPoiLayerSetVisible(); -} - -void Framework::AdditionalPoiLayerAddPoi(Bookmark const & bm) -{ - m_bmManager.AdditionalPoiLayerAddPoi(bm); -} - -Bookmark const * Framework::AdditionalPoiLayerGetBookmark(size_t index) const -{ - return m_bmManager.AdditionalPoiLayerGetBookmark(index); -} - -Bookmark * Framework::AdditionalPoiLayerGetBookmark(size_t index) -{ - return m_bmManager.AdditionalPoiLayerGetBookmark(index); -} - -void Framework::AdditionalPoiLayerClear() -{ - m_bmManager.AdditionalPoiLayerClear(); -} - -bool Framework::IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const -{ - return m_bmManager.IsAdditionalLayerPoi(bm); -} - -bool Framework::AdditionalLayerIsVisible() -{ - return m_bmManager.AdditionalLayerIsVisible(); -} - -size_t Framework::AdditionalLayerNumberOfPoi() -{ - return m_bmManager.AdditionalLayerNumberOfPoi(); -} - void Framework::GetLocalMaps(vector & outMaps) const { Platform & pl = GetPlatform(); @@ -639,14 +531,6 @@ void Framework::InvalidateRect(m2::RectD const & rect, bool doForceUpdate) m_renderPolicy->SetInvalidRect(m2::AnyRectD(rect)); m_renderPolicy->GetWindowHandle()->invalidate(); } - /* - else - { - m_hasPendingInvalidate = true; - m_doForceUpdate = doForceUpdate; - m_invalidRect = m2::AnyRectD(rect); - } - */ } void Framework::SaveState() @@ -786,16 +670,10 @@ void Framework::DrawAdditionalInfo(shared_ptr const & e) #endif m_informationDisplay.doDraw(pDrawer); - - DrawMapApiPoints(e); pScreen->endFrame(); m_bmManager.DrawItems(e); - - // somewhere here I can add current place mark - m_balloonManager.DrawPin(e); - m_guiController->UpdateElements(); m_guiController->DrawFrame(pScreen); } @@ -1222,12 +1100,14 @@ bool Framework::GetCurrentPosition(double & lat, double & lon) const void Framework::ShowSearchResult(search::Result const & res) { - m_bmManager.AdditionalPoiLayerSetVisible(); - m_bmManager.AdditionalPoiLayerClear(); - - Bookmark bmk(res.GetFeatureCenter(), res.GetString(), "search-result"); - bmk.SetDescription(res.GetFeatureType()); - m_bmManager.AdditionalPoiLayerAddPoi(bmk); + UserMarkContainer::Type type = UserMarkContainer::SEARCH_MARK; + m_bmManager.UserMarksSetVisible(type, true); + m_bmManager.UserMarksClear(type); + UserMark * mark = m_bmManager.UserMarksAddMark(type, res.GetFeatureCenter()); + search::AddressInfo info; + GetAddressInfoForGlobalPoint(mark->GetOrg(), info); + mark->InjectCustomData(new SearchCustomData(res.GetString(), res.GetFeatureType(), + info.FormatNameAndAddress())); int scale; m2::PointD center; @@ -1268,9 +1148,6 @@ void Framework::ShowAllSearchResults() { using namespace search; - m_bmManager.AdditionalPoiLayerSetVisible(); - m_bmManager.AdditionalPoiLayerClear(); - Results searchRes; GetSearchEngine()->GetResults(searchRes); @@ -1281,6 +1158,10 @@ void Framework::ShowAllSearchResults() case 0: return; } + UserMarkContainer::Type type = UserMarkContainer::SEARCH_MARK; + m_bmManager.UserMarksSetVisible(type, true); + m_bmManager.UserMarksClear(type); + m2::RectD rect; for (size_t i = 0; i < count; ++i) { @@ -1288,9 +1169,11 @@ void Framework::ShowAllSearchResults() search::Result const & r = searchRes.GetResult(i); if (r.GetResultType() != Result::RESULT_SUGGESTION) { - Bookmark bmk(r.GetFeatureCenter(), r.GetString(), "search-result"); - bmk.SetDescription(r.GetFeatureType()); - m_bmManager.AdditionalPoiLayerAddPoi(bmk); + UserMark * mark = m_bmManager.UserMarksAddMark(type, r.GetFeatureCenter()); + AddressInfo info; + GetAddressInfoForGlobalPoint(mark->GetOrg(), info); + mark->InjectCustomData(new SearchCustomData(r.GetString(), r.GetFeatureType(), + info.FormatNameAndAddress())); rect.Add(r.GetFeatureCenter()); } @@ -1339,8 +1222,7 @@ bool Framework::GetDistanceAndAzimut(m2::PointD const & point, void Framework::SetRenderPolicy(RenderPolicy * renderPolicy) { - m_balloonManager.Shutdown(); - m_bmManager.DeleteScreen(); + m_bmManager.ResetScreen(); m_guiController->ResetRenderParams(); m_renderPolicy.reset(); m_renderPolicy.reset(renderPolicy); @@ -1387,7 +1269,7 @@ void Framework::InitGuiSubsystem() pr.m_storageType = graphics::EMediumStorage; pr.m_textureType = graphics::ESmallTexture; - m_bmManager.SetScreen(m_renderPolicy->CreateScreenWithParams(pr)); + m_bmManager.SetScreen(m_renderPolicy->GetCacheScreen().get()); //@} // Do full invalidate instead of any "pending" stuff. @@ -1421,34 +1303,12 @@ anim::Controller * Framework::GetAnimController() const return m_animController.get(); } -/* -void Framework::AddBookmarkAndSetViewport(Bookmark & bm, m2::RectD const & viewPort) -{ - bm.SetType(LastEditedBMType()); - m_bmManager.AddBookmark(LastEditedBMCategory(), bm); - - ShowRectExVisibleScale(viewPort); -} -*/ - -namespace -{ - -void CheckPointName(url_scheme::ResultPoint & point, StringsBundle const & bundle) -{ - string & name = point.GetName(); - if (name.empty()) - name = bundle.GetString("dropped_pin"); -} - -} - bool Framework::ShowMapForURL(string const & url) { - url_scheme::ResultPoint point; + m2::PointD clickPoint; m2::RectD rect; - enum ResultT { FAILED, NO_BALLOON, BALLOON, BALLOON_PADDING }; + enum ResultT { FAILED, NEED_CLICK, NO_NEED_CLICK }; ResultT result = FAILED; // always hide current balloon here @@ -1463,11 +1323,10 @@ bool Framework::ShowMapForURL(string const & url) ParseGeoURL(url, info); if (info.IsValid()) { - point.MakeFrom(info.m_lat, info.m_lon); - CheckPointName(point, m_stringsBundle); - - rect = m_scales.GetRectForDrawScale(info.m_zoom, point.GetOrg()); - result = BALLOON; + clickPoint = m2::PointD(MercatorBounds::LonToX(info.m_lon), + MercatorBounds::LatToY(info.m_lat)); + rect = m_scales.GetRectForDrawScale(info.m_zoom, clickPoint); + result = NEED_CLICK; } } else if (StartsWith(url, "ge0")) @@ -1478,29 +1337,23 @@ bool Framework::ShowMapForURL(string const & url) if (parser.Parse(url, pt, zoom)) { - point.MakeFrom(pt); - CheckPointName(point, m_stringsBundle); - - rect = m_scales.GetRectForDrawScale(zoom, point.GetOrg()); - result = BALLOON; + clickPoint = m2::PointD(MercatorBounds::LonToX(pt.m_lon), + MercatorBounds::LatToY(pt.m_lat)); + rect = m_scales.GetRectForDrawScale(zoom, clickPoint); + result = NEED_CLICK; } } else if (StartsWith(url, "mapswithme://") || StartsWith(url, "mwm://")) { if (m_ParsedMapApi.SetUriAndParse(url)) { - rect = GetMapApiViewportRect(); + if (!m_ParsedMapApi.GetViewportRect(m_scales, rect)) + rect = ScalesProcessor::GetWorldRect(); - if (m_ParsedMapApi.GetPoints().size() == 1) - { - point.MakeFrom(m_ParsedMapApi.GetPoints().front()); - result = BALLOON_PADDING; - } + if (m_ParsedMapApi.GetSinglePoint(clickPoint)) + result = NEED_CLICK; else - { - // show world rect without balloon - result = NO_BALLOON; - } + result = NO_NEED_CLICK; } } @@ -1510,8 +1363,8 @@ bool Framework::ShowMapForURL(string const & url) StopLocationFollow(); SetViewPortASync(rect); - if (result != NO_BALLOON) - m_balloonManager.OnClick(GtoP(point.GetOrg()), true); + if (result != NO_NEED_CLICK) + m_balloonManager.OnClick(GtoP(clickPoint), true); return true; } else @@ -1609,29 +1462,6 @@ bool Framework::GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, return false; } -Framework::BookmarkOrPoi Framework::GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot, - search::AddressInfo & info, BookmarkAndCategory & bmCat) -{ - bmCat = GetBookmark(pxPoint); - bool const isCorrectBookmark = IsValid(bmCat) && m_bmManager.GetBmCategory(bmCat.first)->IsVisible(); - if (isCorrectBookmark) - return Framework::BOOKMARK; - else if (m_bmManager.IsAdditionalLayerPoi(bmCat)) - return Framework::ADDTIONAL_LAYER; - - if (GetVisiblePOI(pxPoint, pxPivot, info)) - { - // We need almost the exact position of the bookmark, parameter 0.1 resolves the error in 2 pixels - bmCat = GetBookmark(pxPivot, 0.1); - if (isCorrectBookmark) - return Framework::BOOKMARK; - else - return Framework::POI; - } - - return Framework::NOTHING_FOUND; -} - Animator & Framework::GetAnimator() { return m_animator; @@ -1647,6 +1477,41 @@ shared_ptr const & Framework::GetLocationState() const return m_informationDisplay.locationState(); } +UserMark const * Framework::ActivateUserMark(m2::PointD const & pxPoint, bool isLongPress) +{ + m2::AnyRectD rect; + m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * GetVisualScale(), rect); + UserMark const * mark = m_bmManager.FindNearestUserMark(rect); + + if (mark == NULL) + { + bool needMark = false; + m2::PointD pxPivot; + search::AddressInfo info; + if (GetVisiblePOI(pxPoint, pxPivot, info)) + needMark = true; + else if (isLongPress) + { + GetAddressInfoForPixelPoint(pxPoint, info); + pxPivot = pxPoint; + needMark = true; + } + + if (needMark) + { + UserMark * poiMark = UserMarkContainer::UserMarkForPoi(m_navigator.PtoG(pxPivot)); + poiMark->InjectCustomData(new PoiCustomData(info.GetPinName(), info.GetPinType(), + info.FormatAddress())); + mark = poiMark; + } + } + + if (mark) + m_bmManager.ActivateMark(mark); + + return mark; +} + StringsBundle const & Framework::GetStringsBundle() { return m_stringsBundle; @@ -1672,75 +1537,6 @@ string Framework::CodeGe0url(double lat, double lon, double zoomLevel, string co return res; } -void Framework::DrawMapApiPoints(shared_ptr const & e) -{ - // get viewport limit rect - m2::AnyRectD const & glbRect = m_navigator.Screen().GlobalRect(); - Drawer * pDrawer = e->drawer(); - - vector const & v = GetMapApiPoints(); - - for (size_t i = 0; i < v.size(); ++i) - { - m2::PointD const & org = m2::PointD(MercatorBounds::LonToX(v[i].m_lon), - MercatorBounds::LatToY(v[i].m_lat)); - if (glbRect.IsPointInside(org)) - { - /// @todo Use custom pins from 3-party app - m_informationDisplay.drawPlacemark(pDrawer, "search-result", m_navigator.GtoP(org)); - } - } -} - -/// @todo Create method that will run all layers without copy/past -bool Framework::GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ResultPoint & point) -{ - m2::AnyRectD rect; - m_navigator.GetTouchRect(pxPoint, TOUCH_PIXEL_RADIUS * GetVisualScale(), rect); - m2::PointD const center = rect.GlobalCenter(); - - double minD = numeric_limits::max(); - bool result = false; - - vector const & v = m_ParsedMapApi.GetPoints(); - for (size_t i = 0; i < v.size(); ++i) - { - url_scheme::ResultPoint pt; - pt.MakeFrom(v[i]); - - if (rect.IsPointInside(pt.GetOrg())) - { - double const d = center.SquareLength(pt.GetOrg()); - if (d < minD) - { - point = pt; - minD = d; - result = true; - } - } - } - - return result; -} - -m2::RectD Framework::GetMapApiViewportRect() const -{ - double zoom; - m2::PointD center; - if (m_ParsedMapApi.GetViewport(center, zoom)) - { - return m_scales.GetRectForDrawScale(zoom, center); - } - else - { - m2::RectD rect; - if (m_ParsedMapApi.GetViewportRect(rect)) - return rect; - - return ScalesProcessor::GetWorldRect(); - } -} - string Framework::GenerateApiBackUrl(url_scheme::ApiPoint const & point) { string res = m_ParsedMapApi.GetGlobalBackUrl(); diff --git a/map/framework.hpp b/map/framework.hpp index d70ea4c50a..e90d6e0c33 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -179,8 +179,8 @@ public: void LoadBookmarks(); /// @return Created bookmark index in category. - size_t AddBookmark(size_t categoryIndex, Bookmark & bm); - void ReplaceBookmark(size_t catIndex, size_t bmIndex, Bookmark const & bm); + size_t AddBookmark(size_t categoryIndex, m2::PointD const & ptOrg, BookmarkCustomData & bm); + void ReplaceBookmark(size_t catIndex, size_t bmIndex, BookmarkCustomData const & bm); /// @return Created bookmark category index. size_t AddCategory(string const & categoryName); @@ -195,14 +195,6 @@ public: /// @return true if category was deleted bool DeleteBmCategory(size_t index); - /// @name Get bookmark by touch. - /// @param[in] pixPt Coordinates of touch point in pixels. - /// @return NULL If there is no bookmark found - //@{ - BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint) const; - BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint, double visualScale) const; - //@} - void ShowBookmark(BookmarkAndCategory const & bnc); void ShowTrack(Track const & track); @@ -210,19 +202,6 @@ public: bool AddBookmarksFile(string const & filePath); - /// @name Additional Layer methods. - //@{ - void AdditionalPoiLayerSetInvisible(); - void AdditionalPoiLayerSetVisible(); - void AdditionalPoiLayerAddPoi(Bookmark const & bm); - Bookmark const * AdditionalPoiLayerGetBookmark(size_t index) const; - Bookmark * AdditionalPoiLayerGetBookmark(size_t index); - void AdditionalPoiLayerClear(); - bool IsAdditionalLayerPoi(const BookmarkAndCategory & bm) const; - bool AdditionalLayerIsVisible(); - size_t AdditionalLayerNumberOfPoi(); - //@} - inline m2::PointD PtoG(m2::PointD const & p) const { return m_navigator.PtoG(p); } inline m2::PointD GtoP(m2::PointD const & p) const { return m_navigator.GtoP(p); } @@ -356,17 +335,6 @@ private: public: bool GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, search::AddressInfo & info) const; - enum BookmarkOrPoi - { - NOTHING_FOUND = 0, - BOOKMARK = 1, - POI = 2, - ADDTIONAL_LAYER = 3 - }; - - BookmarkOrPoi GetBookmarkOrPoi(m2::PointD const & pxPoint, m2::PointD & pxPivot, - search::AddressInfo & info, BookmarkAndCategory & bmCat); - virtual void BeginPaint(shared_ptr const & e); /// Function for calling from platform dependent-paint function. virtual void DoPaint(shared_ptr const & e); @@ -457,6 +425,7 @@ public: bool IsCountryLoaded(m2::PointD const & pt) const; shared_ptr const & GetLocationState() const; + const UserMark * ActivateUserMark(m2::PointD const & pxPoint, bool isLongPress); public: string CodeGe0url(Bookmark const * bmk, bool addName); @@ -464,23 +433,14 @@ public: /// @name Api //@{ + string GenerateApiBackUrl(url_scheme::ApiPoint const & point); + url_scheme::ParsedMapApi const & GetApiDataHolder() const { return m_ParsedMapApi; } + private: url_scheme::ParsedMapApi m_ParsedMapApi; - void DrawMapApiPoints(shared_ptr const & e); void SetViewPortASync(m2::RectD const & rect); public: - bool GetMapApiPoint(m2::PointD const & pxPoint, url_scheme::ResultPoint & point); - - vector const & GetMapApiPoints() { return m_ParsedMapApi.GetPoints(); } - void ClearMapApiPoints() { m_ParsedMapApi.Reset(); } - int GetMapApiVersion() const { return m_ParsedMapApi.GetApiVersion(); } - string const & GetMapApiAppTitle() const { return m_ParsedMapApi.GetAppTitle(); } - string const & GetMapApiBackUrl() const { return m_ParsedMapApi.GetGlobalBackUrl(); } - m2::RectD GetMapApiViewportRect() const; - bool IsValidMapApi() const { return m_ParsedMapApi.IsValid(); } - string GenerateApiBackUrl(url_scheme::ApiPoint const & point); - bool GoBackOnBalloonClick() const { return m_ParsedMapApi.GoBackOnBalloonClick(); } //@} /// @name Map updates diff --git a/map/mwm_url.cpp b/map/mwm_url.cpp index c4e88d265d..c36cea1369 100644 --- a/map/mwm_url.cpp +++ b/map/mwm_url.cpp @@ -1,4 +1,5 @@ #include "mwm_url.hpp" +#include "scales_processor.hpp" #include "../indexer/mercator.hpp" #include "../indexer/scales.hpp" @@ -15,12 +16,6 @@ namespace url_scheme { -void ResultPoint::Init() -{ - m_org = m2::PointD(MercatorBounds::LonToX(m_point.m_lon), - MercatorBounds::LatToY(m_point.m_lat)); -} - namespace { @@ -30,14 +25,17 @@ bool IsInvalidApiPoint(ApiPoint const & p) { return p.m_lat == INVALID_LAT_VALUE } // unnames namespace -ParsedMapApi::ParsedMapApi() : m_version(0), m_zoomLevel(0.0), m_goBackOnBalloonClick(false) +ParsedMapApi::ParsedMapApi() + : m_controller(NULL) + , m_version(0) + , m_zoomLevel(0.0) + , m_goBackOnBalloonClick(false) { } -ParsedMapApi::ParsedMapApi(Uri const & uri) : m_version(0), m_zoomLevel(0.0), m_goBackOnBalloonClick(false) +void ParsedMapApi::SetController(UserMarkContainer::Controller * controller) { - if (!Parse(uri)) - Reset(); + m_controller = controller; } bool ParsedMapApi::SetUriAndParse(string const & url) @@ -48,29 +46,42 @@ bool ParsedMapApi::SetUriAndParse(string const & url) bool ParsedMapApi::IsValid() const { - return !m_points.empty(); + ASSERT(m_controller != NULL, ()); + return m_controller->GetUserMarkCount() > 0; } bool ParsedMapApi::Parse(Uri const & uri) { + ASSERT(m_controller != NULL, ()); + string const & scheme = uri.GetScheme(); if ((scheme != "mapswithme" && scheme != "mwm") || uri.GetPath() != "map") return false; - uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2)); - m_points.erase(remove_if(m_points.begin(), m_points.end(), &IsInvalidApiPoint), m_points.end()); + vector points; + uri.ForEachKeyValue(bind(&ParsedMapApi::AddKeyValue, this, _1, _2, ref(points))); + points.erase(remove_if(points.begin(), points.end(), &IsInvalidApiPoint), points.end()); + + for (size_t i = 0; i < points.size(); ++i) + { + ApiPoint const & p = points[i]; + m2::PointD glPoint(MercatorBounds::LonToX(p.m_lon), + MercatorBounds::LatToY(p.m_lat)); + UserMark * mark = m_controller->CreateUserMark(glPoint); + mark->InjectCustomData(new ApiCustomData(p.m_name, p.m_id)); + } return true; } -void ParsedMapApi::AddKeyValue(string key, string const & value) +void ParsedMapApi::AddKeyValue(string key, string const & value, vector & points) { strings::AsciiToLower(key); if (key == "ll") { - m_points.push_back(ApiPoint()); - m_points.back().m_lat = INVALID_LAT_VALUE; + points.push_back(ApiPoint()); + points.back().m_lat = INVALID_LAT_VALUE; size_t const firstComma = value.find(','); if (firstComma == string::npos) @@ -99,9 +110,8 @@ void ParsedMapApi::AddKeyValue(string key, string const & value) return; } - m_points.back().m_lat = lat; - m_points.back().m_lon = lon; - m_showRect = m2::Add(m_showRect, m2::PointD(lon, lat)); + points.back().m_lat = lat; + points.back().m_lon = lon; } else if (key == "z") { @@ -110,15 +120,15 @@ void ParsedMapApi::AddKeyValue(string key, string const & value) } else if (key == "n") { - if (!m_points.empty()) - m_points.back().m_name = value; + if (!points.empty()) + points.back().m_name = value; else LOG(LWARNING, ("Map API: Point name with no point. 'll' should come first!")); } else if (key == "id") { - if (!m_points.empty()) - m_points.back().m_id = value; + if (!points.empty()) + points.back().m_id = value; else LOG(LWARNING, ("Map API: Point url with no point. 'll' should come first!")); } @@ -147,37 +157,47 @@ void ParsedMapApi::AddKeyValue(string key, string const & value) void ParsedMapApi::Reset() { - m_points.clear(); m_globalBackUrl.clear(); m_appTitle.clear(); m_version = 0; - m_showRect = m2::RectD(); m_zoomLevel = 0.0; m_goBackOnBalloonClick = false; } -bool ParsedMapApi::GetViewport(m2::PointD & pt, double & zoom) const +bool ParsedMapApi::GetViewportRect(ScalesProcessor const & scales, m2::RectD & rect) const { - if (m_zoomLevel >= 1.0 && m_points.size() == 1) + ASSERT(m_controller != NULL, ()); + size_t markCount = m_controller->GetUserMarkCount(); + if (markCount == 1 && m_zoomLevel >= 1) { - zoom = min(static_cast(scales::GetUpperComfortScale()), m_zoomLevel); - pt.x = MercatorBounds::LonToX(m_points.front().m_lon); - pt.y = MercatorBounds::LatToY(m_points.front().m_lat); - return true; - } - - return false; -} - -bool ParsedMapApi::GetViewportRect(m2::RectD & rect) const -{ - if (m_showRect.IsValid()) - { - rect = MercatorBounds::FromLatLonRect(m_showRect); + double zoom = min(static_cast(scales::GetUpperComfortScale()), m_zoomLevel); + rect = scales.GetRectForDrawScale(zoom, m_controller->GetUserMark(0)->GetOrg()); return true; } else + { + m2::RectD result; + for (size_t i = 0; i < m_controller->GetUserMarkCount(); ++i) + result.Add(m_controller->GetUserMark(i)->GetOrg()); + + if (result.IsValid()) + { + rect = result; + return true; + } + return false; + } +} + +bool ParsedMapApi::GetSinglePoint(m2::PointD & point) const +{ + ASSERT(m_controller != NULL, ()); + if (m_controller->GetUserMarkCount() != 1) + return false; + + point = m_controller->GetUserMark(0)->GetOrg(); + return true; } } diff --git a/map/mwm_url.hpp b/map/mwm_url.hpp index 2a2d0b511f..9f66146514 100644 --- a/map/mwm_url.hpp +++ b/map/mwm_url.hpp @@ -1,13 +1,16 @@ +#pragma once + +#include "user_mark_container.hpp" + #include "../geometry/rect2d.hpp" #include "../std/string.hpp" +class ScalesProcessor; namespace url_scheme { -class Uri; - struct ApiPoint { double m_lat; @@ -16,67 +19,36 @@ struct ApiPoint string m_id; }; -class ResultPoint -{ - ApiPoint m_point; - m2::PointD m_org; - - void Init(); - -public: - void MakeFrom(double lat, double lon) - { - m_point.m_lat = lat; - m_point.m_lon = lon; - Init(); - } - void MakeFrom(url_scheme::ApiPoint const & pt) - { - m_point = pt; - Init(); - } - - /// Need to fix default name using "dropped_pin" in Framework. - string & GetName() { return m_point.m_name; } - - m2::PointD const & GetOrg() const { return m_org; } - string const & GetName() const { return m_point.m_name; } - ApiPoint const & GetPoint() const { return m_point; } -}; - +class Uri; /// Handles [mapswithme|mwm]://map?params - everything related to displaying info on a map class ParsedMapApi { public: - ParsedMapApi(Uri const & uri); ParsedMapApi(); + void SetController(UserMarkContainer::Controller * controller); + bool SetUriAndParse(string const & url); bool IsValid() const; - vector const & GetPoints() const { return m_points; } string const & GetGlobalBackUrl() const { return m_globalBackUrl; } string const & GetAppTitle() const { return m_appTitle; } int GetApiVersion() const { return m_version; } - m2::RectD GetLatLonRect() const { return m_showRect; } void Reset(); bool GoBackOnBalloonClick() const { return m_goBackOnBalloonClick; } /// @name Used in settings map viewport after invoking API. - //@{ - bool GetViewport(m2::PointD & pt, double & zoom) const; - bool GetViewportRect(m2::RectD & rect) const; - //@} + bool GetViewportRect(ScalesProcessor const & scales, m2::RectD & rect) const; + bool GetSinglePoint(m2::PointD & point) const; private: bool Parse(Uri const & uri); - void AddKeyValue(string key, string const & value); + void AddKeyValue(string key, string const & value, vector & points); - vector m_points; + UserMarkContainer::Controller * m_controller; string m_globalBackUrl; string m_appTitle; int m_version; - m2::RectD m_showRect; /// Zoom level in OSM format (e.g. from 1.0 to 20.0) /// Taken into an account when calculating viewport rect, but only if points count is == 1 double m_zoomLevel; diff --git a/map/user_mark.cpp b/map/user_mark.cpp new file mode 100644 index 0000000000..53922b91e2 --- /dev/null +++ b/map/user_mark.cpp @@ -0,0 +1,69 @@ +#include "user_mark.hpp" +#include "user_mark_container.hpp" + +#include "../indexer/mercator.hpp" + +namespace +{ + static EmptyCustomData s_emptyData; +} + +UserMark::UserMark(const m2::PointD & ptOrg, UserMarkContainer * container) + : m_ptOrg(ptOrg) + , m_container(container) + , m_customData(NULL) +{ +} + +UserMark::~UserMark() +{ + delete m_customData; +} + +UserMarkContainer const * UserMark::GetContainer() const +{ + return m_container; +} + +m2::PointD const & UserMark::GetOrg() const +{ + return m_ptOrg; +} + +void UserMark::GetLatLon(double & lat, double & lon) const +{ + lon = MercatorBounds::XToLon(m_ptOrg.x); + lat = MercatorBounds::YToLat(m_ptOrg.y); +} + +void UserMark::InjectCustomData(UserCustomData * customData) +{ + delete m_customData; + m_customData = customData; +} + +UserCustomData const & UserMark::GetCustomData() const +{ + if (m_customData == NULL) + return s_emptyData; + + return *m_customData; +} + +void UserMark::Activate() const +{ + m_container->ActivateMark(this); +} + +void UserMark::Diactivate() const +{ + m_container->DiactivateMark(); +} + +UserCustomData & UserMark::GetCustomData() +{ + if (m_customData == NULL) + return s_emptyData; + + return *m_customData; +} diff --git a/map/user_mark.hpp b/map/user_mark.hpp new file mode 100644 index 0000000000..3490985729 --- /dev/null +++ b/map/user_mark.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include "../geometry/point2d.hpp" + +#include "../std/string.hpp" +#include "../std/noncopyable.hpp" + +class UserMarkContainer; + +class UserCustomData +{ +public: + enum Type + { + EMPTY, + POI, + SEARCH, + API, + BOOKMARK + }; + + virtual ~UserCustomData() {} + + virtual Type GetType() const = 0; +}; + +class EmptyCustomData : public UserCustomData +{ +public: + virtual Type GetType() const { return EMPTY; } +}; + +class BaseCustomData : public UserCustomData +{ +public: + BaseCustomData(string const & name, string const & typeName, string address) + : m_name(name) + , m_typeName(typeName) + , m_address(address) {} + + string const & GetName() const { return m_name; } + string const & GetTypeName() const { return m_typeName; } + string const & GetAddress() const { return m_address; } + +private: + string m_name; + string m_typeName; + string m_address; +}; + +class PoiCustomData : public BaseCustomData +{ + typedef BaseCustomData base_t; +public: + PoiCustomData(string const & name, string const & typeName, string address) + : base_t(name, typeName, address) {} + + virtual Type GetType() const { return POI; } +}; + +class SearchCustomData : public BaseCustomData +{ + typedef BaseCustomData base_t; +public: + SearchCustomData(string const & name, string const & typeName, string address) + : base_t(name, typeName, address) {} + + virtual Type GetType() const { return SEARCH; } +}; + +class ApiCustomData : public UserCustomData +{ + typedef UserCustomData base_t; +public: + ApiCustomData(string const & name, string const & id) + : m_name(name) + , m_id(id) {} + + virtual Type GetType() const { return API; } + + string const & GetName() const { return m_name; } + string const & GetID() const {return m_id; } + +private: + string m_name; + string m_id; +}; + +class UserMark : private noncopyable +{ +public: + UserMark(m2::PointD const & ptOrg, UserMarkContainer * container); + virtual ~UserMark(); + + UserMarkContainer const * GetContainer() const; + m2::PointD const & GetOrg() const; + void GetLatLon(double & lat, double & lon) const; + + // custom data must be allocated in head + // memory where allocated custom data will be deallocated by UserMark + void InjectCustomData(UserCustomData * customData); + UserCustomData const & GetCustomData() const; + +protected: + friend class BookmarkManager; + void Activate() const; + void Diactivate() const; + UserCustomData & GetCustomData(); + +protected: + m2::PointD m_ptOrg; + mutable UserMarkContainer * m_container; + UserCustomData * m_customData; +}; diff --git a/map/user_mark_container.cpp b/map/user_mark_container.cpp new file mode 100644 index 0000000000..8cdc0daaef --- /dev/null +++ b/map/user_mark_container.cpp @@ -0,0 +1,390 @@ +#include "user_mark_container.hpp" + +#include "drawer.hpp" +#include "framework.hpp" + +#include "../graphics/display_list.hpp" +#include "../graphics/screen.hpp" + +#include "../geometry/transformations.hpp" + +#include "../anim/task.hpp" +#include "../anim/controller.hpp" + +#include "../base/macros.hpp" +#include "../base/stl_add.hpp" + +#include "../std/scoped_ptr.hpp" + +namespace +{ + struct AnimPhase + { + AnimPhase(double endScale, double timeInterval) + : m_endScale(endScale) + , m_timeInterval(timeInterval) + { + } + + double m_endScale; + double m_timeInterval; + }; + + class PinAnimation : public anim::Task + { + public: + PinAnimation(Framework & f) + : m_f(f) + , m_scale(0.0) + { + } + + void AddAnimPhase(AnimPhase const & phase) + { + m_animPhases.push_back(phase); + } + + virtual void OnStart(double ts) + { + m_startTime = ts; + m_startScale = m_scale; + m_phaseIndex = 0; + } + + virtual void OnStep(double ts) + { + ASSERT(m_phaseIndex < m_animPhases.size(), ()); + + AnimPhase const * phase = &m_animPhases[m_phaseIndex]; + double elapsedTime = ts - m_startTime; + if (elapsedTime > phase->m_timeInterval) + { + m_startTime = ts; + m_scale = phase->m_endScale; + m_startScale = m_scale; + m_phaseIndex++; + if (m_phaseIndex >= m_animPhases.size()) + { + End(); + return; + } + } + + elapsedTime = ts - m_startTime; + double t = elapsedTime / phase->m_timeInterval; + m_scale = m_startScale + t * (phase->m_endScale - m_startScale); + + m_f.Invalidate(); + } + + double GetScale() const + { + return m_scale; + } + + private: + Framework & m_f; + vector m_animPhases; + size_t m_phaseIndex; + double m_scale; + double m_startTime; + double m_startScale; + }; +} + +//////////////////////////////////////////////////////////////////////// + +namespace +{ + class FindMarkFunctor + { + public: + FindMarkFunctor(UserMark ** mark, double & minD, m2::AnyRectD const & rect) + : m_mark(mark) + , m_minD(minD) + , m_rect(rect) + { + m_globalCenter = rect.GlobalCenter(); + } + + void operator()(UserMark * mark) + { + m2::PointD const & org = mark->GetOrg(); + if (m_rect.IsPointInside(org)) + { + double minDCandidate = m_globalCenter.SquareLength(org); + if (minDCandidate < m_minD) + { + *m_mark = mark; + m_minD = minDCandidate; + } + } + } + + UserMark ** m_mark; + double & m_minD; + m2::AnyRectD const & m_rect; + m2::PointD m_globalCenter; + }; + + class DrawFunctor + { + public: + DrawFunctor(double scale, + ScreenBase const & modelView, + graphics::DisplayList * dl, + graphics::Screen * screen) + : m_scale(scale) + , m_modelView(modelView) + , m_dl(dl) + , m_screen(screen) + { + } + + void operator()(UserMark const * mark) + { + m2::PointD pxPoint = m_modelView.GtoP(mark->GetOrg()); + math::Matrix m = math::Shift(math::Scale(math::Identity(), + m_scale, m_scale), + pxPoint.x, pxPoint.y); + m_dl->draw(m_screen, m); + } + + private: + double m_scale; + ScreenBase const & m_modelView; + graphics::DisplayList * m_dl; + graphics::Screen * m_screen; + }; +} + +UserMarkContainer::UserMarkContainer(Type type, double layerDepth, Framework & framework) + : m_controller(this) + , m_type(type) + , m_isVisible(true) + , m_layerDepth(layerDepth) + , m_activeMark(NULL) + , m_symbolDL(NULL) + , m_activeSymbolDL(NULL) + , m_cacheScreen(NULL) + , m_framework(framework) +{ + ASSERT(m_type >= 0 && m_type < TERMINANT, ()); +} + +UserMarkContainer::~UserMarkContainer() +{ + Clear(); + ReleaseScreen(); +} + +void UserMarkContainer::SetScreen(graphics::Screen * cacheScreen) +{ + Purge(); + m_cacheScreen = cacheScreen; +} + +UserMark const * UserMarkContainer::FindMarkInRect(m2::AnyRectD const & rect, double & d) +{ + UserMark * mark = NULL; + d = numeric_limits::max(); + FindMarkFunctor f(&mark, d, rect); + for_each(m_userMarks.begin(), m_userMarks.end(), f); + return mark; +} + +void UserMarkContainer::Draw(PaintOverlayEvent const & e) +{ + if (m_isVisible == false) + return; + + ASSERT(m_cacheScreen != NULL, ()); + if (m_cacheScreen == NULL) + return; + + graphics::Screen * screen = e.GetDrawer()->screen(); + ScreenBase modelView = e.GetModelView(); + if (m_activeMark != NULL) + (void)DrawFunctor(GetActiveMarkScale(), modelView, GetActiveDL(), screen)(m_activeMark); + + DrawFunctor f(1.0, modelView, GetDL(), screen); + for_each(m_userMarks.begin(), m_userMarks.end(), f); +} + +void UserMarkContainer::ActivateMark(UserMark const * mark) +{ + ASSERT(mark->GetContainer() == this, ()); + m_activeMark = mark; + StartActivationAnim(); +} + +void UserMarkContainer::DiactivateMark() +{ + KillActivationAnim(); + m_activeMark = NULL; +} + +void UserMarkContainer::Clear() +{ + Purge(); + DeleteRange(m_userMarks, DeleteFunctor()); + m_activeMark = NULL; +} + +static string s_TypeNames[] = +{ + "search-result", + "api-result" +}; + +string const & UserMarkContainer::GetTypeName() const +{ + ASSERT(m_type < ARRAY_SIZE(s_TypeNames), ()); + return s_TypeNames[m_type]; +} + +namespace +{ + class PoiUserMark : public UserMark + { + public: + PoiUserMark(UserMarkContainer * container) + : UserMark(m2::PointD(0.0, 0.0), container) {} + + void SetPtOrg(m2::PointD const & ptOrg) { m_ptOrg = ptOrg; } + }; + + static scoped_ptr s_selectionUserMark; +} + +void UserMarkContainer::InitPoiSelectionMark(UserMarkContainer * container) +{ + ASSERT(s_selectionUserMark == NULL, ()); + s_selectionUserMark.reset(new PoiUserMark(container)); +} + +UserMark * UserMarkContainer::UserMarkForPoi(m2::PointD const & ptOrg) +{ + ASSERT(s_selectionUserMark != NULL, ()); + s_selectionUserMark->SetPtOrg(ptOrg); + return s_selectionUserMark.get(); +} + +UserMark * UserMarkContainer::CreateUserMark(m2::PointD ptOrg) +{ + m_userMarks.push_back(new UserMark(ptOrg, this)); + return m_userMarks.back(); +} + +size_t UserMarkContainer::GetUserMarkCount() const +{ + return m_userMarks.size(); +} + +UserMark const * UserMarkContainer::GetUserMark(size_t index) const +{ + ASSERT_LESS(index, m_userMarks.size(), ()); + return m_userMarks[index]; +} + +UserMark * UserMarkContainer::GetUserMark(size_t index) +{ + ASSERT_LESS(index, m_userMarks.size(), ()); + return m_userMarks[index]; +} + +void UserMarkContainer::EditUserMark(size_t index, UserCustomData * data) +{ + UserMark * mark = GetUserMark(index); + mark->InjectCustomData(data); +} + +namespace +{ + +template void DeleteItem(vector & v, size_t i) +{ + if (i < v.size()) + { + delete v[i]; + v.erase(v.begin() + i); + } + else + { + LOG(LWARNING, ("Trying to delete non-existing item at index", i)); + } +} + +} + +void UserMarkContainer::DeleteUserMark(size_t index) +{ + DeleteItem(m_userMarks, index); +} + +graphics::DisplayList * UserMarkContainer::GetDL() +{ + if (m_symbolDL == NULL) + m_symbolDL = CreateDL(GetTypeName()); + + return m_symbolDL; +} + +graphics::DisplayList * UserMarkContainer::GetActiveDL() +{ + if (m_activeSymbolDL == NULL) + m_activeSymbolDL = CreateDL(GetTypeName() + "-active"); + + return m_activeSymbolDL; +} + +graphics::DisplayList * UserMarkContainer::CreateDL(const string & symbolName) +{ + graphics::DisplayList * dl = m_cacheScreen->createDisplayList(); + m_cacheScreen->beginFrame(); + m_cacheScreen->setDisplayList(dl); + m_cacheScreen->drawSymbol(m2::PointD(0.0, 0.0), symbolName, graphics::EPosCenter, m_layerDepth); + m_cacheScreen->setDisplayList(0); + m_cacheScreen->endFrame(); + + return dl; +} + +void UserMarkContainer::Purge() +{ + delete m_symbolDL; + m_symbolDL = NULL; + delete m_activeSymbolDL; + m_activeSymbolDL = NULL; +} + +void UserMarkContainer::ReleaseScreen() +{ + m_cacheScreen = NULL; +} + +void UserMarkContainer::StartActivationAnim() +{ + PinAnimation * anim = new PinAnimation(m_framework); + anim->AddAnimPhase(AnimPhase(1.2, 0.15)); + anim->AddAnimPhase(AnimPhase(0.8, 0.08)); + anim->AddAnimPhase(AnimPhase(1, 0.05)); + m_animTask.reset(anim); + m_framework.GetAnimController()->AddTask(m_animTask); +} + +void UserMarkContainer::KillActivationAnim() +{ + m_animTask.reset(); +} + +double UserMarkContainer::GetActiveMarkScale() const +{ + if (m_animTask != NULL) + { + PinAnimation * a = static_cast(m_animTask.get()); + return a->GetScale(); + } + + return 1.0; +} diff --git a/map/user_mark_container.hpp b/map/user_mark_container.hpp new file mode 100644 index 0000000000..16f5347225 --- /dev/null +++ b/map/user_mark_container.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include "events.hpp" +#include "user_mark.hpp" + +#include "../geometry/point2d.hpp" +#include "../geometry/rect2d.hpp" + +#include "../std/noncopyable.hpp" + +class Framework; + +namespace anim +{ + class Task; +} + +namespace graphics +{ + class DisplayList; + class Screen; +} + +class UserMarkContainer : private noncopyable +{ +public: + class Controller + { + public: + Controller(UserMarkContainer * container) + : m_container(container) {} + + UserMark * CreateUserMark(m2::PointD ptOrg) { return m_container->CreateUserMark(ptOrg); } + size_t GetUserMarkCount() const { return m_container->GetUserMarkCount(); } + UserMark const * GetUserMark(size_t index) const { return m_container->GetUserMark(index); } + void EditUserMark(size_t index, UserCustomData * data) { m_container->EditUserMark(index, data); } + void DeleteUserMark(size_t index) { m_container->DeleteUserMark(index); } + + private: + UserMarkContainer * m_container; + }; + + enum Type + { + SEARCH_MARK, + API_MARK, + BOOKMARK_MARK, + TERMINANT + }; + + UserMarkContainer(Type type, double layerDepth, Framework & framework); + ~UserMarkContainer(); + + void SetScreen(graphics::Screen * cacheScreen); + + bool IsVisible() const { return m_isVisible; } + void SetVisible(bool isVisible) { m_isVisible = isVisible; } + + // If not found mark on rect result is NULL + // If mark is found in "d" return distance from rect center + // In multiple select choose mark with min(d) + UserMark const * FindMarkInRect(m2::AnyRectD const & rect, double & d); + + void Draw(PaintOverlayEvent const & e); + void ActivateMark(UserMark const * mark); + void DiactivateMark(); + + void Clear(); + + Type const & GetType() const { return m_type; } + string const & GetTypeName() const; + + static void InitPoiSelectionMark(UserMarkContainer * container); + static UserMark * UserMarkForPoi(m2::PointD const & ptOrg); + + Controller const & GetController() const { return m_controller; } + Controller & GetController() { return m_controller; } + +private: + friend class Controller; + UserMark * CreateUserMark(m2::PointD ptOrg); + size_t GetUserMarkCount() const; + UserMark const * GetUserMark(size_t index) const; + UserMark * GetUserMark(size_t index); + void EditUserMark(size_t index, UserCustomData * data); + void DeleteUserMark(size_t index); + +private: + graphics::DisplayList * GetDL(); + graphics::DisplayList * GetActiveDL(); + graphics::DisplayList * CreateDL(string const & symbolName); + void Purge(); + void ReleaseScreen(); + +private: + Controller m_controller; + Type m_type; + bool m_isVisible; + double m_layerDepth; + vector m_userMarks; + UserMark const * m_activeMark; + graphics::DisplayList * m_symbolDL; + graphics::DisplayList * m_activeSymbolDL; + graphics::Screen * m_cacheScreen; + +private: + /// animation support + void StartActivationAnim(); + void KillActivationAnim(); + double GetActiveMarkScale() const; + + Framework & m_framework; + shared_ptr m_animTask; +};