diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 5118c90047..057a3a5ef4 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -221,83 +221,99 @@ void DrapeEngine::InvalidateUserMarks() MessagePriority::Normal); } -void DrapeEngine::UpdateUserMarksGroup(MarkGroupID groupId, UserMarksProvider * provider) +void DrapeEngine::UpdateUserMarks(UserMarksProvider * provider) { - auto const & groupMarkIds = provider->GetPointMarkIds(groupId); - auto groupIdCollection = make_unique_dp(); - groupIdCollection->m_marksID.reserve(groupMarkIds.size()); + auto const & dirtyGroupIds = provider->GetDirtyGroupIds(); + if (dirtyGroupIds.empty()) + return; + auto marksRenderCollection = make_unique_dp(); - marksRenderCollection->reserve(groupMarkIds.size()); - - for (auto markId : groupMarkIds) - { - groupIdCollection->m_marksID.push_back(markId); - UserPointMark const * mark = provider->GetUserPointMark(markId); - if (mark->IsDirty()) - { - auto renderInfo = make_unique_dp(); - renderInfo->m_anchor = mark->GetAnchor(); - renderInfo->m_depth = mark->GetDepth(); - renderInfo->m_depthLayer = mark->GetDepthLayer(); - renderInfo->m_minZoom = mark->GetMinZoom(); - renderInfo->m_minTitleZoom = mark->GetMinTitleZoom(); - renderInfo->m_isVisible = mark->IsVisible(); - renderInfo->m_pivot = mark->GetPivot(); - renderInfo->m_pixelOffset = mark->GetPixelOffset(); - renderInfo->m_titleDecl = mark->GetTitleDecl(); - renderInfo->m_symbolNames = mark->GetSymbolNames(); - renderInfo->m_coloredSymbols = mark->GetColoredSymbols(); - renderInfo->m_symbolSizes = mark->GetSymbolSizes(); - renderInfo->m_symbolOffsets = mark->GetSymbolOffsets(); - renderInfo->m_hasSymbolPriority = mark->HasSymbolPriority(); - renderInfo->m_hasTitlePriority = mark->HasTitlePriority(); - renderInfo->m_priority = mark->GetPriority(); - renderInfo->m_index = mark->GetIndex(); - renderInfo->m_featureId = mark->GetFeatureID(); - renderInfo->m_hasCreationAnimation = mark->HasCreationAnimation(); - - marksRenderCollection->emplace(mark->GetId(), std::move(renderInfo)); - mark->ResetChanges(); - } - } - - auto const & lineIds = provider->GetLineMarkIds(groupId); auto linesRenderCollection = make_unique_dp(); - linesRenderCollection->reserve(lineIds.size()); - for (auto lineId : lineIds) - { - UserLineMark const * mark = provider->GetUserLineMark(lineId); - if (mark->IsDirty()) - { - auto renderInfo = make_unique_dp(); - renderInfo->m_minZoom = mark->GetMinZoom(); - renderInfo->m_depthLayer = mark->GetDepthLayer(); - renderInfo->m_spline = m2::SharedSpline(mark->GetPoints()); - renderInfo->m_layers.reserve(mark->GetLayerCount()); - for (size_t layerIndex = 0, layersCount = mark->GetLayerCount(); layerIndex < layersCount; ++layerIndex) - { - renderInfo->m_layers.emplace_back(mark->GetColor(layerIndex), - mark->GetWidth(layerIndex), - mark->GetDepth(layerIndex)); - } + auto createdIdCollection = make_unique_dp(); + auto removedIdCollection = make_unique_dp(); - linesRenderCollection->emplace(mark->GetId(), std::move(renderInfo)); - mark->ResetChanges(); + df::MarkGroupID lastGroupId = *dirtyGroupIds.begin(); + bool visibilityChanged = provider->IsGroupVisiblityChanged(lastGroupId); + bool groupIsVisible = provider->IsGroupVisible(lastGroupId); + + auto const HandleMark = [&]( + df::MarkID markId, + UserMarksRenderCollection & renderCollection, + IDCollection * idCollection) + { + auto const * mark = provider->GetUserPointMark(markId); + if (!mark->IsDirty()) + return; + auto const groupId = mark->GetGroupId(); + if (groupId != lastGroupId) + { + lastGroupId = groupId; + visibilityChanged = provider->IsGroupVisiblityChanged(groupId); + groupIsVisible = provider->IsGroupVisible(groupId); + } + if (!visibilityChanged && groupIsVisible) + { + if (idCollection) + idCollection->push_back(markId); + renderCollection.emplace(markId, GenerateMarkRenderInfo(mark)); + } + }; + + for (auto markId : provider->GetCreatedMarkIds()) + HandleMark(markId, *marksRenderCollection, &createdIdCollection->m_marksID); + + for (auto markId : provider->GetUpdatedMarkIds()) + HandleMark(markId, *marksRenderCollection, nullptr); + + auto const & removedMarkIds = provider->GetRemovedMarkIds(); + removedIdCollection->m_marksID.reserve(removedMarkIds.size()); + removedIdCollection->m_marksID.assign(removedMarkIds.begin(), removedMarkIds.end()); + + std::map> dirtyMarkIds; + for (auto groupId : dirtyGroupIds) + { + auto & idCollection = *(dirtyMarkIds.emplace(groupId, make_unique_dp()).first->second); + visibilityChanged = provider->IsGroupVisiblityChanged(groupId); + groupIsVisible = provider->IsGroupVisible(groupId); + if (!groupIsVisible && !visibilityChanged) + continue; + + auto const & markIds = provider->GetGroupPointIds(groupId); + auto const & lineIds = provider->GetGroupLineIds(groupId); + if (groupIsVisible) + { + idCollection.m_marksID.reserve(markIds.size()); + idCollection.m_marksID.assign(markIds.begin(), markIds.end()); + idCollection.m_linesID.reserve(lineIds.size()); + idCollection.m_linesID.assign(lineIds.begin(), lineIds.end()); + + for (auto lineId : lineIds) + { + auto const * line = provider->GetUserLineMark(lineId); + if (visibilityChanged || line->IsDirty()) + linesRenderCollection->emplace(lineId, GenerateLineRenderInfo(line)); + } + if (visibilityChanged) + { + for (auto markId : markIds) + marksRenderCollection->emplace( + markId, GenerateMarkRenderInfo(provider->GetUserPointMark(markId))); + } + } + else + { + auto & points = removedIdCollection->m_marksID; + points.reserve(points.size() + markIds.size()); + points.insert(points.end(), markIds.begin(), markIds.end()); + auto & lines = removedIdCollection->m_linesID; + lines.reserve(lines.size() + lineIds.size()); + lines.insert(lines.end(), lineIds.begin(), lineIds.end()); } } - auto const & createdIds = provider->GetCreatedMarkIds(groupId); - auto const & removedIds = provider->GetRemovedMarkIds(groupId); - if (!createdIds.empty() || !removedIds.empty() || - !marksRenderCollection->empty() || !linesRenderCollection->empty()) + if (!marksRenderCollection->empty() || !linesRenderCollection->empty() + || !removedIdCollection->IsEmpty() || !createdIdCollection->IsEmpty()) { - auto createdIdCollection = make_unique_dp(); - createdIdCollection->m_marksID.reserve(createdIds.size()); - createdIdCollection->m_marksID.assign(createdIds.begin(), createdIds.end()); - auto removedIdCollection = make_unique_dp(); - removedIdCollection->m_marksID.reserve(removedIds.size()); - removedIdCollection->m_marksID.assign(removedIds.begin(), removedIds.end()); - m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp( std::move(createdIdCollection), @@ -307,11 +323,14 @@ void DrapeEngine::UpdateUserMarksGroup(MarkGroupID groupId, UserMarksProvider * MessagePriority::Normal); } - m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp( - groupId, - std::move(groupIdCollection)), - MessagePriority::Normal); + for (auto & v : dirtyMarkIds) + { + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp( + v.first, + std::move(v.second)), + MessagePriority::Normal); + } } void DrapeEngine::SetRenderingEnabled(ref_ptr contextFactory) @@ -764,4 +783,46 @@ void DrapeEngine::RunFirstLaunchAnimation() make_unique_dp(), MessagePriority::Normal); } + +drape_ptr DrapeEngine::GenerateMarkRenderInfo(UserPointMark const * mark) +{ + auto renderInfo = make_unique_dp(); + renderInfo->m_anchor = mark->GetAnchor(); + renderInfo->m_depth = mark->GetDepth(); + renderInfo->m_depthLayer = mark->GetDepthLayer(); + renderInfo->m_minZoom = mark->GetMinZoom(); + renderInfo->m_minTitleZoom = mark->GetMinTitleZoom(); + renderInfo->m_isVisible = mark->IsVisible(); + renderInfo->m_pivot = mark->GetPivot(); + renderInfo->m_pixelOffset = mark->GetPixelOffset(); + renderInfo->m_titleDecl = mark->GetTitleDecl(); + renderInfo->m_symbolNames = mark->GetSymbolNames(); + renderInfo->m_coloredSymbols = mark->GetColoredSymbols(); + renderInfo->m_symbolSizes = mark->GetSymbolSizes(); + renderInfo->m_symbolOffsets = mark->GetSymbolOffsets(); + renderInfo->m_hasSymbolPriority = mark->HasSymbolPriority(); + renderInfo->m_hasTitlePriority = mark->HasTitlePriority(); + renderInfo->m_priority = mark->GetPriority(); + renderInfo->m_index = mark->GetIndex(); + renderInfo->m_featureId = mark->GetFeatureID(); + renderInfo->m_hasCreationAnimation = mark->HasCreationAnimation(); + return renderInfo; +} + +drape_ptr DrapeEngine::GenerateLineRenderInfo(UserLineMark const * mark) +{ + auto renderInfo = make_unique_dp(); + renderInfo->m_minZoom = mark->GetMinZoom(); + renderInfo->m_depthLayer = mark->GetDepthLayer(); + renderInfo->m_spline = m2::SharedSpline(mark->GetPoints()); + renderInfo->m_layers.reserve(mark->GetLayerCount()); + for (size_t layerIndex = 0, layersCount = mark->GetLayerCount(); layerIndex < layersCount; ++layerIndex) + { + renderInfo->m_layers.emplace_back(mark->GetColor(layerIndex), + mark->GetWidth(layerIndex), + mark->GetDepth(layerIndex)); + } + return renderInfo; +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index dbd2a8d134..00efa718af 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -133,7 +133,7 @@ public: void ClearUserMarksGroup(size_t layerId); void ChangeVisibilityUserMarksGroup(MarkGroupID groupId, bool isVisible); - void UpdateUserMarksGroup(MarkGroupID groupId, UserMarksProvider * provider); + void UpdateUserMarks(UserMarksProvider * provider); void InvalidateUserMarks(); void SetRenderingEnabled(ref_ptr contextFactory = nullptr); @@ -228,6 +228,9 @@ private: dp::DrapeID GenerateDrapeID(); + static drape_ptr GenerateMarkRenderInfo(UserPointMark const * mark); + static drape_ptr GenerateLineRenderInfo(UserLineMark const * mark); + drape_ptr m_frontend; drape_ptr m_backend; drape_ptr m_threadCommutator; diff --git a/drape_frontend/user_marks_global.hpp b/drape_frontend/user_marks_global.hpp index 16e487242d..b815b159a5 100644 --- a/drape_frontend/user_marks_global.hpp +++ b/drape_frontend/user_marks_global.hpp @@ -8,5 +8,7 @@ namespace df using MarkID = uint32_t; using MarkGroupID = size_t; using IDCollection = std::vector; -using MarkIDSet = std::set; +using MarkIDSet = std::set; +using GroupIDList = std::vector; +using GroupIDSet = std::set; } // namespace df diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp index 758dabd231..41b356cd97 100644 --- a/drape_frontend/user_marks_provider.hpp +++ b/drape_frontend/user_marks_provider.hpp @@ -48,6 +48,7 @@ public: virtual void ResetChanges() const = 0; MarkID GetId() const { return m_id; } + virtual df::MarkGroupID GetGroupId() const = 0; virtual m2::PointD const & GetPivot() const = 0; virtual m2::PointD GetPixelOffset() const = 0; @@ -100,13 +101,17 @@ class UserMarksProvider { public: virtual ~UserMarksProvider() {} - virtual MarkIDSet const & GetPointMarkIds(MarkGroupID groupID) const = 0; - virtual MarkIDSet const & GetLineMarkIds(MarkGroupID groupID) const = 0; - virtual MarkIDSet const & GetCreatedMarkIds(MarkGroupID groupID) const = 0; - virtual MarkIDSet const & GetRemovedMarkIds(MarkGroupID groupID) const = 0; - /// never store UserPointMark reference + virtual GroupIDSet const & GetDirtyGroupIds() const = 0; + virtual bool IsGroupVisible(MarkGroupID groupID) const = 0; + virtual bool IsGroupVisiblityChanged(MarkGroupID groupID) const = 0; + virtual MarkIDSet const & GetGroupPointIds(MarkGroupID groupID) const = 0; + virtual MarkIDSet const & GetGroupLineIds(MarkGroupID groupID) const = 0; + virtual MarkIDSet const & GetCreatedMarkIds() const = 0; + virtual MarkIDSet const & GetRemovedMarkIds() const = 0; + virtual MarkIDSet const & GetUpdatedMarkIds() const = 0; + /// Never store UserPointMark reference. virtual UserPointMark const * GetUserPointMark(MarkID markID) const = 0; - /// never store UserLineMark reference + /// Never store UserLineMark reference. virtual UserLineMark const * GetUserLineMark(MarkID markID) const = 0; }; diff --git a/iphone/Maps/Bookmarks/BookmarksVC.mm b/iphone/Maps/Bookmarks/BookmarksVC.mm index 6bb0569244..f77f281cba 100644 --- a/iphone/Maps/Bookmarks/BookmarksVC.mm +++ b/iphone/Maps/Bookmarks/BookmarksVC.mm @@ -307,7 +307,7 @@ extern NSString * const kBookmarkDeletedNotification = @"BookmarkDeletedNotifica NSValue * value = [NSValue valueWithBytes:&bmId objCType:@encode(df::MarkID*)]; [NSNotificationCenter.defaultCenter postNotificationName:kBookmarkDeletedNotification object:value]; - bmManager.DeleteUserMark(bmId); + bmManager.DeleteBookmark(bmId); [m_bookmarkIds removeObjectAtIndex:indexPath.row]; [NSNotificationCenter.defaultCenter postNotificationName:kBookmarksChangedNotification object:nil diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/APIBar/MWMAPIBar.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/APIBar/MWMAPIBar.mm index aec5d46fc8..291e242b86 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/APIBar/MWMAPIBar.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/APIBar/MWMAPIBar.mm @@ -51,7 +51,7 @@ static NSString * const kKeyPath = @"subviews"; Framework & f = GetFramework(); f.DeactivateMapSelection(true); auto & bmManager = f.GetBookmarkManager(); - bmManager.ClearUserMarks(UserMark::Type::API); + bmManager.ClearGroup(UserMark::Type::API); bmManager.NotifyChanges(UserMark::Type::API); NSURL * url = [NSURL URLWithString:@(f.GetApiDataHolder().GetGlobalBackUrl().c_str())]; [UIApplication.sharedApplication openURL:url]; diff --git a/map/bookmark.cpp b/map/bookmark.cpp index 7eb2665146..4cf08451b9 100644 --- a/map/bookmark.cpp +++ b/map/bookmark.cpp @@ -150,24 +150,15 @@ BookmarkCategory::BookmarkCategory(std::string const & name, BookmarkCategory::~BookmarkCategory() { - ClearTracks(); -} - -void BookmarkCategory::ClearTracks() -{ - SetDirty(); - m_tracks.clear(); } void BookmarkCategory::AttachTrack(df::MarkID trackId) { - SetDirty(); m_tracks.insert(trackId); } void BookmarkCategory::DetachTrack(df::MarkID trackId) { - SetDirty(); m_tracks.erase(trackId); } diff --git a/map/bookmark.hpp b/map/bookmark.hpp index c469167e0c..925e50de47 100644 --- a/map/bookmark.hpp +++ b/map/bookmark.hpp @@ -133,8 +133,6 @@ public: std::string const & GetFileName() const { return m_file; } private: - void ClearTracks(); - const df::MarkGroupID m_groupID; std::string m_name; // Stores file name from which bookmarks were loaded. diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index a1559f7671..7034cd9941 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -154,6 +154,14 @@ BookmarkManager::~BookmarkManager() //////////////////////////// +UserMark const * BookmarkManager::GetMark(df::MarkID markID) const +{ + auto const * userMark = GetUserMark(markID); + if (userMark != nullptr) + return userMark; + return static_cast(GetBookmark(markID)); +} + UserMark const * BookmarkManager::GetUserMark(df::MarkID markID) const { auto it = m_userMarks.find(markID); @@ -165,8 +173,7 @@ UserMark * BookmarkManager::GetUserMarkForEdit(df::MarkID markID) auto it = m_userMarks.find(markID); if (it == m_userMarks.end()) return nullptr; - auto const groupId = static_cast(it->second->GetMarkType()); - m_userMarkLayers[groupId]->EditUserMark(markID); + m_updatedMarks.insert(markID); return it->second.get(); } @@ -175,6 +182,11 @@ void BookmarkManager::DeleteUserMark(df::MarkID markId) auto it = m_userMarks.find(markId); auto const groupId = it->second->GetGroupId(); FindContainer(groupId)->DetachUserMark(markId); + auto const mit = m_createdMarks.find(markId); + if (mit != m_createdMarks.end()) + m_createdMarks.erase(mit); + else + m_removedMarks.insert(markId); m_userMarks.erase(it); } @@ -216,7 +228,9 @@ Bookmark * BookmarkManager::GetBookmarkForEdit(df::MarkID markID) return nullptr; auto const groupId = it->second->GetGroupId(); if (groupId) - GetBmCategory(groupId)->EditUserMark(markID); + { + m_updatedMarks.insert(markID); + } return it->second.get(); } @@ -234,11 +248,18 @@ void BookmarkManager::DetachBookmark(df::MarkID bmId, df::MarkGroupID catID) void BookmarkManager::DeleteBookmark(df::MarkID bmId) { - auto it = m_bookmarks.find(bmId); - auto const groupID = it->second->GetGroupId(); + auto groupIt = m_bookmarks.find(bmId); + auto const groupID = groupIt->second->GetGroupId(); if (groupID) + { + auto const it = m_createdMarks.find(bmId); + if (it != m_createdMarks.end()) + m_createdMarks.erase(it); + else + m_removedMarks.insert(bmId); FindContainer(groupID)->DetachUserMark(bmId); - m_bookmarks.erase(it); + } + m_bookmarks.erase(groupIt); } Track * BookmarkManager::CreateTrack(m2::PolylineD const & polyline, Track::Params const & p) @@ -273,39 +294,71 @@ void BookmarkManager::DeleteTrack(df::MarkID trackID) m_tracks.erase(it); } -void BookmarkManager::NotifyChanges(df::MarkGroupID groupId) +void BookmarkManager::FindDirtyGroups() { - auto * group = FindContainer(groupId); - if (!group->IsDirty()) - return; - - if (IsBookmark(groupId)) + m_dirtyGroups.clear(); + for (auto const & group : m_userMarkLayers) { - OnCreateUserMarks(*group); - OnUpdateUserMarks(*group); - OnDeleteUserMarks(*group); + if (!group->IsDirty()) + continue; + auto const groupId = static_cast(group->GetType()); + m_dirtyGroups.insert(groupId); } + for (auto const & group : m_categories) + { + if (!group.second->IsDirty()) + continue; + m_dirtyGroups.insert(group.first); + } + for (auto const markId : m_updatedMarks) + { + auto const * mark = GetMark(markId); + if (mark->IsDirty()) + m_dirtyGroups.insert(mark->GetGroupId()); + } +} +void BookmarkManager::NotifyChanges(df::MarkGroupID) +{ + FindDirtyGroups(); + + if (m_dirtyGroups.empty()) + return; df::DrapeEngineLockGuard lock(m_drapeEngine); if (!lock) return; + bool isBookmarks = false; auto engine = lock.Get(); - - engine->ChangeVisibilityUserMarksGroup(groupId, group->IsVisible()); - - if (group->GetUserMarks().empty() && group->GetUserLines().empty()) + for (auto groupId : m_dirtyGroups) { - engine->UpdateUserMarksGroup(groupId, this); - engine->ClearUserMarksGroup(groupId); + isBookmarks |= IsBookmark(groupId); + auto * group = FindContainer(groupId); + engine->ChangeVisibilityUserMarksGroup(groupId, group->IsVisible()); } - else if (group->IsVisible()) + + engine->UpdateUserMarks(this); + + for (auto groupId : m_dirtyGroups) { - engine->UpdateUserMarksGroup(groupId, this); + auto * group = FindContainer(groupId); + if (group->GetUserMarks().empty() && group->GetUserLines().empty()) + engine->ClearUserMarksGroup(groupId); + group->ResetChanges(); } engine->InvalidateUserMarks(); - group->ResetChanges(); + + if (isBookmarks) + SendBookmarksChanges(); + + for (auto const markId : m_updatedMarks) + GetMark(markId)->ResetChanges(); + + m_dirtyGroups.clear(); + m_createdMarks.clear(); + m_removedMarks.clear(); + m_updatedMarks.clear(); } df::MarkIDSet const & BookmarkManager::GetUserMarkIds(df::MarkGroupID groupID) const @@ -318,16 +371,23 @@ df::MarkIDSet const & BookmarkManager::GetTrackIds(df::MarkGroupID groupID) cons return FindContainer(groupID)->GetUserLines(); } -void BookmarkManager::ClearUserMarks(df::MarkGroupID groupId) +void BookmarkManager::ClearGroup(df::MarkGroupID groupId) { auto * group = FindContainer(groupId); for (auto markId : group->GetUserMarks()) { + auto const it = m_createdMarks.find(markId); + if (it == m_createdMarks.end()) + m_removedMarks.insert(markId); + else + m_createdMarks.erase(it); if (IsBookmark(groupId)) m_bookmarks.erase(markId); else m_userMarks.erase(markId); } + for (auto trackId : group->GetUserLines()) + m_tracks.erase(trackId); group->Clear(); } @@ -366,14 +426,14 @@ UserMark const * BookmarkManager::FindMarkInRect(df::MarkGroupID groupID, m2::An return mark; } -void BookmarkManager::SetIsVisible(df::MarkGroupID categoryId, bool visible) +void BookmarkManager::SetIsVisible(df::MarkGroupID groupId, bool visible) { - return FindContainer(categoryId)->SetIsVisible(visible); + return FindContainer(groupId)->SetIsVisible(visible); } -bool BookmarkManager::IsVisible(df::MarkGroupID categoryId) const +bool BookmarkManager::IsVisible(df::MarkGroupID groupId) const { - return FindContainer(categoryId)->IsVisible(); + return FindContainer(groupId)->IsVisible(); } //////////////////////////// @@ -404,6 +464,7 @@ Bookmark * BookmarkManager::AddBookmark(std::unique_ptr && bookmark) auto const markId = bm->GetId(); ASSERT(m_bookmarks.count(markId) == 0, ()); m_bookmarks.emplace(markId, std::move(bookmark)); + m_createdMarks.insert(markId); return bm; } @@ -617,7 +678,6 @@ void BookmarkManager::MoveBookmark(df::MarkID bmID, df::MarkGroupID curGroupID, { DetachBookmark(bmID, curGroupID); SaveToKMLFile(curGroupID); - NotifyChanges(curGroupID); AttachBookmark(bmID, newGroupID); } @@ -659,36 +719,25 @@ BookmarkCategory * BookmarkManager::GetBmCategory(df::MarkGroupID categoryId) co return (it != m_categories.end() ? it->second.get() : 0); } -void BookmarkManager::OnCreateUserMarks(UserMarkContainer const & container) +void BookmarkManager::SendBookmarksChanges() { - if (m_callbacks.m_createdBookmarksCallback == nullptr) - return; - - std::vector> marksInfo; - GetBookmarksData(container.GetCreatedMarks(), marksInfo); - - m_callbacks.m_createdBookmarksCallback(marksInfo); -} - -void BookmarkManager::OnUpdateUserMarks(UserMarkContainer const & container) -{ - if (m_callbacks.m_updatedBookmarksCallback == nullptr) - return; - - std::vector> marksInfo; - GetBookmarksData(container.GetUpdatedMarks(), marksInfo); - - m_callbacks.m_updatedBookmarksCallback(marksInfo); -} - -void BookmarkManager::OnDeleteUserMarks(UserMarkContainer const & container) -{ - if (m_callbacks.m_deletedBookmarksCallback == nullptr) - return; - - auto const & removedIds = container.GetRemovedMarks(); - df::IDCollection idCollection(removedIds.begin(), removedIds.end()); - m_callbacks.m_deletedBookmarksCallback(idCollection); + if (m_callbacks.m_createdBookmarksCallback != nullptr) + { + std::vector> marksInfo; + GetBookmarksData(m_createdMarks, marksInfo); + m_callbacks.m_createdBookmarksCallback(marksInfo); + } + if (m_callbacks.m_updatedBookmarksCallback != nullptr) + { + std::vector> marksInfo; + GetBookmarksData(m_updatedMarks, marksInfo); + m_callbacks.m_updatedBookmarksCallback(marksInfo); + } + if (m_callbacks.m_deletedBookmarksCallback != nullptr) + { + df::IDCollection idCollection(m_removedMarks.begin(), m_removedMarks.end()); + m_callbacks.m_deletedBookmarksCallback(idCollection); + } } void BookmarkManager::GetBookmarksData(df::MarkIDSet const & markIds, @@ -699,8 +748,8 @@ void BookmarkManager::GetBookmarksData(df::MarkIDSet const & markIds, for (auto markId : markIds) { auto const * bookmark = GetBookmark(markId); - ASSERT(bookmark != nullptr, ()); - data.push_back(std::make_pair(markId, bookmark->GetData())); + if (bookmark) + data.push_back(std::make_pair(markId, bookmark->GetData())); } } @@ -728,11 +777,7 @@ bool BookmarkManager::DeleteBmCategory(df::MarkGroupID groupID) // TODO(darina): check the necessity of DeleteLater // cat.DeleteLater(); FileWriter::DeleteFileX(group.GetFileName()); - for (auto markId : group.GetUserMarks()) - m_bookmarks.erase(markId); - for (auto trackId : group.GetUserLines()) - m_tracks.erase(trackId); - it->second->Clear(); + ClearGroup(groupID); NotifyChanges(groupID); m_categories.erase(it); m_bmGroupsIdList.erase(std::remove(m_bmGroupsIdList.begin(), m_bmGroupsIdList.end(), groupID), @@ -812,24 +857,44 @@ UserMarkContainer * BookmarkManager::FindContainer(df::MarkGroupID containerId) } } -df::MarkIDSet const & BookmarkManager::GetPointMarkIds(df::MarkGroupID groupId) const +df::GroupIDSet const & BookmarkManager::GetDirtyGroupIds() const +{ + return m_dirtyGroups; +} + +bool BookmarkManager::IsGroupVisible(df::MarkGroupID groupID) const +{ + return IsVisible(groupID); +} + +bool BookmarkManager::IsGroupVisiblityChanged(df::MarkGroupID groupID) const +{ + return FindContainer(groupID)->IsVisibilityChanged(); +} + +df::MarkIDSet const & BookmarkManager::GetGroupPointIds(df::MarkGroupID groupId) const { return GetUserMarkIds(groupId); } -df::MarkIDSet const & BookmarkManager::GetLineMarkIds(df::MarkGroupID groupId) const +df::MarkIDSet const & BookmarkManager::GetGroupLineIds(df::MarkGroupID groupId) const { return GetTrackIds(groupId); } -df::MarkIDSet const & BookmarkManager::GetCreatedMarkIds(df::MarkGroupID groupId) const +df::MarkIDSet const & BookmarkManager::GetCreatedMarkIds() const { - return FindContainer(groupId)->GetCreatedMarks(); + return m_createdMarks; } -df::MarkIDSet const & BookmarkManager::GetRemovedMarkIds(df::MarkGroupID groupId) const +df::MarkIDSet const & BookmarkManager::GetRemovedMarkIds() const { - return FindContainer(groupId)->GetRemovedMarks(); + return m_removedMarks; +} + +df::MarkIDSet const & BookmarkManager::GetUpdatedMarkIds() const +{ + return m_updatedMarks; } df::UserPointMark const * BookmarkManager::GetUserPointMark(df::MarkID markID) const diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 70a8595b0e..879ebde719 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -80,6 +80,7 @@ public: ASSERT(m_userMarks.count(markId) == 0, ()); ASSERT_LESS(groupId, m_userMarkLayers.size(), ()); m_userMarks.emplace(markId, std::move(mark)); + m_createdMarks.insert(markId); m_userMarkLayers[groupId]->AttachUserMark(markId); return m; } @@ -133,7 +134,7 @@ public: void DeleteTrack(df::MarkID trackID); ////////////////// - void ClearUserMarks(df::MarkGroupID groupID); + void ClearGroup(df::MarkGroupID groupID); void NotifyChanges(df::MarkGroupID groupID); @@ -143,10 +144,10 @@ public: std::string const & GetCategoryName(df::MarkGroupID categoryId) const; void SetCategoryName(df::MarkGroupID categoryId, std::string const & name); - UserMark const * FindMarkInRect(df::MarkGroupID categoryId, m2::AnyRectD const & rect, double & d) const; + UserMark const * FindMarkInRect(df::MarkGroupID groupId, m2::AnyRectD const & rect, double & d) const; - void SetIsVisible(df::MarkGroupID categoryId, bool visible); - bool IsVisible(df::MarkGroupID categoryId) const; + void SetIsVisible(df::MarkGroupID groupId, bool visible); + bool IsVisible(df::MarkGroupID groupId) const; /// Uses the same file name from which was loaded, or /// creates unique file name on first save and uses it every time. @@ -200,10 +201,14 @@ public: bool IsAsyncLoadingInProgress() const { return m_asyncLoadingInProgress; } // UserMarksProvider - df::MarkIDSet const & GetPointMarkIds(df::MarkGroupID groupId) const override; - df::MarkIDSet const & GetLineMarkIds(df::MarkGroupID groupId) const override; - df::MarkIDSet const & GetCreatedMarkIds(df::MarkGroupID groupId) const override; - df::MarkIDSet const & GetRemovedMarkIds(df::MarkGroupID groupId) const override; + df::GroupIDSet const & GetDirtyGroupIds() const override; + bool IsGroupVisible(df::MarkGroupID groupID) const override; + bool IsGroupVisiblityChanged(df::MarkGroupID groupID) const override; + df::MarkIDSet const & GetGroupPointIds(df::MarkGroupID groupId) const override; + df::MarkIDSet const & GetGroupLineIds(df::MarkGroupID groupId) const override; + df::MarkIDSet const & GetCreatedMarkIds() const override; + df::MarkIDSet const & GetRemovedMarkIds() const override; + df::MarkIDSet const & GetUpdatedMarkIds() const override; df::UserPointMark const * GetUserPointMark(df::MarkID markID) const override; df::UserLineMark const * GetUserLineMark(df::MarkID markID) const override; @@ -211,6 +216,8 @@ private: using KMLDataCollection = std::vector>; bool IsBookmark(df::MarkGroupID groupId) const { return groupId >= UserMark::BOOKMARK; } + UserMark const * GetMark(df::MarkID markID) const; + void FindDirtyGroups(); UserMarkContainer const * FindContainer(df::MarkGroupID containerId) const; UserMarkContainer * FindContainer(df::MarkGroupID containerId); @@ -228,9 +235,7 @@ private: void NotifyAboutFile(bool success, std::string const & filePath, bool isTemporaryFile); void LoadBookmarkRoutine(std::string const & filePath, bool isTemporaryFile); - void OnCreateUserMarks(UserMarkContainer const & container); - void OnUpdateUserMarks(UserMarkContainer const & container); - void OnDeleteUserMarks(UserMarkContainer const & container); + void SendBookmarksChanges(); void GetBookmarksData(df::MarkIDSet const & markIds, std::vector> & data) const; @@ -245,19 +250,21 @@ private: ScreenBase m_viewport; CategoriesCollection m_categories; - GroupIdList m_bmGroupsIdList; + df::GroupIDList m_bmGroupsIdList; + df::GroupIDSet m_dirtyGroups; std::string m_lastCategoryUrl; std::string m_lastType; UserMarkLayers m_userMarkLayers; - uint64_t m_generation; - MarksCollection m_userMarks; BookmarksCollection m_bookmarks; TracksCollection m_tracks; + df::MarkIDSet m_createdMarks; + df::MarkIDSet m_removedMarks; + df::MarkIDSet m_updatedMarks; - StaticMarkPoint* m_selectionMark; - MyPositionMarkPoint* m_myPositionMark; + StaticMarkPoint * m_selectionMark = nullptr; + MyPositionMarkPoint * m_myPositionMark = nullptr; bool m_asyncLoadingInProgress = false; struct BookmarkLoaderInfo diff --git a/map/framework.cpp b/map/framework.cpp index e880cd867f..3dcef1099e 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1605,7 +1605,7 @@ void Framework::FillSearchResultsMarks(bool clear, search::Results::ConstIter be { auto & bmManager = GetBookmarkManager(); if (clear) - bmManager.ClearUserMarks(UserMark::Type::SEARCH); + bmManager.ClearGroup(UserMark::Type::SEARCH); bmManager.SetIsVisible(UserMark::Type::SEARCH, true); for (auto it = begin; it != end; ++it) @@ -1637,7 +1637,7 @@ void Framework::FillSearchResultsMarks(bool clear, search::Results::ConstIter be void Framework::ClearSearchResultsMarks() { - GetBookmarkManager().ClearUserMarks(UserMark::Type::SEARCH); + GetBookmarkManager().ClearGroup(UserMark::Type::SEARCH); GetBookmarkManager().NotifyChanges(UserMark::Type::SEARCH); } @@ -2030,7 +2030,7 @@ url_scheme::ParsedMapApi::ParsingResult Framework::ParseAndSetApiURL(string cons // Clear every current API-mark. { auto & bmManager = GetBookmarkManager(); - bmManager.ClearUserMarks(UserMark::Type::API); + bmManager.ClearGroup(UserMark::Type::API); bmManager.SetIsVisible(UserMark::Type::API, true); bmManager.NotifyChanges(UserMark::Type::API); } diff --git a/map/local_ads_manager.cpp b/map/local_ads_manager.cpp index c5f3403dfe..54c051e53f 100644 --- a/map/local_ads_manager.cpp +++ b/map/local_ads_manager.cpp @@ -177,7 +177,7 @@ void DeleteAllLocalAdsMarks(BookmarkManager * bmManager) GetPlatform().RunTask(Platform::Thread::Gui, [bmManager]() { - bmManager->ClearUserMarks(UserMark::Type::LOCAL_ADS); + bmManager->ClearGroup(UserMark::Type::LOCAL_ADS); bmManager->NotifyChanges(UserMark::Type::LOCAL_ADS); }); } diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 90774d1a6a..2cbfa2746d 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -410,7 +410,7 @@ void RoutingManager::SetRouterImpl(RouterType type) void RoutingManager::RemoveRoute(bool deactivateFollowing) { - m_bmManager->ClearUserMarks(UserMark::Type::TRANSIT); + m_bmManager->ClearGroup(UserMark::Type::TRANSIT); m_bmManager->NotifyChanges(UserMark::Type::TRANSIT); if (deactivateFollowing) @@ -578,7 +578,7 @@ void RoutingManager::CloseRouting(bool removeRoutePoints) if (removeRoutePoints) { - m_bmManager->ClearUserMarks(UserMark::Type::ROUTING); + m_bmManager->ClearGroup(UserMark::Type::ROUTING); m_bmManager->NotifyChanges(UserMark::Type::ROUTING); CancelRecommendation(Recommendation::RebuildAfterPointsLoading); @@ -784,7 +784,7 @@ void RoutingManager::BuildRoute(uint32_t timeoutSec) { ASSERT_THREAD_CHECKER(m_threadChecker, ("BuildRoute")); - m_bmManager->ClearUserMarks(UserMark::Type::TRANSIT); + m_bmManager->ClearGroup(UserMark::Type::TRANSIT); m_bmManager->NotifyChanges(UserMark::Type::TRANSIT); auto routePoints = GetRoutePoints(); @@ -1129,7 +1129,7 @@ void RoutingManager::CancelRoutePointsTransaction(uint32_t transactionId) // Revert route points. ASSERT(m_bmManager != nullptr, ()); - m_bmManager->ClearUserMarks(UserMark::Type::ROUTING); + m_bmManager->ClearGroup(UserMark::Type::ROUTING); RoutePointsLayout routePoints(*m_bmManager); for (auto & markData : routeMarks) routePoints.AddRoutePoint(move(markData)); @@ -1169,7 +1169,7 @@ bool RoutingManager::LoadRoutePoints() // If we have found my position, we use my position as start point. auto const & myPosMark = m_bmManager->MyPositionMark(); ASSERT(m_bmManager != nullptr, ()); - m_bmManager->ClearUserMarks(UserMark::Type::ROUTING); + m_bmManager->ClearGroup(UserMark::Type::ROUTING); for (auto & p : points) { if (p.m_pointType == RouteMarkType::Start && myPosMark.HasPosition()) diff --git a/map/routing_mark.cpp b/map/routing_mark.cpp index 19d3278935..b861d992c0 100644 --- a/map/routing_mark.cpp +++ b/map/routing_mark.cpp @@ -279,7 +279,7 @@ bool RoutePointsLayout::RemoveRoutePoint(RouteMarkType type, size_t intermediate void RoutePointsLayout::RemoveRoutePoints() { - m_manager.ClearUserMarks(UserMark::Type::ROUTING); + m_manager.ClearGroup(UserMark::Type::ROUTING); } void RoutePointsLayout::RemoveIntermediateRoutePoints() diff --git a/map/user_mark.hpp b/map/user_mark.hpp index 792cbd406b..e49a1e5921 100644 --- a/map/user_mark.hpp +++ b/map/user_mark.hpp @@ -44,6 +44,9 @@ public: UserMark(m2::PointD const & ptOrg, UserMark::Type type); + Type GetMarkType() const { return m_type; } + df::MarkGroupID GetGroupId() const override { return m_type; } + // df::UserPointMark overrides. bool IsDirty() const override { return m_isDirty; } void ResetChanges() const override { m_isDirty = false; } @@ -51,7 +54,7 @@ public: m2::PointD const & GetPivot() const override; m2::PointD GetPixelOffset() const override; dp::Anchor GetAnchor() const override; - virtual float GetDepth() const override { return 0.0f; } + float GetDepth() const override { return 0.0f; } df::RenderState::DepthLayer GetDepthLayer() const override; drape_ptr GetTitleDecl() const override { return nullptr; } drape_ptr GetColoredSymbols() const override { return nullptr; } @@ -67,8 +70,6 @@ public: bool HasCreationAnimation() const override { return false; } ms::LatLon GetLatLon() const; - virtual Type GetMarkType() const { return m_type; } - virtual df::MarkGroupID GetGroupId() const { return m_type; } virtual bool IsAvailableForSearch() const { return true; } diff --git a/map/user_mark_container.cpp b/map/user_mark_container.cpp index c0e9b3e309..6a60bbc6b7 100644 --- a/map/user_mark_container.cpp +++ b/map/user_mark_container.cpp @@ -26,6 +26,11 @@ bool UserMarkContainer::IsVisible() const return m_isVisible; } +bool UserMarkContainer::IsVisibilityChanged() const +{ + return m_isVisible != m_wasVisible; +} + UserMark::Type UserMarkContainer::GetType() const { return m_type; @@ -34,12 +39,6 @@ UserMark::Type UserMarkContainer::GetType() const void UserMarkContainer::Clear() { SetDirty(); - for (auto const & markId : m_userMarks) - { - if (m_createdMarks.find(markId) == m_createdMarks.end()) - m_removedMarks.insert(markId); - } - m_createdMarks.clear(); m_userMarks.clear(); } @@ -52,50 +51,20 @@ void UserMarkContainer::SetIsVisible(bool isVisible) } } -void UserMarkContainer::Update() -{ - SetDirty(); -} - -void UserMarkContainer::SetDirty() -{ - m_isDirty = true; -} - -bool UserMarkContainer::IsDirty() const -{ - return m_isDirty; -} - void UserMarkContainer::ResetChanges() { - m_createdMarks.clear(); - m_removedMarks.clear(); - m_updatedMarks.clear(); m_isDirty = false; + m_wasVisible = m_isVisible; } - void UserMarkContainer::AttachUserMark(df::MarkID markId) { SetDirty(); - m_createdMarks.insert(markId); m_userMarks.insert(markId); } -void UserMarkContainer::EditUserMark(df::MarkID markId) -{ - SetDirty(); - m_updatedMarks.insert(markId); -} - void UserMarkContainer::DetachUserMark(df::MarkID markId) { SetDirty(); - auto const it = m_createdMarks.find(markId); - if (it != m_createdMarks.end()) - m_createdMarks.erase(it); - else - m_removedMarks.insert(markId); m_userMarks.erase(markId); } diff --git a/map/user_mark_container.hpp b/map/user_mark_container.hpp index e7dda7911d..cc1f7af2da 100644 --- a/map/user_mark_container.hpp +++ b/map/user_mark_container.hpp @@ -17,45 +17,36 @@ class UserMarkContainer { public: - using NotifyChangesFn = std::function; - UserMarkContainer(UserMark::Type type); virtual ~UserMarkContainer(); - bool IsDirty() const; - // Discard isDirty and clear the lists of created, removed and updated items. + bool IsDirty() const { return m_isDirty; } virtual void ResetChanges(); bool IsVisible() const; + bool IsVisibilityChanged() const; UserMark::Type GetType() const; df::MarkIDSet const & GetUserMarks() const { return m_userMarks; } virtual df::MarkIDSet const & GetUserLines() const { return m_userLines; } - df::MarkIDSet const & GetCreatedMarks() const { return m_createdMarks; } - df::MarkIDSet const & GetUpdatedMarks() const { return m_updatedMarks; } - df::MarkIDSet const & GetRemovedMarks() const { return m_removedMarks; } void AttachUserMark(df::MarkID markId); - void EditUserMark(df::MarkID markId); void DetachUserMark(df::MarkID markId); void Clear(); void SetIsVisible(bool isVisible); - void Update(); protected: - void SetDirty(); + void SetDirty() { m_isDirty = true; } UserMark::Type m_type; df::MarkIDSet m_userMarks; df::MarkIDSet m_userLines; - df::MarkIDSet m_createdMarks; - df::MarkIDSet m_removedMarks; - df::MarkIDSet m_updatedMarks; - bool m_isVisible = true; bool m_isDirty = false; + bool m_isVisible = true; + bool m_wasVisible = false; DISALLOW_COPY_AND_MOVE(UserMarkContainer); };