diff --git a/android/jni/CMakeLists.txt b/android/jni/CMakeLists.txt index 3051560588..143cd689f8 100644 --- a/android/jni/CMakeLists.txt +++ b/android/jni/CMakeLists.txt @@ -41,7 +41,6 @@ set( com/mapswithme/core/jni_helper.cpp com/mapswithme/core/logging.cpp com/mapswithme/maps/analytics/ExternalLibrariesMediator.cpp - com/mapswithme/maps/bookmarks/data/Bookmark.cpp com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp com/mapswithme/maps/discovery/DiscoveryManager.cpp com/mapswithme/maps/discovery/Locals.cpp @@ -87,6 +86,7 @@ set( com/mapswithme/platform/SecureStorage.cpp com/mapswithme/platform/SocketImpl.cpp com/mapswithme/util/Config.cpp + com/mapswithme/util/GeoUtils.cpp com/mapswithme/util/HttpClient.cpp com/mapswithme/util/HttpUploader.cpp com/mapswithme/util/Language.cpp diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 98f2ac4514..a187bbf495 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -683,14 +683,9 @@ void Framework::SetupMeasurementSystem() m_work.SetupMeasurementSystem(); } -void Framework::SetPlacePageInfo(place_page::Info const & info) -{ - m_info = info; -} - place_page::Info & Framework::GetPlacePageInfo() { - return m_info; + return m_work.GetCurrentPlacePageInfo(); } void Framework::RequestBookingMinPrice(JNIEnv * env, jobject policy, @@ -1023,20 +1018,19 @@ Java_com_mapswithme_maps_Framework_nativeSetMapObjectListener(JNIEnv * env, jcla "(Lcom/mapswithme/maps/bookmarks/data/MapObject;)V"); // void onDismiss(boolean switchFullScreenMode); jmethodID const dismissId = jni::GetMethodID(env, g_mapObjectListener, "onDismiss", "(Z)V"); - auto const fillPlacePage = [activatedId](place_page::Info const & info) + auto const fillPlacePage = [activatedId]() { JNIEnv * env = jni::GetEnv(); - g_framework->SetPlacePageInfo(info); + auto const & info = frm()->GetCurrentPlacePageInfo(); jni::TScopedLocalRef mapObject(env, usermark_helper::CreateMapObject(env, info)); env->CallVoidMethod(g_mapObjectListener, activatedId, mapObject.get()); }; auto const closePlacePage = [dismissId](bool switchFullScreenMode) { JNIEnv * env = jni::GetEnv(); - g_framework->SetPlacePageInfo({}); env->CallVoidMethod(g_mapObjectListener, dismissId, switchFullScreenMode); }; - frm()->SetPlacePageListenners(fillPlacePage, closePlacePage, fillPlacePage); + frm()->SetPlacePageListeners(fillPlacePage, closePlacePage, fillPlacePage); } JNIEXPORT void JNICALL @@ -1045,7 +1039,7 @@ Java_com_mapswithme_maps_Framework_nativeRemoveMapObjectListener(JNIEnv * env, j if (g_mapObjectListener == nullptr) return; - frm()->SetPlacePageListenners({} /* onOpen */, {} /* onClose */, {} /* onUpdate */); + frm()->SetPlacePageListeners({} /* onOpen */, {} /* onClose */, {} /* onUpdate */); LOG(LINFO, ("Remove global map object listener")); env->DeleteGlobalRef(g_mapObjectListener); g_mapObjectListener = nullptr; @@ -1773,20 +1767,14 @@ Java_com_mapswithme_maps_Framework_nativeDeleteBookmarkFromMapObject(JNIEnv * en { place_page::Info & info = g_framework->GetPlacePageInfo(); auto const bookmarkId = info.GetBookmarkId(); - frm()->ResetBookmarkInfo(*frm()->GetBookmarkManager().GetBookmark(bookmarkId), info); frm()->GetBookmarkManager().GetEditSession().DeleteBookmark(bookmarkId); - return usermark_helper::CreateMapObject(env, info); -} -JNIEXPORT void JNICALL -Java_com_mapswithme_maps_Framework_nativeOnBookmarkCategoryChanged(JNIEnv * env, jclass, jlong cat, jlong bmk) -{ - place_page::Info & info = g_framework->GetPlacePageInfo(); - ASSERT_GREATER_OR_EQUAL(bmk, 0, ()); - ASSERT_GREATER_OR_EQUAL(cat, 0, ()); - info.SetBookmarkCategoryId(static_cast(cat)); - info.SetBookmarkId(static_cast(bmk)); - info.SetBookmarkCategoryName(frm()->GetBookmarkManager().GetCategoryName(static_cast(cat))); + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_match = place_page::BuildInfo::Match::FeatureOnly; + buildInfo.m_userMarkId = kml::kInvalidMarkId; + frm()->UpdatePlacePageInfoForCurrentSelection(buildInfo); + + return usermark_helper::CreateMapObject(env, info); } JNIEXPORT void JNICALL @@ -2188,9 +2176,8 @@ Java_com_mapswithme_maps_Framework_nativeGetMapObject(JNIEnv * env, jclass, static_cast(env->CallObjectMethod(notificationCandidate, getDefaultNameId)); notification.SetDefaultName(jni::ToNativeString(env, defaultName)); - place_page::Info info; - if (frm()->MakePlacePageInfo(notification, info)) - return usermark_helper::CreateMapObject(env, info); + if (frm()->MakePlacePageForNotification(notification)) + return usermark_helper::CreateMapObject(env, frm()->GetCurrentPlacePageInfo()); return nullptr; } diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index c40df4fcd0..36c1aec581 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -81,8 +81,6 @@ namespace android bool m_isChoosePositionMode; - place_page::Info m_info; - public: Framework(); @@ -185,7 +183,6 @@ namespace android void ApplyWidgets(); void CleanWidgets(); - void SetPlacePageInfo(place_page::Info const & info); place_page::Info & GetPlacePageInfo(); void RequestBookingMinPrice(JNIEnv * env, jobject policy, booking::BlockParams && params, booking::BlockAvailabilityCallback const & callback); diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp deleted file mode 100644 index dde7ca5ae1..0000000000 --- a/android/jni/com/mapswithme/maps/bookmarks/data/Bookmark.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include "com/mapswithme/maps/Framework.hpp" - -#include "com/mapswithme/core/jni_helper.hpp" - -#include "kml/types.hpp" - -namespace -{ -::Framework * frm() { return g_framework->NativeFramework(); } - -Bookmark const * getBookmark(jlong bokmarkId) -{ - Bookmark const * pBmk = frm()->GetBookmarkManager().GetBookmark(static_cast(bokmarkId)); - ASSERT(pBmk, ("Bookmark not found, id", bokmarkId)); - return pBmk; -} -} - -extern "C" -{ -JNIEXPORT jstring JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetName( - JNIEnv * env, jobject thiz, jlong bmk) -{ - return jni::ToJavaString(env, getBookmark(bmk)->GetPreferredName()); -} - -JNIEXPORT jstring JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetFeatureType( - JNIEnv * env, jobject thiz, jlong bmk) -{ - return jni::ToJavaString(env, - kml::GetLocalizedFeatureType(getBookmark(bmk)->GetData().m_featureTypes)); -} - -JNIEXPORT jstring JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetBookmarkDescription( - JNIEnv * env, jobject thiz, jlong bmk) -{ - return jni::ToJavaString(env, getBookmark(bmk)->GetDescription()); -} - -JNIEXPORT jint JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetColor( - JNIEnv * env, jobject thiz, jlong bmk) -{ - auto const * mark = getBookmark(bmk); - return static_cast(mark != nullptr ? mark->GetColor() - : frm()->LastEditedBMColor()); -} - -JNIEXPORT jint JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetIcon( - JNIEnv * env, jobject thiz, jlong bmk) -{ - auto const * mark = getBookmark(bmk); - return static_cast(mark != nullptr ? mark->GetData().m_icon - : kml::BookmarkIcon::None); -} - -JNIEXPORT void JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeSetBookmarkParams( - JNIEnv * env, jobject thiz, jlong bmk, - jstring name, jint color, jstring descr) -{ - auto const * mark = getBookmark(bmk); - - // initialize new bookmark - kml::BookmarkData bmData(mark->GetData()); - auto const bmName = jni::ToNativeString(env, name); - if (mark->GetPreferredName() != bmName) - kml::SetDefaultStr(bmData.m_customName, bmName); - if (descr) - kml::SetDefaultStr(bmData.m_description, jni::ToNativeString(env, descr)); - bmData.m_color.m_predefinedColor = static_cast(color); - - g_framework->ReplaceBookmark(static_cast(bmk), bmData); -} - -JNIEXPORT void JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeChangeCategory( - JNIEnv * env, jobject thiz, jlong oldCat, jlong newCat, jlong bmk) -{ - g_framework->MoveBookmark(static_cast(bmk), static_cast(oldCat), - static_cast(newCat)); -} - -JNIEXPORT jobject JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetXY( - JNIEnv * env, jobject thiz, jlong bmk) -{ - return jni::GetNewParcelablePointD(env, getBookmark(bmk)->GetPivot()); -} - -JNIEXPORT jdouble JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetScale( - JNIEnv * env, jobject thiz, jlong bmk) -{ - return getBookmark(bmk)->GetScale(); -} - -JNIEXPORT jstring JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeEncode2Ge0Url( - JNIEnv * env, jobject thiz, jlong bmk, jboolean addName) -{ - return jni::ToJavaString(env, frm()->CodeGe0url(getBookmark(bmk), addName)); -} - -JNIEXPORT jobject JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeGetAddress( - JNIEnv * env, jobject thiz, jlong bmkId) -{ - auto const address = frm()->GetAddressAtPoint(getBookmark(bmkId)->GetPivot()).FormatAddress(); - return jni::ToJavaString(env, address); -} - -JNIEXPORT jobject JNICALL -Java_com_mapswithme_maps_bookmarks_data_Bookmark_nativeToLatLon( - JNIEnv * env, jobject thiz, jdouble mercX, jdouble mercY) -{ - auto const mercPoint = m2::PointD(static_cast(mercX), static_cast(mercY)); - auto const latLon = MercatorBounds::ToLatLon(mercPoint); - auto const latlonPoint = m2::PointD(latLon.m_lat, latLon.m_lon); - - return jni::GetNewParcelablePointD(env, latlonPoint); -} -} // extern "C" diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index 8decef4b25..7bacac5bc4 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -507,6 +507,13 @@ void OnCategorySortingResults(JNIEnv * env, long long timestamp, blocksRef.get(), static_cast(timestamp)); jni::HandleJavaException(env); } + +Bookmark const * getBookmark(jlong bokmarkId) +{ + Bookmark const * pBmk = frm()->GetBookmarkManager().GetBookmark(static_cast(bokmarkId)); + ASSERT(pBmk, ("Bookmark not found, id", bokmarkId)); + return pBmk; +} } // namespace extern "C" @@ -628,9 +635,13 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeAddBookmarkToLastE if (info.IsFeature()) SaveFeatureTypes(info.GetTypes(), bmData); - auto const * createdBookmark = bmMng.GetEditSession().CreateBookmark(std::move(bmData), lastEditedCategory); + auto const * createdBookmark = bmMng.GetEditSession().CreateBookmark(std::move(bmData), + lastEditedCategory); - frm()->FillBookmarkInfo(*createdBookmark, info); + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_match = place_page::BuildInfo::Match::Everything; + buildInfo.m_userMarkId = createdBookmark->GetId(); + frm()->UpdatePlacePageInfoForCurrentSelection(buildInfo); return usermark_helper::CreateMapObject(env, info); } @@ -760,17 +771,15 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetTracksCount( static_cast(catId)).size()); } -// TODO(AlexZ): Get rid of UserMarks completely in UI code. -// TODO(yunikkk): Refactor java code to get all necessary info without Bookmark wrapper, and without hierarchy. -// If bookmark information is needed in the BookmarkManager, it does not relate in any way to Place Page info -// and should be passed separately via simple name string and lat lon to calculate a distance. JNIEXPORT jobject JNICALL -Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmark( +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeUpdateBookmarkPlacePage( JNIEnv * env, jobject thiz, jlong bmkId) { - auto const * mark = frm()->GetBookmarkManager().GetBookmark(static_cast(bmkId)); - place_page::Info info; - frm()->FillBookmarkInfo(*mark, info); + auto & info = g_framework->GetPlacePageInfo(); + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_userMarkId = static_cast(bmkId); + frm()->UpdatePlacePageInfoForCurrentSelection(buildInfo); + return usermark_helper::CreateMapObject(env, info); } @@ -779,6 +788,8 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkInfo( JNIEnv * env, jobject thiz, jlong bmkId) { auto const bookmark = frm()->GetBookmarkManager().GetBookmark(static_cast(bmkId)); + if (!bookmark) + return nullptr; return env->NewObject(g_bookmarkInfoClass, g_bookmarkInfoConstructor, static_cast(bookmark->GetGroupId()), static_cast(bmkId)); @@ -1263,4 +1274,100 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetSortedCategory( bm.GetSortedCategory(sortParams); } + +JNIEXPORT jstring JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkName( + JNIEnv * env, jobject thiz, jlong bmk) +{ + return jni::ToJavaString(env, getBookmark(bmk)->GetPreferredName()); +} + +JNIEXPORT jstring JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkFeatureType( + JNIEnv * env, jobject thiz, jlong bmk) +{ + return jni::ToJavaString(env, + kml::GetLocalizedFeatureType(getBookmark(bmk)->GetData().m_featureTypes)); +} + +JNIEXPORT jstring JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkDescription( + JNIEnv * env, jobject thiz, jlong bmk) +{ + return jni::ToJavaString(env, getBookmark(bmk)->GetDescription()); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkColor( + JNIEnv * env, jobject thiz, jlong bmk) +{ + auto const * mark = getBookmark(bmk); + return static_cast(mark != nullptr ? mark->GetColor() + : frm()->LastEditedBMColor()); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkIcon( + JNIEnv * env, jobject thiz, jlong bmk) +{ + auto const * mark = getBookmark(bmk); + return static_cast(mark != nullptr ? mark->GetData().m_icon + : kml::BookmarkIcon::None); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeSetBookmarkParams( + JNIEnv * env, jobject thiz, jlong bmk, + jstring name, jint color, jstring descr) +{ + auto const * mark = getBookmark(bmk); + + // initialize new bookmark + kml::BookmarkData bmData(mark->GetData()); + auto const bmName = jni::ToNativeString(env, name); + if (mark->GetPreferredName() != bmName) + kml::SetDefaultStr(bmData.m_customName, bmName); + if (descr) + kml::SetDefaultStr(bmData.m_description, jni::ToNativeString(env, descr)); + bmData.m_color.m_predefinedColor = static_cast(color); + + g_framework->ReplaceBookmark(static_cast(bmk), bmData); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeChangeBookmarkCategory( + JNIEnv * env, jobject thiz, jlong oldCat, jlong newCat, jlong bmk) +{ + g_framework->MoveBookmark(static_cast(bmk), static_cast(oldCat), + static_cast(newCat)); +} + +JNIEXPORT jobject JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkXY( + JNIEnv * env, jobject thiz, jlong bmk) +{ + return jni::GetNewParcelablePointD(env, getBookmark(bmk)->GetPivot()); +} + +JNIEXPORT jdouble JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkScale( + JNIEnv * env, jobject thiz, jlong bmk) +{ + return getBookmark(bmk)->GetScale(); +} + +JNIEXPORT jstring JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeEncode2Ge0Url( + JNIEnv * env, jobject thiz, jlong bmk, jboolean addName) +{ + return jni::ToJavaString(env, frm()->CodeGe0url(getBookmark(bmk), addName)); +} + +JNIEXPORT jobject JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkAddress( + JNIEnv * env, jobject thiz, jlong bmkId) +{ + auto const address = frm()->GetAddressAtPoint(getBookmark(bmkId)->GetPivot()).FormatAddress(); + return jni::ToJavaString(env, address); +} } // extern "C" diff --git a/android/jni/com/mapswithme/util/GeoUtils.cpp b/android/jni/com/mapswithme/util/GeoUtils.cpp new file mode 100644 index 0000000000..22d2636847 --- /dev/null +++ b/android/jni/com/mapswithme/util/GeoUtils.cpp @@ -0,0 +1,17 @@ +#include "android/jni/com/mapswithme/core/jni_helper.hpp" + +#include "geometry/mercator.hpp" + +extern "C" +{ +JNIEXPORT jobject JNICALL + Java_com_mapswithme_util_GeoUtils_nativeToLatLon( + JNIEnv * env, jobject thiz, jdouble mercX, jdouble mercY) +{ + auto const mercPoint = m2::PointD(static_cast(mercX), static_cast(mercY)); + auto const latLon = MercatorBounds::ToLatLon(mercPoint); + auto const latlonPoint = m2::PointD(latLon.m_lat, latLon.m_lon); + + return jni::GetNewParcelablePointD(env, latlonPoint); +} +} diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java index 01ff35b9ad..bf2fcc9444 100644 --- a/android/src/com/mapswithme/maps/Framework.java +++ b/android/src/com/mapswithme/maps/Framework.java @@ -427,9 +427,6 @@ public class Framework @NonNull public static native MapObject nativeDeleteBookmarkFromMapObject(); - // TODO remove that hack after bookmarks will be refactored completely - public static native void nativeOnBookmarkCategoryChanged(long cat, long bmk); - public static native void nativeZoomToPoint(double lat, double lon, int zoom, boolean animate); /** diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java index 055c66c729..fde971b536 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkListAdapter.java @@ -11,6 +11,7 @@ import android.widget.TextView; import com.mapswithme.maps.R; import com.mapswithme.maps.bookmarks.data.BookmarkCategory; +import com.mapswithme.maps.bookmarks.data.BookmarkInfo; import com.mapswithme.maps.bookmarks.data.BookmarkManager; import com.mapswithme.maps.bookmarks.data.SortedBlock; import com.mapswithme.maps.content.DataSource; @@ -525,7 +526,6 @@ public class BookmarkListAdapter extends RecyclerView.Adapter mRatings; @Nullable @@ -285,6 +285,11 @@ public class MapObject implements Parcelable, PopularityProvider, ShareableInfoP return mTitle; } + public void setTitle(@NonNull String title) + { + mTitle = title; + } + @NonNull @Override public String getName() @@ -326,6 +331,11 @@ public class MapObject implements Parcelable, PopularityProvider, ShareableInfoP return mDescription; } + public void setDescription(@NonNull String description) + { + mDescription = description; + } + @NonNull @Override public Popularity getPopularity() diff --git a/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java b/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java index 41b7780866..c0cbbb46b2 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java +++ b/android/src/com/mapswithme/maps/widget/placepage/EditBookmarkFragment.java @@ -15,14 +15,13 @@ import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; -import com.mapswithme.maps.Framework; import com.mapswithme.maps.R; import com.mapswithme.maps.base.BaseMwmDialogFragment; import com.mapswithme.maps.bookmarks.ChooseBookmarkCategoryFragment; import com.mapswithme.maps.bookmarks.ChooseBookmarkCategoryFragment.Listener; import com.mapswithme.maps.bookmarks.data.AbstractCategoriesSnapshot; -import com.mapswithme.maps.bookmarks.data.Bookmark; import com.mapswithme.maps.bookmarks.data.BookmarkCategory; +import com.mapswithme.maps.bookmarks.data.BookmarkInfo; import com.mapswithme.maps.bookmarks.data.BookmarkManager; import com.mapswithme.maps.bookmarks.data.FilterStrategy; import com.mapswithme.maps.bookmarks.data.Icon; @@ -42,7 +41,7 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View. @Nullable private Icon mIcon; @Nullable - private Bookmark mBookmark; + private BookmarkInfo mBookmark; @Nullable private EditBookmarkListener mListener; @@ -87,8 +86,9 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View. long categoryId = args.getLong(EXTRA_CATEGORY_ID); mBookmarkCategory = BookmarkManager.INSTANCE.getCategoryById(categoryId); long bookmarkId = args.getLong(EXTRA_BOOKMARK_ID); - mBookmark = BookmarkManager.INSTANCE.getBookmark(bookmarkId); - mIcon = mBookmark.getIcon(); + mBookmark = BookmarkManager.INSTANCE.getBookmarkInfo(bookmarkId); + if (mBookmark != null) + mIcon = mBookmark.getIcon(); mEtName = (EditText) view.findViewById(R.id.et__bookmark_name); mEtDescription = (EditText) view.findViewById(R.id.et__description); mTvBookmarkGroup = (TextView) view.findViewById(R.id.tv__bookmark_set); @@ -133,11 +133,9 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View. } boolean movedFromCategory = mBookmark.getCategoryId() != mBookmarkCategory.getId(); if (movedFromCategory) - { - mBookmark.setCategoryId(mBookmarkCategory.getId()); - Framework.nativeOnBookmarkCategoryChanged(mBookmark.getCategoryId(), mBookmark.getBookmarkId()); - } - mBookmark.setParams(mEtName.getText().toString(), mIcon, mEtDescription.getText().toString()); + BookmarkManager.INSTANCE.notifyCategoryChanging(mBookmark, mBookmarkCategory.getId()); + BookmarkManager.INSTANCE.notifyParametersUpdating(mBookmark, mEtName.getText().toString(), + mIcon, mEtDescription.getText().toString()); if (mListener != null) mListener.onBookmarkSaved(mBookmark.getBookmarkId(), movedFromCategory); @@ -224,10 +222,13 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View. return; if (TextUtils.isEmpty(mEtName.getText())) - mEtName.setText(mBookmark.getTitle()); + mEtName.setText(mBookmark.getName()); if (TextUtils.isEmpty(mEtDescription.getText())) - mEtDescription.setText(mBookmark.getBookmarkDescription()); + { + mEtDescription.setText( + BookmarkManager.INSTANCE.getBookmarkDescription(mBookmark.getBookmarkId())); + } refreshCategory(); refreshColorMarker(); } diff --git a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java index 6a275f3354..fdb60faae6 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java +++ b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java @@ -2082,7 +2082,7 @@ public class PlacePageView extends NestedScrollView @Override public void onBookmarkSaved(long bookmarkId, boolean movedFromCategory) { - setMapObject(BookmarkManager.INSTANCE.getBookmark(bookmarkId), null); + setMapObject(BookmarkManager.INSTANCE.updateBookmarkPlacePage(bookmarkId), null); NetworkPolicy policy = NetworkPolicy.newInstance(NetworkPolicy.getCurrentNetworkUsageStatus()); refreshViews(policy); } diff --git a/android/src/com/mapswithme/util/GeoUtils.java b/android/src/com/mapswithme/util/GeoUtils.java new file mode 100644 index 0000000000..55a719ba57 --- /dev/null +++ b/android/src/com/mapswithme/util/GeoUtils.java @@ -0,0 +1,17 @@ +package com.mapswithme.util; + +import android.support.annotation.NonNull; + +import com.mapswithme.maps.bookmarks.data.ParcelablePointD; + +public class GeoUtils +{ + @NonNull + static public ParcelablePointD toLatLon(double merX, double merY) + { + return nativeToLatLon(merX, merY); + } + + @NonNull + private static native ParcelablePointD nativeToLatLon(double merX, double merY); +} diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index f63b216697..1345aff3a8 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -2649,15 +2649,17 @@ void FrontendRenderer::RenderLayer::Sort(ref_ptr overlayTree) } } -m2::AnyRectD TapInfo::GetDefaultSearchRect(ScreenBase const & screen) const +// static +m2::AnyRectD TapInfo::GetDefaultSearchRect(m2::PointD const & mercator, ScreenBase const & screen) { m2::AnyRectD result; double const halfSize = VisualParams::Instance().GetTouchRectRadius(); - screen.GetTouchRect(screen.GtoP(m_mercator), halfSize, result); + screen.GetTouchRect(screen.GtoP(mercator), halfSize, result); return result; } -m2::AnyRectD TapInfo::GetBookmarkSearchRect(ScreenBase const & screen) const +// static +m2::AnyRectD TapInfo::GetBookmarkSearchRect(m2::PointD const & mercator, ScreenBase const & screen) { static int constexpr kBmTouchPixelIncrease = 20; @@ -2666,19 +2668,26 @@ m2::AnyRectD TapInfo::GetBookmarkSearchRect(ScreenBase const & screen) const double const halfSize = VisualParams::Instance().GetTouchRectRadius(); double const pxWidth = halfSize; double const pxHeight = halfSize + bmAddition; - screen.GetTouchRect(screen.GtoP(m_mercator) + m2::PointD(0, bmAddition), + screen.GetTouchRect(screen.GtoP(mercator) + m2::PointD(0, bmAddition), pxWidth, pxHeight, result); return result; } -m2::AnyRectD TapInfo::GetRoutingPointSearchRect(ScreenBase const & screen) const +// static +m2::AnyRectD TapInfo::GetRoutingPointSearchRect(m2::PointD const & mercator, ScreenBase const & screen) { static int constexpr kRoutingPointTouchPixelIncrease = 20; m2::AnyRectD result; double const bmAddition = kRoutingPointTouchPixelIncrease * VisualParams::Instance().GetVisualScale(); double const halfSize = VisualParams::Instance().GetTouchRectRadius(); - screen.GetTouchRect(screen.GtoP(m_mercator), halfSize + bmAddition, result); + screen.GetTouchRect(screen.GtoP(mercator), halfSize + bmAddition, result); return result; } + +// static +m2::AnyRectD TapInfo::GetPreciseSearchRect(m2::PointD const & mercator, double const eps) +{ + return m2::AnyRectD(mercator, ang::AngleD(0.0) /* angle */, m2::RectD(-eps, -eps, eps, eps)); +} } // namespace df diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index ace736ce68..9b3cca99bf 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -65,9 +65,10 @@ struct TapInfo bool const m_isMyPositionTapped; FeatureID const m_featureTapped; - m2::AnyRectD GetDefaultSearchRect(ScreenBase const & screen) const; - m2::AnyRectD GetBookmarkSearchRect(ScreenBase const & screen) const; - m2::AnyRectD GetRoutingPointSearchRect(ScreenBase const & screen) const; + static m2::AnyRectD GetDefaultSearchRect(m2::PointD const & mercator, ScreenBase const & screen); + static m2::AnyRectD GetBookmarkSearchRect(m2::PointD const & mercator, ScreenBase const & screen); + static m2::AnyRectD GetRoutingPointSearchRect(m2::PointD const & mercator, ScreenBase const & screen); + static m2::AnyRectD GetPreciseSearchRect(m2::PointD const & mercator, double const eps); }; class FrontendRenderer : public BaseRenderer, diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h index d554631596..94acc8a3e7 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.h @@ -43,9 +43,9 @@ class Info; #pragma mark - MWMPlacePageViewManager - (void)dismissPlacePage; -- (void)showPlacePage:(place_page::Info const &)info; -- (void)updatePlacePage:(place_page::Info const &)info; -- (void)showPlacePageReview:(place_page::Info const &)info; +- (void)showPlacePage; +- (void)updatePlacePage; +- (void)showPlacePageReview; - (void)addPlace:(BOOL)isBusiness hasPoint:(BOOL)hasPoint point:(m2::PointD const &)point; #pragma mark - MWMNavigationDashboardManager diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm index f0bc25dec7..e2e72d5352 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm @@ -129,23 +129,21 @@ extern NSString * const kAlohalyticsTapEventKey; [self.placePageManager dismiss]; } -- (void)showPlacePage:(place_page::Info const &)info -{ - network_policy::CallPartnersApi([self, info](auto const & /* canUseNetwork */) { +- (void)showPlacePage { + network_policy::CallPartnersApi([self](auto const & /* canUseNetwork */) { self.trafficButtonHidden = YES; - [self.placePageManager show:info]; + [self.placePageManager show]; }); } -- (void)updatePlacePage:(place_page::Info const &)info { - [self.placePageManager update:info]; +- (void)updatePlacePage { + [self.placePageManager update]; } -- (void)showPlacePageReview:(place_page::Info const &)info -{ - network_policy::CallPartnersApi([self, info](auto const & /* canUseNetwork */) { +- (void)showPlacePageReview { + network_policy::CallPartnersApi([self](auto const & /* canUseNetwork */) { self.trafficButtonHidden = YES; - [self.placePageManager showReview:info]; + [self.placePageManager showReview]; }); } diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 8bb7d189e8..05d2e0c313 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -130,14 +130,13 @@ NSString * const kHotelFacilitiesSegue = @"Map2FacilitiesSegue"; self.controlsManager.hidden = !self.controlsManager.hidden; } -- (void)onMapObjectSelected:(place_page::Info const &)info -{ +- (void)onMapObjectSelected { self.controlsManager.hidden = NO; - [self.controlsManager showPlacePage:info]; + [self.controlsManager showPlacePage]; } -- (void)onMapObjectUpdated:(place_page::Info const &)info { - [self.controlsManager updatePlacePage:info]; +- (void)onMapObjectUpdated { + [self.controlsManager updatePlacePage]; } - (void)checkMaskedPointer:(UITouch *)touch withEvent:(df::TouchEvent &)e @@ -395,9 +394,9 @@ NSString * const kHotelFacilitiesSegue = @"Map2FacilitiesSegue"; self.listeners = [NSHashTable> weakObjectsHashTable]; Framework & f = GetFramework(); // TODO: Review and improve this code. - f.SetPlacePageListenners([self](place_page::Info const &info) { [self onMapObjectSelected:info]; }, - [self](bool switchFullScreen) { [self onMapObjectDeselected:switchFullScreen]; }, - [self](place_page::Info const &info) { [self onMapObjectUpdated:info]; }); + f.SetPlacePageListeners([self]() { [self onMapObjectSelected]; }, + [self](bool switchFullScreen) { [self onMapObjectDeselected:switchFullScreen]; }, + [self]() { [self onMapObjectUpdated]; }); // TODO: Review and improve this code. f.SetMyPositionModeListener([self](location::EMyPositionMode mode, bool routingActive) { // TODO: Two global listeners are subscribed to the same event from the core. diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index b6bd097b2f..c18ded999e 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -808,9 +808,8 @@ continueUserActivity:(NSUserActivity *)userActivity { [Statistics logEvent:kStatUGCReviewNotificationClicked]; ReviewNotification * reviewNotification = (ReviewNotification *)notification; - place_page::Info info; - if (GetFramework().MakePlacePageInfo(reviewNotification.notificationWrapper.notificationCandidate, info)) - [[MapViewController sharedController].controlsManager showPlacePageReview:info]; + if (GetFramework().MakePlacePageForNotification(reviewNotification.notificationWrapper.notificationCandidate)) + [[MapViewController sharedController].controlsManager showPlacePageReview]; } else if (notification.class == AuthNotification.class) { diff --git a/iphone/Maps/UI/PlacePage/MWMPlacePageData.h b/iphone/Maps/UI/PlacePage/MWMPlacePageData.h index 7a3596ddc4..4242be160a 100644 --- a/iphone/Maps/UI/PlacePage/MWMPlacePageData.h +++ b/iphone/Maps/UI/PlacePage/MWMPlacePageData.h @@ -165,9 +165,6 @@ typedef void (^RefreshPromoCallbackBlock)(NSIndexSet *insertedSections); @property(nonatomic, readonly) BOOL isSmartDeal; @property(nonatomic, readonly) BOOL isPopular; -// ready callback will be called from main queue. -- (instancetype)initWithPlacePageInfo:(place_page::Info const &)info; - - (place_page::Info const &)getRawData; - (void)fillSections; diff --git a/iphone/Maps/UI/PlacePage/MWMPlacePageData.mm b/iphone/Maps/UI/PlacePage/MWMPlacePageData.mm index 53dbe18cd9..e909c71c50 100644 --- a/iphone/Maps/UI/PlacePage/MWMPlacePageData.mm +++ b/iphone/Maps/UI/PlacePage/MWMPlacePageData.mm @@ -49,8 +49,6 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; @implementation MWMPlacePageData { - Info m_info; - std::vector m_sections; std::vector m_previewRows; std::vector m_metainfoRows; @@ -65,16 +63,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; booking::HotelInfo m_hotelInfo; } -- (instancetype)initWithPlacePageInfo:(Info const &)info -{ - self = [super init]; - if (self) - m_info = info; - - return self; -} - -- (place_page::Info const &)getRawData { return m_info; } +- (place_page::Info const &)getRawData { return GetFramework().GetCurrentPlacePageInfo(); } #pragma mark - Filling sections @@ -97,8 +86,10 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; m_sections.push_back(Sections::Description); } + place_page::Info const & info = [self getRawData]; + // It's bookmark. - if (m_info.IsBookmark()) + if (info.IsBookmark()) m_sections.push_back(Sections::Bookmark); // There is always at least coordinate meta field. @@ -125,24 +116,25 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; [Statistics logEvent:kStatPlacepageTaxiShow withParameters:@{ @"provider" : provider }]; } - if (m_info.ShouldShowAddPlace() || m_info.ShouldShowEditPlace() || - m_info.ShouldShowAddBusiness() || m_info.IsSponsored()) + if (info.ShouldShowAddPlace() || info.ShouldShowEditPlace() || + info.ShouldShowAddBusiness() || info.IsSponsored()) { m_sections.push_back(Sections::Buttons); [self fillButtonsSection]; } - if (m_info.ShouldShowUGC()) + if (info.ShouldShowUGC()) [self addUGCSections]; } - (void)addUGCSections { - NSAssert(m_info.ShouldShowUGC(), @""); + place_page::Info const & info = [self getRawData]; + NSAssert(info.ShouldShowUGC(), @""); __weak auto wself = self; GetFramework().GetUGC( - m_info.GetID(), [wself](ugc::UGC const & ugc, ugc::UGCUpdate const & update) { + info.GetID(), [wself](ugc::UGC const & ugc, ugc::UGCUpdate const & update) { __strong auto self = wself; self.ugc = [[MWMUGCViewModel alloc] initWithUGC:ugc update:update]; @@ -260,11 +252,12 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; m_previewRows.push_back(PreviewRows::Space); NSAssert(!m_previewRows.empty(), @"Preview row's can't be empty!"); - if (network_policy::CanUseNetwork() && m_info.HasBanner()) + place_page::Info const & info = [self getRawData]; + if (network_policy::CanUseNetwork() && info.HasBanner()) { __weak auto wSelf = self; [[MWMBannersCache cache] - getWithCoreBanners:banner_helpers::MatchPriorityBanners(m_info.GetBanners()) + getWithCoreBanners:banner_helpers::MatchPriorityBanners(info.GetBanners()) cacheOnly:NO loadNew:YES completion:^(id ad, BOOL isAsync) { @@ -283,7 +276,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (void)fillMetaInfoSection { using namespace osm; - auto const availableProperties = m_info.AvailableProperties(); + auto const availableProperties = [self getRawData].AvailableProperties(); // We can't match each metadata property to its UI field and thats why we need to use our own // enum. for (auto const p : availableProperties) @@ -311,13 +304,14 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; } } - auto const address = m_info.GetAddress(); + place_page::Info const & info = [self getRawData]; + auto const address = info.GetAddress(); if (!address.empty()) m_metainfoRows.push_back(MetainfoRows::Address); m_metainfoRows.push_back(MetainfoRows::Coordinate); - switch (m_info.GetLocalAdsStatus()) + switch (info.GetLocalAdsStatus()) { case place_page::LocalAdsStatus::NotAvailable: break; case place_page::LocalAdsStatus::Candidate: @@ -342,19 +336,22 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; return; } - if (m_info.ShouldShowAddPlace()) + place_page::Info const & info = [self getRawData]; + + if (info.ShouldShowAddPlace()) m_buttonsRows.push_back(ButtonsRows::AddPlace); - if (m_info.ShouldShowEditPlace()) + if (info.ShouldShowEditPlace()) m_buttonsRows.push_back(ButtonsRows::EditPlace); - if (m_info.ShouldShowAddBusiness()) + if (info.ShouldShowAddBusiness()) m_buttonsRows.push_back(ButtonsRows::AddBusiness); } - (float)ratingRawValue { - return m_info.GetRatingRawValue(); + place_page::Info const & info = [self getRawData]; + return info.GetRatingRawValue(); } - (void)fillOnlineBookingSections @@ -457,30 +454,36 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; { auto & f = GetFramework(); auto & bmManager = f.GetBookmarkManager(); + place_page::Info const & info = [self getRawData]; if (isBookmark) { auto const categoryId = f.LastEditedBMCategory(); kml::BookmarkData bmData; - bmData.m_name = m_info.FormatNewBookmarkName(); + bmData.m_name = info.FormatNewBookmarkName(); bmData.m_color.m_predefinedColor = f.LastEditedBMColor(); bmData.m_point = self.mercator; - if (m_info.IsFeature()) - SaveFeatureTypes(m_info.GetTypes(), bmData); + if (info.IsFeature()) + SaveFeatureTypes(info.GetTypes(), bmData); auto editSession = bmManager.GetEditSession(); auto const * bookmark = editSession.CreateBookmark(std::move(bmData), categoryId); - f.FillBookmarkInfo(*bookmark, m_info); + + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_match = place_page::BuildInfo::Match::Everything; + buildInfo.m_userMarkId = bookmark->GetId(); + f.UpdatePlacePageInfoForCurrentSelection(buildInfo); + m_sections.insert(m_sections.begin() + [self bookmarkSectionPosition], Sections::Bookmark); } else { - auto const bookmarkId = m_info.GetBookmarkId(); - auto const * bookmark = bmManager.GetBookmark(bookmarkId); - if (bookmark) - { - f.ResetBookmarkInfo(*bookmark, m_info); - [[MWMBookmarksManager sharedManager] deleteBookmark:bookmarkId]; - } + auto const bookmarkId = info.GetBookmarkId(); + [[MWMBookmarksManager sharedManager] deleteBookmark:bookmarkId]; + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_match = place_page::BuildInfo::Match::FeatureOnly; + buildInfo.m_userMarkId = kml::kInvalidMarkId; + f.UpdatePlacePageInfoForCurrentSelection(buildInfo); + m_sections.erase(remove(m_sections.begin(), m_sections.end(), Sections::Bookmark)); } } @@ -498,14 +501,14 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; #pragma mark - Getters -- (BOOL)isPopular { return m_info.GetPopularity() > 0; } -- (storage::CountryId const &)countryId { return m_info.GetCountryId(); } -- (FeatureID const &)featureId { return m_info.GetID(); } -- (NSString *)title { return @(m_info.GetTitle().c_str()); } -- (NSString *)subtitle { return @(m_info.GetSubtitle().c_str()); } +- (BOOL)isPopular { return [self getRawData].GetPopularity() > 0; } +- (storage::CountryId const &)countryId { return [self getRawData].GetCountryId(); } +- (FeatureID const &)featureId { return [self getRawData].GetID(); } +- (NSString *)title { return @([self getRawData].GetTitle().c_str()); } +- (NSString *)subtitle { return @([self getRawData].GetSubtitle().c_str()); } - (NSString *)placeDescription { - NSString * descr = @(m_info.GetDescription().c_str()); + NSString * descr = @([self getRawData].GetDescription().c_str()); if (descr.length > 0) descr = [NSString stringWithFormat:@"%@", descr]; @@ -515,7 +518,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (place_page::OpeningHours)schedule; { using type = place_page::OpeningHours; - auto const raw = m_info.GetOpeningHours(); + auto const raw = [self getRawData].GetOpeningHours(); if (raw.empty()) return type::Unknown; @@ -539,7 +542,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; { if (!self.isBooking) return nil; - auto const ratingRaw = m_info.GetRatingRawValue(); + auto const ratingRaw = [self getRawData].GetRatingRawValue(); return [[MWMUGCRatingValueType alloc] initWithValue:@(rating::GetRatingFormatted(ratingRaw).c_str()) type:[MWMPlacePageData ratingValueType:rating::GetImpress(ratingRaw)]]; @@ -548,15 +551,16 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (NSString *)bookingPricing { ASSERT(self.isBooking, ("Only for booking.com hotels")); - return self.cachedMinPrice.length ? self.cachedMinPrice : @(m_info.GetApproximatePricing().c_str()); + return self.cachedMinPrice.length ? self.cachedMinPrice : @([self getRawData].GetApproximatePricing().c_str()); } - (NSURL *)sponsoredURL { + place_page::Info const & info = [self getRawData]; // There are sponsors without URL. For such psrtners we do not show special button. - if (m_info.IsSponsored() && !m_info.GetSponsoredUrl().empty()) + if (info.IsSponsored() && !info.GetSponsoredUrl().empty()) { - auto urlString = [@(m_info.GetSponsoredUrl().c_str()) + auto urlString = [@(info.GetSponsoredUrl().c_str()) stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet .URLQueryAllowedCharacterSet]; auto url = [NSURL URLWithString:urlString]; @@ -567,8 +571,9 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (NSURL *)deepLink { - auto const & link = m_info.GetSponsoredDeepLink(); - if (m_info.IsSponsored() && !link.empty()) + place_page::Info const & info = [self getRawData]; + auto const & link = info.GetSponsoredDeepLink(); + if (info.IsSponsored() && !link.empty()) return [NSURL URLWithString:@(link.c_str())]; return nil; @@ -576,35 +581,39 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (NSURL *)sponsoredDescriptionURL { - return m_info.IsSponsored() - ? [NSURL URLWithString:@(m_info.GetSponsoredDescriptionUrl().c_str())] + place_page::Info const & info = [self getRawData]; + return info.IsSponsored() + ? [NSURL URLWithString:@(info.GetSponsoredDescriptionUrl().c_str())] : nil; } - (NSURL *)sponsoredMoreURL { - return m_info.IsSponsored() - ? [NSURL URLWithString:@(m_info.GetSponsoredMoreUrl().c_str())] + place_page::Info const & info = [self getRawData]; + return info.IsSponsored() + ? [NSURL URLWithString:@(info.GetSponsoredMoreUrl().c_str())] : nil; } - (NSURL *)sponsoredReviewURL { - return m_info.IsSponsored() - ? [NSURL URLWithString:@(m_info.GetSponsoredReviewUrl().c_str())] + place_page::Info const & info = [self getRawData]; + return info.IsSponsored() + ? [NSURL URLWithString:@(info.GetSponsoredReviewUrl().c_str())] : nil; } - (NSURL *)bookingSearchURL { - auto const & url = m_info.GetBookingSearchUrl(); + auto const & url = [self getRawData].GetBookingSearchUrl(); return url.empty() ? nil : [NSURL URLWithString:@(url.c_str())]; } - (NSString *)sponsoredId { - return m_info.IsSponsored() - ? @(m_info.GetMetadata().Get(feature::Metadata::FMD_SPONSORED_ID).c_str()) + place_page::Info const & info = [self getRawData]; + return info.IsSponsored() + ? @(info.GetMetadata().Get(feature::Metadata::FMD_SPONSORED_ID).c_str()) : nil; } @@ -627,7 +636,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (std::vector const &)hotelReviews { return m_hotelInfo.m_reviews; } - (NSUInteger)numberOfHotelReviews { return m_hotelInfo.m_scoreCount; } -- (NSURL *)URLToAllReviews { return [NSURL URLWithString:@(m_info.GetSponsoredReviewUrl().c_str())]; } +- (NSURL *)URLToAllReviews { return [NSURL URLWithString:@([self getRawData].GetSponsoredReviewUrl().c_str())]; } - (NSArray *)photos { if (_photos) @@ -651,29 +660,29 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (boost::optional)hotelRawApproximatePricing { - return m_info.GetRawApproximatePricing(); + return [self getRawData].GetRawApproximatePricing(); } - (boost::optional)hotelType { - return m_info.GetHotelType(); + return [self getRawData].GetHotelType(); } #pragma mark - Partners - (NSString *)partnerName { - return self.isPartner ? @(m_info.GetPartnerName().c_str()) : nil; + return self.isPartner ? @([self getRawData].GetPartnerName().c_str()) : nil; } - (int)partnerIndex { - return self.isPartner ? m_info.GetPartnerIndex() : -1; + return self.isPartner ? [self getRawData].GetPartnerIndex() : -1; } #pragma mark - UGC -- (ftraits::UGCRatingCategories)ugcRatingCategories { return m_info.GetRatingCategories(); } +- (ftraits::UGCRatingCategories)ugcRatingCategories { return [self getRawData].GetRatingCategories(); } - (void)setUGCUpdateFrom:(MWMUGCReviewModel *)reviewModel resultHandler:(void (^)(BOOL))resultHandler { @@ -693,8 +702,9 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; UGCUpdate update{r, t, std::chrono::system_clock::now()}; - GetFramework().GetUGCApi()->SetUGCUpdate(m_info.GetID(), update, - [resultHandler, info = m_info](Storage::SettingResult const result) + place_page::Info const & info = [self getRawData]; + GetFramework().GetUGCApi()->SetUGCUpdate(info.GetID(), update, + [resultHandler, info](Storage::SettingResult const result) { if (result != Storage::SettingResult::Success) { @@ -714,32 +724,38 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (NSString *)externalTitle { - return m_info.GetSecondaryTitle().empty() ? nil : @(m_info.GetSecondaryTitle().c_str()); + place_page::Info const & info = [self getRawData]; + return info.GetSecondaryTitle().empty() ? nil : @(info.GetSecondaryTitle().c_str()); } - (kml::PredefinedColor)bookmarkColor { - return m_info.IsBookmark() ? m_info.GetBookmarkData().m_color.m_predefinedColor : kml::PredefinedColor::None; + place_page::Info const & info = [self getRawData]; + return info.IsBookmark() ? info.GetBookmarkData().m_color.m_predefinedColor : kml::PredefinedColor::None; } - (NSString *)bookmarkDescription { - return m_info.IsBookmark() ? @(GetPreferredBookmarkStr(m_info.GetBookmarkData().m_description).c_str()) : nil; + place_page::Info const & info = [self getRawData]; + return info.IsBookmark() ? @(GetPreferredBookmarkStr(info.GetBookmarkData().m_description).c_str()) : nil; } - (NSString *)bookmarkCategory { - return m_info.IsBookmark() ? @(m_info.GetBookmarkCategoryName().c_str()) : nil; + place_page::Info const & info = [self getRawData]; + return info.IsBookmark() ? @(info.GetBookmarkCategoryName().c_str()) : nil; } - (kml::MarkId)bookmarkId { - return m_info.GetBookmarkId(); + place_page::Info const & info = [self getRawData]; + return info.GetBookmarkId(); } - (kml::MarkGroupId)bookmarkCategoryId { - return m_info.GetBookmarkCategoryId(); + place_page::Info const & info = [self getRawData]; + return info.GetBookmarkCategoryId(); } - (BOOL)isBookmarkEditable @@ -748,13 +764,14 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; } #pragma mark - Local Ads -- (NSString *)localAdsURL { return @(m_info.GetLocalAdsUrl().c_str()); } +- (NSString *)localAdsURL { return @([self getRawData].GetLocalAdsUrl().c_str()); } - (void)logLocalAdsEvent:(local_ads::EventType)type { - auto const status = m_info.GetLocalAdsStatus(); + place_page::Info const & info = [self getRawData]; + auto const status = info.GetLocalAdsStatus(); if (status != place_page::LocalAdsStatus::Customer && status != place_page::LocalAdsStatus::Hidden) return; - auto const featureID = m_info.GetID(); + auto const featureID = info.GetID(); auto const & mwmInfo = featureID.m_mwmId.GetInfo(); if (!mwmInfo) return; @@ -770,15 +787,15 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; #pragma mark - Taxi - (std::vector const &)taxiProviders { - return m_info.ReachableByTaxiProviders(); + return [self getRawData].ReachableByTaxiProviders(); } #pragma mark - Getters -- (RouteMarkType)routeMarkType { return m_info.GetRouteMarkType(); } -- (size_t)intermediateIndex { return m_info.GetIntermediateIndex(); } -- (NSString *)address { return @(m_info.GetAddress().c_str()); } -- (NSString *)apiURL { return @(m_info.GetApiUrl().c_str()); } +- (RouteMarkType)routeMarkType { return [self getRawData].GetRouteMarkType(); } +- (size_t)intermediateIndex { return [self getRawData].GetIntermediateIndex(); } +- (NSString *)address { return @([self getRawData].GetAddress().c_str()); } +- (NSString *)apiURL { return @([self getRawData].GetApiUrl().c_str()); } - (std::vector const &)sections { return m_sections; } - (std::vector const &)previewRows { return m_previewRows; } - (std::vector const &)metainfoRows { return m_metainfoRows; } @@ -791,23 +808,23 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (std::vector const &)hotelReviewsRows { return m_hotelReviewsRows; } - (NSString *)stringForRow:(MetainfoRows)row { + place_page::Info const & info = [self getRawData]; switch (row) { case MetainfoRows::ExtendedOpeningHours: return nil; - case MetainfoRows::OpeningHours: return @(m_info.GetOpeningHours().c_str()); - case MetainfoRows::Phone: return @(m_info.GetPhone().c_str()); - case MetainfoRows::Address: return @(m_info.GetAddress().c_str()); - case MetainfoRows::Website: return @(m_info.GetWebsite().c_str()); - case MetainfoRows::Email: return @(m_info.GetEmail().c_str()); + case MetainfoRows::OpeningHours: return @(info.GetOpeningHours().c_str()); + case MetainfoRows::Phone: return @(info.GetPhone().c_str()); + case MetainfoRows::Address: return @(info.GetAddress().c_str()); + case MetainfoRows::Website: return @(info.GetWebsite().c_str()); + case MetainfoRows::Email: return @(info.GetEmail().c_str()); case MetainfoRows::Cuisine: - return @(strings::JoinStrings(m_info.GetLocalizedCuisines(), Info::kSubtitleSeparator).c_str()); - case MetainfoRows::Operator: return @(m_info.GetOperator().c_str()); + return @(strings::JoinStrings(info.GetLocalizedCuisines(), Info::kSubtitleSeparator).c_str()); + case MetainfoRows::Operator: return @(info.GetOperator().c_str()); case MetainfoRows::Internet: return L(@"WiFi_available"); case MetainfoRows::LocalAdsCandidate: return L(@"create_campaign_button"); case MetainfoRows::LocalAdsCustomer: return L(@"view_campaign_button"); case MetainfoRows::Coordinate: - return @(m_info - .GetFormattedCoordinate( + return @(info.GetFormattedCoordinate( [NSUserDefaults.standardUserDefaults boolForKey:kUserDefaultsLatLonAsDMSKey]) .c_str()); } @@ -816,22 +833,22 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; #pragma mark - Helpers -- (NSString *)phoneNumber { return @(m_info.GetPhone().c_str()); } -- (BOOL)isBookmark { return m_info.IsBookmark(); } -- (BOOL)isApi { return m_info.HasApiUrl(); } -- (BOOL)isBooking { return m_info.GetSponsoredType() == SponsoredType::Booking; } -- (BOOL)isOpentable { return m_info.GetSponsoredType() == SponsoredType::Opentable; } -- (BOOL)isPartner { return m_info.GetSponsoredType() == SponsoredType::Partner; } -- (BOOL)isHolidayObject { return m_info.GetSponsoredType() == SponsoredType::Holiday; } +- (NSString *)phoneNumber { return @([self getRawData].GetPhone().c_str()); } +- (BOOL)isBookmark { return [self getRawData].IsBookmark(); } +- (BOOL)isApi { return [self getRawData].HasApiUrl(); } +- (BOOL)isBooking { return [self getRawData].GetSponsoredType() == SponsoredType::Booking; } +- (BOOL)isOpentable { return [self getRawData].GetSponsoredType() == SponsoredType::Opentable; } +- (BOOL)isPartner { return [self getRawData].GetSponsoredType() == SponsoredType::Partner; } +- (BOOL)isHolidayObject { return [self getRawData].GetSponsoredType() == SponsoredType::Holiday; } - (BOOL)isPromoCatalog { return self.isLargeToponim || self.isSightseeing; } -- (BOOL)isLargeToponim { return m_info.GetSponsoredType() == SponsoredType::PromoCatalogCity; } -- (BOOL)isSightseeing { return m_info.GetSponsoredType() == SponsoredType::PromoCatalogSightseeings; } -- (BOOL)isBookingSearch { return !m_info.GetBookingSearchUrl().empty(); } -- (BOOL)isMyPosition { return m_info.IsMyPosition(); } -- (BOOL)isHTMLDescription { return strings::IsHTML(GetPreferredBookmarkStr(m_info.GetBookmarkData().m_description)); } -- (BOOL)isRoutePoint { return m_info.IsRoutePoint(); } -- (RoadWarningMarkType)roadType { return m_info.GetRoadType(); } -- (BOOL)isPreviewPlus { return m_info.GetOpeningMode() == place_page::OpeningMode::PreviewPlus; } +- (BOOL)isLargeToponim { return [self getRawData].GetSponsoredType() == SponsoredType::PromoCatalogCity; } +- (BOOL)isSightseeing { return [self getRawData].GetSponsoredType() == SponsoredType::PromoCatalogSightseeings; } +- (BOOL)isBookingSearch { return ![self getRawData].GetBookingSearchUrl().empty(); } +- (BOOL)isMyPosition { return [self getRawData].IsMyPosition(); } +- (BOOL)isHTMLDescription { return strings::IsHTML(GetPreferredBookmarkStr([self getRawData].GetBookmarkData().m_description)); } +- (BOOL)isRoutePoint { return [self getRawData].IsRoutePoint(); } +- (RoadWarningMarkType)roadType { return [self getRawData].GetRoadType(); } +- (BOOL)isPreviewPlus { return [self getRawData].GetOpeningMode() == place_page::OpeningMode::PreviewPlus; } - (BOOL)isPartnerAppInstalled { // TODO(): Load list of registered schemas from plist. @@ -852,8 +869,8 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; } #pragma mark - Coordinates -- (m2::PointD const &)mercator { return m_info.GetMercator(); } -- (ms::LatLon)latLon { return m_info.GetLatLon(); } +- (m2::PointD const &)mercator { return [self getRawData].GetMercator(); } +- (ms::LatLon)latLon { return [self getRawData].GetLatLon(); } + (void)toggleCoordinateSystem { // TODO: Move changing latlon's mode to the settings. @@ -867,7 +884,7 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; - (NSString *)statisticsTags { NSMutableArray * result = [@[] mutableCopy]; - for (auto const & s : m_info.GetRawTypes()) + for (auto const & s : [self getRawData].GetRawTypes()) [result addObject:@(s.c_str())]; return [result componentsJoinedByString:@", "]; } @@ -952,11 +969,12 @@ NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS"; auto appInfo = AppInfo.sharedInfo; auto locale = appInfo.twoLetterLanguageId.UTF8String; - if (m_info.GetSponsoredType() == SponsoredType::PromoCatalogCity) { + place_page::Info const & info = [self getRawData]; + if (info.GetSponsoredType() == SponsoredType::PromoCatalogCity) { api->GetCityGallery(self.mercator, locale, UTM::LargeToponymsPlacepageGallery, resultHandler, errorHandler); } else { api->GetPoiGallery(self.mercator, locale, - m_info.GetRawTypes(), + info.GetRawTypes(), [MWMFrameworkHelper isWiFiConnected], UTM::SightseeingsPlacepageGallery, resultHandler, diff --git a/iphone/Maps/UI/PlacePage/MWMPlacePageManager.mm b/iphone/Maps/UI/PlacePage/MWMPlacePageManager.mm index 82bddabf60..afd2c7a540 100644 --- a/iphone/Maps/UI/PlacePage/MWMPlacePageManager.mm +++ b/iphone/Maps/UI/PlacePage/MWMPlacePageManager.mm @@ -89,20 +89,18 @@ void RegisterEventIfPossible(eye::MapObject::Event::Type const type, place_page: @implementation MWMPlacePageManager -- (void)showReview:(place_page::Info const &)info -{ - [self show:info]; +- (void)showReview { + [self show]; [self showUGCAddReview:MWMRatingSummaryViewValueTypeNoValue fromSource:MWMUGCReviewSourceNotification]; } -- (void)show:(place_page::Info const &)info -{ +- (void)show { self.isSponsoredOpenLogged = NO; self.currentDownloaderStatus = storage::NodeStatus::Undefined; [MWMFrameworkListener addObserver:self]; - self.data = [[MWMPlacePageData alloc] initWithPlacePageInfo:info]; + self.data = [[MWMPlacePageData alloc] init]; [self.data fillSections]; if (!self.layout) @@ -123,11 +121,11 @@ void RegisterEventIfPossible(eye::MapObject::Event::Type const type, place_page: [self processCountryEvent:[self.data countryId]]; } -- (void)update:(place_page::Info const &)info { +- (void)update { if (!self.isPPShown) return; - self.data = [[MWMPlacePageData alloc] initWithPlacePageInfo:info]; + self.data = [[MWMPlacePageData alloc] init]; [self.data fillSections]; [self setupSpeedAndDistance]; [self.layout updateWithData:self.data]; diff --git a/iphone/Maps/UI/PlacePage/MWMPlacePageProtocol.h b/iphone/Maps/UI/PlacePage/MWMPlacePageProtocol.h index 4295ac4313..1dac0d2aa6 100644 --- a/iphone/Maps/UI/PlacePage/MWMPlacePageProtocol.h +++ b/iphone/Maps/UI/PlacePage/MWMPlacePageProtocol.h @@ -49,9 +49,9 @@ struct HotelFacility; @protocol MWMPlacePageProtocol -- (void)show:(place_page::Info const &)info; -- (void)update:(place_page::Info const &)info; -- (void)showReview:(place_page::Info const &)info; +- (void)show; +- (void)update; +- (void)showReview; - (BOOL)isPPShown; - (void)dismiss; - (void)mwm_refreshUI; diff --git a/map/framework.cpp b/map/framework.cpp index a13c5d8cde..989842b58c 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -380,7 +380,6 @@ void Framework::Migrate(bool keepDownloaded) OnDestroySurface(); } m_bmManager->ResetRegionAddressGetter(); - m_selectedFeature = FeatureID(); m_discoveryManager.reset(); m_searchAPI.reset(); m_infoGetter.reset(); @@ -850,16 +849,6 @@ void Framework::FillBookmarkInfo(Bookmark const & bmk, place_page::Info & info) FillPointInfoForBookmark(bmk, info); } -void Framework::ResetBookmarkInfo(Bookmark const & bmk, place_page::Info & info) const -{ - info.SetBookmarkCategoryName(""); - info.SetBookmarkData({}); - info.SetBookmarkId(kml::kInvalidMarkId); - info.SetBookmarkCategoryId(kml::kInvalidMarkGroupId); - info.SetOpeningMode(place_page::OpeningMode::Preview); - FillPointInfoForBookmark(bmk, info); -} - search::ReverseGeocoder::Address Framework::GetAddressAtPoint(m2::PointD const & pt) const { return m_addressGetter.GetAddressAtPoint(m_featuresFetcher.GetDataSource(), pt); @@ -889,22 +878,27 @@ void Framework::FillPointInfo(place_page::Info & info, m2::PointD const & mercat FeatureMatcher && matcher /* = nullptr */) const { auto const fid = GetFeatureAtPoint(mercator, move(matcher)); - if (fid.IsValid()) { m_featuresFetcher.GetDataSource().ReadFeature( [&](FeatureType & ft) { FillInfoFromFeatureType(ft, info); }, fid); + // This line overwrites mercator center from area feature which can be far away. + info.SetMercator(mercator); } else { - if (customTitle.empty()) - info.SetCustomNameWithCoordinates(mercator, m_stringsBundle.GetString("core_placepage_unknown_place")); - else - info.SetCustomName(customTitle); - info.SetCanEditOrAdd(CanEditMap()); + FillNotMatchedPlaceInfo(info, mercator, customTitle); } +} - // This line overwrites mercator center from area feature which can be far away. +void Framework::FillNotMatchedPlaceInfo(place_page::Info & info, m2::PointD const & mercator, + std::string const & customTitle /* = {} */) const +{ + if (customTitle.empty()) + info.SetCustomNameWithCoordinates(mercator, m_stringsBundle.GetString("core_placepage_unknown_place")); + else + info.SetCustomName(customTitle); + info.SetCanEditOrAdd(CanEditMap()); info.SetMercator(mercator); } @@ -1083,15 +1077,14 @@ void Framework::FillSearchResultInfo(SearchMarkPoint const & smp, place_page::In FillPointInfo(info, smp.GetPivot(), smp.GetMatchedName()); } -void Framework::FillMyPositionInfo(place_page::Info & info, df::TapInfo const & tapInfo) const +void Framework::FillMyPositionInfo(place_page::Info & info, place_page::BuildInfo const & buildInfo) const { auto const position = GetCurrentPosition(); VERIFY(position, ()); info.SetMercator(*position); - info.SetIsMyPosition(); info.SetCustomName(m_stringsBundle.GetString("core_my_position")); - UserMark const * mark = FindUserMarkInTapPosition(tapInfo); + UserMark const * mark = FindUserMarkInTapPosition(buildInfo); if (mark != nullptr && mark->GetMarkType() == UserMark::Type::ROUTING) { auto routingMark = static_cast(mark); @@ -1150,20 +1143,22 @@ void Framework::ShowBookmark(Bookmark const * mark) StopLocationFollow(); + place_page::BuildInfo info; + info.m_mercator = mark->GetPivot(); + info.m_userMarkId = mark->GetId(); + m_currentPlacePageInfo = BuildPlacePageInfo(info); + auto scale = static_cast(mark->GetScale()); if (scale == 0) scale = scales::GetUpperComfortScale(); if (m_drapeEngine != nullptr) + { m_drapeEngine->SetModelViewCenter(mark->GetPivot(), scale, true /* isAnim */, true /* trackVisibleViewport */); + } - place_page::Info info; - FillBookmarkInfo(*mark, info); - ActivateMapSelection(true, df::SelectionShape::OBJECT_USER_MARK, TapEvent::Source::Other, info); - // TODO - // We need to preserve bookmark id in the m_lastTapEvent, because one feature can have several bookmarks. - m_lastTapEvent = MakeTapEvent(info.GetMercator(), info.GetID(), TapEvent::Source::Other); + ActivateMapSelection(m_currentPlacePageInfo); } void Framework::ShowTrack(kml::TrackId trackId) @@ -1195,18 +1190,15 @@ void Framework::ShowFeatureByMercator(m2::PointD const & pt) { StopLocationFollow(); + place_page::BuildInfo info; + info.m_mercator = pt; + m_currentPlacePageInfo = BuildPlacePageInfo(info); if (m_drapeEngine != nullptr) { m_drapeEngine->SetModelViewCenter(pt, scales::GetUpperComfortScale(), true /* isAnim */, true /* trackVisibleViewport */); } - - place_page::Info info; - std::string name; - GetBookmarkManager().SelectionMark().SetPtOrg(pt); - FillPointInfo(info, pt, name); - ActivateMapSelection(false, df::SelectionShape::OBJECT_POI, TapEvent::Source::Other, info); - m_lastTapEvent = MakeTapEvent(info.GetMercator(), info.GetID(), TapEvent::Source::Other); + ActivateMapSelection(m_currentPlacePageInfo); } void Framework::AddBookmarksFile(string const & filePath, bool isTemporaryFile) @@ -1706,43 +1698,51 @@ search::DisplayedCategories const & Framework::GetDisplayedCategories() void Framework::SelectSearchResult(search::Result const & result, bool animation) { - place_page::Info info; using namespace search; - int scale; + place_page::BuildInfo info; + info.m_source = place_page::BuildInfo::Source::Search; + info.m_needAnimationOnSelection = false; + int scale = -1; switch (result.GetResultType()) { case Result::Type::Feature: - FillFeatureInfo(result.GetFeatureID(), info); - scale = GetFeatureViewportScale(info.GetTypes()); + info.m_mercator = result.GetFeatureCenter(); + info.m_featureId = result.GetFeatureID(); + info.m_isGeometrySelectionAllowed = true; break; case Result::Type::LatLon: - FillPointInfo(info, result.GetFeatureCenter(), result.GetString()); + info.m_mercator = result.GetFeatureCenter(); + info.m_match = place_page::BuildInfo::Match::Nothing; scale = scales::GetUpperComfortScale(); break; case Result::Type::Postcode: - FillPostcodeInfo(result.GetString(), result.GetFeatureCenter(), info); + info.m_mercator = result.GetFeatureCenter(); + info.m_match = place_page::BuildInfo::Match::Nothing; + info.m_postcode = result.GetString(); scale = scales::GetUpperComfortScale(); break; case Result::Type::SuggestFromFeature: - case Result::Type::PureSuggest: ASSERT(false, ("Suggests should not be here.")); return; + case Result::Type::PureSuggest: + m_currentPlacePageInfo = {}; + ASSERT(false, ("Suggests should not be here.")); + return; } - if (m_purchase && !m_purchase->IsSubscriptionActive(SubscriptionType::RemoveAds)) - info.SetAdsEngine(m_adsEngine.get()); + m_currentPlacePageInfo = BuildPlacePageInfo(info); + if (m_currentPlacePageInfo) + { + if (scale < 0) + scale = GetFeatureViewportScale(m_currentPlacePageInfo->GetTypes()); - SetPlacePageLocation(info); - m2::PointD const center = info.GetMercator(); - if (m_drapeEngine != nullptr) - m_drapeEngine->SetModelViewCenter(center, scale, animation, true /* trackVisibleViewport */); + m2::PointD const center = m_currentPlacePageInfo->GetMercator(); + if (m_drapeEngine != nullptr) + m_drapeEngine->SetModelViewCenter(center, scale, animation, true /* trackVisibleViewport */); - GetBookmarkManager().SelectionMark().SetPtOrg(center); - auto const isGeometrySelectionAllowed = result.GetResultType() == Result::Type::Feature; - ActivateMapSelection(false, df::SelectionShape::OBJECT_POI, TapEvent::Source::Search, info, - isGeometrySelectionAllowed); - m_lastTapEvent = MakeTapEvent(center, info.GetID(), TapEvent::Source::Search); + ActivateMapSelection(m_currentPlacePageInfo); + } } void Framework::ShowSearchResult(search::Result const & res, bool animation) @@ -2002,7 +2002,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFac m_drapeEngine->SetTapEventInfoListener([this](df::TapInfo const & tapInfo) { GetPlatform().RunTask(Platform::Thread::Gui, [this, tapInfo]() { - OnTapEvent({tapInfo, TapEvent::Source::User}); + OnTapEvent(place_page::BuildInfo(tapInfo)); }); }); m_drapeEngine->SetUserPositionListener([this](m2::PointD const & position, bool hasPosition) @@ -2284,25 +2284,26 @@ bool Framework::ShowMapForURL(string const & url) // Always hide current map selection. DeactivateMapSelection(true /* notifyUI */); - // set viewport and stop follow mode if any + // Set viewport and stop follow mode. StopLocationFollow(); ShowRect(rect); if (result != NO_NEED_CLICK) { - place_page::Info info; - if (apiMark) + place_page::BuildInfo info; + info.m_needAnimationOnSelection = false; + if (apiMark != nullptr) { - FillApiMarkInfo(*apiMark, info); - ActivateMapSelection(false, df::SelectionShape::OBJECT_USER_MARK, TapEvent::Source::Other, info); + info.m_mercator = apiMark->GetPivot(); + info.m_userMarkId = apiMark->GetId(); } else { - GetBookmarkManager().SelectionMark().SetPtOrg(point); - FillPointInfo(info, point, name); - ActivateMapSelection(false, df::SelectionShape::OBJECT_POI, TapEvent::Source::Other, info); + info.m_mercator = point; } - m_lastTapEvent = MakeTapEvent(info.GetMercator(), info.GetID(), TapEvent::Source::Other); + + m_currentPlacePageInfo = BuildPlacePageInfo(info); + ActivateMapSelection(m_currentPlacePageInfo); } return true; @@ -2410,92 +2411,83 @@ BookmarkManager const & Framework::GetBookmarkManager() const return *m_bmManager.get(); } -void Framework::SetPlacePageListenners(PlacePageEvent::OnOpen const & onOpen, - PlacePageEvent::OnClose const & onClose, - PlacePageEvent::OnUpdate const & onUpdate) +void Framework::SetPlacePageListeners(PlacePageEvent::OnOpen const & onOpen, + PlacePageEvent::OnClose const & onClose, + PlacePageEvent::OnUpdate const & onUpdate) { m_onPlacePageOpen = onOpen; m_onPlacePageClose = onClose; m_onPlacePageUpdate = onUpdate; } -void Framework::ActivateMapSelection(bool needAnimation, - df::SelectionShape::ESelectedObject selectionType, - TapEvent::Source tapSource, place_page::Info const & info, - bool isGeometrySelectionAllowed) +place_page::Info const & Framework::GetCurrentPlacePageInfo() const { - ASSERT_NOT_EQUAL(selectionType, df::SelectionShape::OBJECT_EMPTY, ("Empty selections are impossible.")); - m_selectedFeature = info.GetID(); + CHECK(IsPlacePageOpened(), ()); + return m_currentPlacePageInfo.get(); +} + +place_page::Info & Framework::GetCurrentPlacePageInfo() +{ + CHECK(IsPlacePageOpened(), ()); + return m_currentPlacePageInfo.get(); +} + +void Framework::ActivateMapSelection(boost::optional const & info) +{ + if (!info) + return; + + CHECK_NOT_EQUAL(info->GetSelectedObject(), df::SelectionShape::OBJECT_EMPTY, ("Empty selections are impossible.")); if (m_drapeEngine != nullptr) { - m_drapeEngine->SelectObject(selectionType, info.GetMercator(), info.GetID(), needAnimation, - isGeometrySelectionAllowed); + m_drapeEngine->SelectObject(info->GetSelectedObject(), info->GetMercator(), info->GetID(), + info->GetBuildInfo().m_needAnimationOnSelection, + info->GetBuildInfo().m_isGeometrySelectionAllowed); } SetDisplacementMode(DisplacementModeManager::SLOT_MAP_SELECTION, - ftypes::IsHotelChecker::Instance()(info.GetTypes()) /* show */); + ftypes::IsHotelChecker::Instance()(info->GetTypes()) /* show */); if (m_onPlacePageOpen) - m_onPlacePageOpen(info); + m_onPlacePageOpen(); else LOG(LWARNING, ("m_onPlacePageOpen has not been set up.")); } void Framework::DeactivateMapSelection(bool notifyUI) { - bool const somethingWasAlreadySelected = (m_lastTapEvent != nullptr); - m_lastTapEvent.reset(); + bool const somethingWasAlreadySelected = (m_currentPlacePageInfo.has_value()); if (notifyUI && m_onPlacePageClose) m_onPlacePageClose(!somethingWasAlreadySelected); + m_currentPlacePageInfo = {}; + if (somethingWasAlreadySelected && m_drapeEngine != nullptr) m_drapeEngine->DeselectObject(); SetDisplacementMode(DisplacementModeManager::SLOT_MAP_SELECTION, false /* show */); } -void Framework::UpdatePlacePageInfoForCurrentSelection() -{ - if (m_lastTapEvent == nullptr) - return; - - place_page::Info info; - - auto const obj = OnTapEventImpl(*m_lastTapEvent, info); - - if (obj == df::SelectionShape::OBJECT_EMPTY) - return; - - SetPlacePageLocation(info); - - if (m_onPlacePageUpdate) - m_onPlacePageUpdate(info); -} - void Framework::InvalidateUserMarks() { GetBookmarkManager().GetEditSession(); } -void Framework::OnTapEvent(TapEvent const & tapEvent) +void Framework::OnTapEvent(place_page::BuildInfo const & buildInfo) { using place_page::SponsoredType; - auto const & tapInfo = tapEvent.m_info; - bool const somethingWasAlreadySelected = (m_lastTapEvent != nullptr); + bool const somethingWasAlreadySelected = (m_currentPlacePageInfo.has_value()); - place_page::Info info; - df::SelectionShape::ESelectedObject const selection = OnTapEventImpl(tapEvent, info); - if (selection != df::SelectionShape::OBJECT_EMPTY) + m_currentPlacePageInfo = BuildPlacePageInfo(buildInfo); + if (m_currentPlacePageInfo) { - // Back up last tap event to recover selection in case of Drape reinitialization. - m_lastTapEvent = make_unique(tapEvent); - - { // Log statistics event. - auto const ll = info.GetLatLon(); + // Log statistics events. + { + auto const ll = m_currentPlacePageInfo->GetLatLon(); double metersToTap = -1; - if (info.IsMyPosition()) + if (m_currentPlacePageInfo->IsMyPosition()) { metersToTap = 0; } @@ -2505,40 +2497,41 @@ void Framework::OnTapEvent(TapEvent const & tapEvent) metersToTap = MercatorBounds::DistanceOnEarth(*position, tapPoint); } - alohalytics::TStringMap kv = {{"longTap", tapInfo.m_isLong ? "1" : "0"}, - {"title", info.GetTitle()}, - {"bookmark", info.IsBookmark() ? "1" : "0"}, + alohalytics::TStringMap kv = {{"longTap", buildInfo.m_isLongTap ? "1" : "0"}, + {"title", m_currentPlacePageInfo->GetTitle()}, + {"bookmark", m_currentPlacePageInfo->IsBookmark() ? "1" : "0"}, {"meters", strings::to_string_dac(metersToTap, 0)}}; - if (info.IsFeature()) - kv["types"] = DebugPrint(info.GetTypes()); + if (m_currentPlacePageInfo->IsFeature()) + kv["types"] = DebugPrint(m_currentPlacePageInfo->GetTypes()); - if (info.GetSponsoredType() == SponsoredType::Holiday) + if (m_currentPlacePageInfo->GetSponsoredType() == SponsoredType::Holiday) { kv["holiday"] = "1"; - auto const & mwmInfo = info.GetID().m_mwmId.GetInfo(); + auto const & mwmInfo = m_currentPlacePageInfo->GetID().m_mwmId.GetInfo(); if (mwmInfo) kv["mwmVersion"] = strings::to_string(mwmInfo->GetVersion()); } - else if (info.GetSponsoredType() == SponsoredType::Partner) + else if (m_currentPlacePageInfo->GetSponsoredType() == SponsoredType::Partner) { - if (!info.GetPartnerName().empty()) - kv["partner"] = info.GetPartnerName(); + if (!m_currentPlacePageInfo->GetPartnerName().empty()) + kv["partner"] = m_currentPlacePageInfo->GetPartnerName(); } - if (info.IsRoadType()) - kv["road_warning"] = DebugPrint(info.GetRoadType()); + if (m_currentPlacePageInfo->IsRoadType()) + kv["road_warning"] = DebugPrint(m_currentPlacePageInfo->GetRoadType()); // Older version of statistics used "$GetUserMark" event. alohalytics::Stats::Instance().LogEvent("$SelectMapObject", kv, alohalytics::Location::FromLatLon(ll.m_lat, ll.m_lon)); // Send realtime statistics about bookmark selection. - if (info.IsBookmark()) + if (m_currentPlacePageInfo->IsBookmark()) { - auto const serverId = m_bmManager->GetCategoryServerId(info.GetBookmarkCategoryId()); + auto const categoryId = m_currentPlacePageInfo->GetBookmarkCategoryId(); + auto const serverId = m_bmManager->GetCategoryServerId(categoryId); if (!serverId.empty()) { - auto const accessRules = m_bmManager->GetCategoryData(info.GetBookmarkCategoryId()).m_accessRules; + auto const accessRules = m_bmManager->GetCategoryData(categoryId).m_accessRules; if (BookmarkManager::IsGuide(accessRules)) { alohalytics::TStringMap params = {{"server_id", serverId}}; @@ -2547,17 +2540,14 @@ void Framework::OnTapEvent(TapEvent const & tapEvent) } } - if (info.GetSponsoredType() == SponsoredType::Booking) + if (m_currentPlacePageInfo->GetSponsoredType() == SponsoredType::Booking) { GetPlatform().GetMarketingService().SendPushWooshTag(marketing::kBookHotelOnBookingComDiscovered); GetPlatform().GetMarketingService().SendMarketingEvent(marketing::kPlacepageHotelBook, {{"provider", "booking.com"}}); } } - - SetPlacePageLocation(info); - - ActivateMapSelection(true, selection, tapEvent.m_source, info); + ActivateMapSelection(m_currentPlacePageInfo); } else { @@ -2604,105 +2594,150 @@ FeatureID Framework::FindBuildingAtPoint(m2::PointD const & mercator) const return featureId; } -df::SelectionShape::ESelectedObject Framework::OnTapEventImpl(TapEvent const & tapEvent, - place_page::Info & outInfo) +boost::optional Framework::BuildPlacePageInfo(place_page::BuildInfo const & buildInfo) { + place_page::Info outInfo; if (m_drapeEngine == nullptr) - return df::SelectionShape::OBJECT_EMPTY; + return {}; - auto const & tapInfo = tapEvent.m_info; + outInfo.SetBuildInfo(buildInfo); - if (tapInfo.m_isMyPositionTapped) + if (buildInfo.m_isMyPosition) { - FillMyPositionInfo(outInfo, tapInfo); - return df::SelectionShape::OBJECT_MY_POSITION; + outInfo.SetSelectedObject(df::SelectionShape::OBJECT_MY_POSITION); + FillMyPositionInfo(outInfo, buildInfo); + SetPlacePageLocation(outInfo); + return outInfo; } if (m_purchase && !m_purchase->IsSubscriptionActive(SubscriptionType::RemoveAds)) outInfo.SetAdsEngine(m_adsEngine.get()); - UserMark const * mark = FindUserMarkInTapPosition(tapInfo); - if (mark != nullptr) + if (buildInfo.IsUserMarkMatchingEnabled()) { - switch (mark->GetMarkType()) + UserMark const * mark = FindUserMarkInTapPosition(buildInfo); + if (mark != nullptr) { - case UserMark::Type::API: - FillApiMarkInfo(*static_cast(mark), outInfo); - break; - case UserMark::Type::BOOKMARK: - FillBookmarkInfo(*static_cast(mark), outInfo); - break; - case UserMark::Type::SEARCH: - FillSearchResultInfo(*static_cast(mark), outInfo); - break; - case UserMark::Type::ROUTING: - FillRouteMarkInfo(*static_cast(mark), outInfo); - break; - case UserMark::Type::ROAD_WARNING: - FillRoadTypeMarkInfo(*static_cast(mark), outInfo); - break; - default: - ASSERT(false, ("FindNearestUserMark returned invalid mark.")); + outInfo.SetSelectedObject(df::SelectionShape::OBJECT_USER_MARK); + switch (mark->GetMarkType()) + { + case UserMark::Type::API: + FillApiMarkInfo(*static_cast(mark), outInfo); + break; + case UserMark::Type::BOOKMARK: + FillBookmarkInfo(*static_cast(mark), outInfo); + break; + case UserMark::Type::SEARCH: + FillSearchResultInfo(*static_cast(mark), outInfo); + break; + case UserMark::Type::ROUTING: + FillRouteMarkInfo(*static_cast(mark), outInfo); + break; + case UserMark::Type::ROAD_WARNING: + FillRoadTypeMarkInfo(*static_cast(mark), outInfo); + break; + default: + ASSERT(false, ("FindNearestUserMark returned invalid mark.")); + } + SetPlacePageLocation(outInfo); + + utils::RegisterEyeEventIfPossible(eye::MapObject::Event::Type::Open, GetCurrentPosition(), + outInfo); + return outInfo; } + } + + if (!buildInfo.m_postcode.empty()) + { + outInfo.SetSelectedObject(df::SelectionShape::OBJECT_POI); + FillPostcodeInfo(buildInfo.m_postcode, buildInfo.m_mercator, outInfo); + GetBookmarkManager().SelectionMark().SetPtOrg(outInfo.GetMercator()); + SetPlacePageLocation(outInfo); utils::RegisterEyeEventIfPossible(eye::MapObject::Event::Type::Open, GetCurrentPosition(), outInfo); - return df::SelectionShape::OBJECT_USER_MARK; + return outInfo; } - FeatureID featureTapped = tapInfo.m_featureTapped; - if (!featureTapped.IsValid()) - featureTapped = FindBuildingAtPoint(tapInfo.m_mercator); + FeatureID selectedFeature = buildInfo.m_featureId; + auto const isFeatureMatchingEnabled = buildInfo.IsFeatureMatchingEnabled(); + if (isFeatureMatchingEnabled && !selectedFeature.IsValid()) + selectedFeature = FindBuildingAtPoint(buildInfo.m_mercator); bool showMapSelection = false; - if (tapInfo.m_isLong || tapEvent.m_source == TapEvent::Source::Search) + if (buildInfo.m_isLongTap || buildInfo.m_source != place_page::BuildInfo::Source::User) { - FillPointInfo(outInfo, tapInfo.m_mercator); - if (!outInfo.IsFeature() && featureTapped.IsValid()) - FillFeatureInfo(featureTapped, outInfo); + if (isFeatureMatchingEnabled) + { + FillPointInfo(outInfo, buildInfo.m_mercator, {}); + if (!outInfo.IsFeature() && selectedFeature.IsValid()) + FillFeatureInfo(selectedFeature, outInfo); + } + else + { + FillNotMatchedPlaceInfo(outInfo, buildInfo.m_mercator, {}); + } showMapSelection = true; } - else if (featureTapped.IsValid()) + else if (selectedFeature.IsValid()) { - FillFeatureInfo(featureTapped, outInfo); + FillFeatureInfo(selectedFeature, outInfo); showMapSelection = true; } if (showMapSelection) { + outInfo.SetSelectedObject(df::SelectionShape::OBJECT_POI); GetBookmarkManager().SelectionMark().SetPtOrg(outInfo.GetMercator()); + SetPlacePageLocation(outInfo); utils::RegisterEyeEventIfPossible(eye::MapObject::Event::Type::Open, GetCurrentPosition(), outInfo); - - return df::SelectionShape::OBJECT_POI; + return outInfo; } - return df::SelectionShape::OBJECT_EMPTY; + return {}; } -UserMark const * Framework::FindUserMarkInTapPosition(df::TapInfo const & tapInfo) const +void Framework::UpdatePlacePageInfoForCurrentSelection(boost::optional const & overrideInfo) { + if (!m_currentPlacePageInfo) + return; + + m_currentPlacePageInfo = BuildPlacePageInfo(overrideInfo.has_value() ? *overrideInfo : + m_currentPlacePageInfo->GetBuildInfo()); + if (m_currentPlacePageInfo && m_onPlacePageUpdate) + m_onPlacePageUpdate(); +} + +UserMark const * Framework::FindUserMarkInTapPosition(place_page::BuildInfo const & buildInfo) const +{ + if (buildInfo.m_userMarkId != kml::kInvalidMarkId) + { + auto mark = GetBookmarkManager().GetUserMark(buildInfo.m_userMarkId); + if (mark != nullptr) + return mark; + } + UserMark const * mark = GetBookmarkManager().FindNearestUserMark( - [this, &tapInfo](UserMark::Type type) + [this, &buildInfo](UserMark::Type type) { + double constexpr kEps = 1e-7; + if (buildInfo.m_source != place_page::BuildInfo::Source::User) + return df::TapInfo::GetPreciseSearchRect(buildInfo.m_mercator, kEps); + if (type == UserMark::Type::BOOKMARK) - return tapInfo.GetBookmarkSearchRect(m_currentModelView); + return df::TapInfo::GetBookmarkSearchRect(buildInfo.m_mercator, m_currentModelView); + if (type == UserMark::Type::ROUTING || type == UserMark::Type::ROAD_WARNING) - return tapInfo.GetRoutingPointSearchRect(m_currentModelView); - return tapInfo.GetDefaultSearchRect(m_currentModelView); + return df::TapInfo::GetRoutingPointSearchRect(buildInfo.m_mercator, m_currentModelView); + + return df::TapInfo::GetDefaultSearchRect(buildInfo.m_mercator, m_currentModelView); }, [](UserMark::Type) { return false; }); return mark; } -unique_ptr Framework::MakeTapEvent(m2::PointD const & center, - FeatureID const & fid, - TapEvent::Source source) const -{ - return make_unique(df::TapInfo{center, false, false, fid}, source); -} - void Framework::PredictLocation(double & lat, double & lon, double accuracy, double bearing, double speed, double elapsedSeconds) { @@ -2922,11 +2957,14 @@ void Framework::SaveTransitSchemeEnabled(bool enabled) settings::Set(kTransitSchemeEnabledKey, enabled); } -void Framework::EnableChoosePositionMode(bool enable, bool enableBounds, bool applyPosition, m2::PointD const & position) +void Framework::EnableChoosePositionMode(bool enable, bool enableBounds, bool applyPosition, + m2::PointD const & position) { if (m_drapeEngine != nullptr) - m_drapeEngine->EnableChoosePositionMode(enable, enableBounds ? GetSelectedFeatureTriangles() : vector(), - applyPosition, position); + { + m_drapeEngine->EnableChoosePositionMode(enable, + enableBounds ? GetSelectedFeatureTriangles() : vector(), applyPosition, position); + } } discovery::Manager::Params Framework::GetDiscoveryParams( @@ -2957,11 +2995,11 @@ m2::PointD Framework::GetDiscoveryViewportCenter() const vector Framework::GetSelectedFeatureTriangles() const { vector triangles; - if (!m_selectedFeature.IsValid()) + if (!m_currentPlacePageInfo || !m_currentPlacePageInfo->GetID().IsValid()) return triangles; - FeaturesLoaderGuard const guard(m_featuresFetcher.GetDataSource(), m_selectedFeature.m_mwmId); - auto ft = guard.GetFeatureByIndex(m_selectedFeature.m_index); + FeaturesLoaderGuard const guard(m_featuresFetcher.GetDataSource(), m_currentPlacePageInfo->GetID().m_mwmId); + auto ft = guard.GetFeatureByIndex(m_currentPlacePageInfo->GetID().m_index); if (!ft) return triangles; @@ -2973,7 +3011,6 @@ vector Framework::GetSelectedFeatureTriangles() const triangles.emplace_back(p1, p2, p3); }, scales::GetUpperScale()); } - m_selectedFeature = FeatureID(); return triangles; } @@ -3362,12 +3399,6 @@ bool Framework::GetEditableMapObject(FeatureID const & fid, osm::EditableMapObje osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject emo) { - if (!m_lastTapEvent) - { - // Automatically select newly created objects. - m_lastTapEvent = MakeTapEvent(emo.GetMercator(), emo.GetID(), TapEvent::Source::Other); - } - auto & editor = osm::Editor::Instance(); ms::LatLon issueLatLon; @@ -3492,14 +3523,25 @@ osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject em emo.RemoveNeedlessNames(); - return osm::Editor::Instance().SaveEditedFeature(emo); + auto const result = osm::Editor::Instance().SaveEditedFeature(emo); + + // Automatically select newly created objects. + if (!m_currentPlacePageInfo) + { + place_page::BuildInfo info; + info.m_mercator = emo.GetMercator(); + info.m_featureId = emo.GetID(); + m_currentPlacePageInfo = BuildPlacePageInfo(info); + ActivateMapSelection(m_currentPlacePageInfo); + } + + return result; } -void Framework::DeleteFeature(FeatureID const & fid) const +void Framework::DeleteFeature(FeatureID const & fid) { osm::Editor::Instance().DeleteFeature(fid); - if (m_selectedFeature == fid) - m_selectedFeature = FeatureID(); + UpdatePlacePageInfoForCurrentSelection(); } osm::NewFeatureCategories Framework::GetEditorCategories() const @@ -3509,8 +3551,6 @@ osm::NewFeatureCategories Framework::GetEditorCategories() const bool Framework::RollBackChanges(FeatureID const & fid) { - if (m_selectedFeature == fid) // reset selected feature since it becomes invalid after rollback - m_selectedFeature = FeatureID(); auto & editor = osm::Editor::Instance(); auto const status = editor.GetFeatureStatus(fid); auto const rolledBack = editor.RollBackChanges(fid); @@ -4163,8 +4203,7 @@ double Framework::GetLastBackgroundTime() const return m_startBackgroundTime; } -bool Framework::MakePlacePageInfo(NotificationCandidate const & notification, - place_page::Info & info) const +bool Framework::MakePlacePageForNotification(NotificationCandidate const & notification) { if (notification.GetType() != NotificationCandidate::Type::UgcReview) return false; @@ -4173,14 +4212,19 @@ bool Framework::MakePlacePageInfo(NotificationCandidate const & notification, bool found = false; m_featuresFetcher.GetDataSource().ForEachInRect( - [this, &info, ¬ification, &found](FeatureType & ft) { - if (found || !feature::GetCenter(ft).EqualDxDy(notification.GetPos(), kMwmPointAccuracy)) + [this, ¬ification, &found](FeatureType & ft) { + auto const featureCenter = feature::GetCenter(ft); + if (found || !featureCenter.EqualDxDy(notification.GetPos(), kMwmPointAccuracy)) return; auto const foundMapObject = utils::MakeEyeMapObject(ft); if (!foundMapObject.IsEmpty() && notification.IsSameMapObject(foundMapObject)) { - FillInfoFromFeatureType(ft, info); + place_page::BuildInfo buildInfo; + buildInfo.m_mercator = featureCenter; + buildInfo.m_featureId = ft.GetID(); + m_currentPlacePageInfo = BuildPlacePageInfo(buildInfo); + ActivateMapSelection(m_currentPlacePageInfo); found = true; } }, diff --git a/map/framework.hpp b/map/framework.hpp index 8a10746871..20ffd08805 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -393,33 +393,13 @@ public: double GetMinDistanceBetweenResults() const override; private: - struct TapEvent - { - enum class Source - { - User, - Search, - Other - }; - - TapEvent(df::TapInfo const & info, Source source) - : m_info(info) - , m_source(source) - {} - - df::TapInfo const m_info; - Source const m_source; - }; - - void ActivateMapSelection(bool needAnimation, df::SelectionShape::ESelectedObject selectionType, - TapEvent::Source tapSource, place_page::Info const & info, - bool isGeometrySelectionAllowed = false); + void ActivateMapSelection(boost::optional const & info); void InvalidateUserMarks(); public: void DeactivateMapSelection(bool notifyUI); /// Used to "refresh" UI in some cases (e.g. feature editing). - void UpdatePlacePageInfoForCurrentSelection(); + void UpdatePlacePageInfoForCurrentSelection(boost::optional const & overrideInfo = {}); void DrawMwmBorder(std::string const & mwmName, std::vector const & regions, bool withVertices); @@ -427,16 +407,19 @@ public: struct PlacePageEvent { /// Called to notify UI that object on a map was selected (UI should show Place Page, for example). - using OnOpen = std::function; + using OnOpen = std::function; /// Called to notify UI that object on a map was deselected (UI should hide Place Page). /// If switchFullScreenMode is true, ui can [optionally] enter or exit full screen mode. - using OnClose = std::function; - using OnUpdate = std::function; + using OnClose = std::function; + using OnUpdate = std::function; }; - void SetPlacePageListenners(PlacePageEvent::OnOpen const & onOpen, - PlacePageEvent::OnClose const & onClose, - PlacePageEvent::OnUpdate const & onUpdate); + void SetPlacePageListeners(PlacePageEvent::OnOpen const & onOpen, + PlacePageEvent::OnClose const & onClose, + PlacePageEvent::OnUpdate const & onUpdate); + bool IsPlacePageOpened() const { return m_currentPlacePageInfo.has_value(); } + place_page::Info const & GetCurrentPlacePageInfo() const; + place_page::Info & GetCurrentPlacePageInfo(); void InvalidateRendering(); void EnableDebugRectRendering(bool enabled); @@ -460,16 +443,12 @@ public: std::vector const & features); private: - std::unique_ptr m_lastTapEvent; + boost::optional m_currentPlacePageInfo; bool m_isViewportInitialized = false; - void OnTapEvent(TapEvent const & tapEvent); - /// outInfo is valid only if return value is not df::SelectionShape::OBJECT_EMPTY. - df::SelectionShape::ESelectedObject OnTapEventImpl(TapEvent const & tapEvent, - place_page::Info & outInfo); - std::unique_ptr MakeTapEvent(m2::PointD const & center, FeatureID const & fid, - TapEvent::Source source) const; - UserMark const * FindUserMarkInTapPosition(df::TapInfo const & tapInfo) const; + void OnTapEvent(place_page::BuildInfo const & buildInfo); + boost::optional BuildPlacePageInfo(place_page::BuildInfo const & buildInfo); + UserMark const * FindUserMarkInTapPosition(place_page::BuildInfo const & buildInfo) const; FeatureID FindBuildingAtPoint(m2::PointD const & mercator) const; void UpdateMinBuildingsTapZoom(); @@ -480,9 +459,6 @@ private: PlacePageEvent::OnClose m_onPlacePageClose; PlacePageEvent::OnUpdate m_onPlacePageUpdate; - /// Here we store last selected feature to get its polygons in case of adding organization. - mutable FeatureID m_selectedFeature; - private: std::vector GetSelectedFeatureTriangles() const; @@ -728,22 +704,26 @@ private: void FillFeatureInfo(FeatureID const & fid, place_page::Info & info) const; /// @param customTitle, if not empty, overrides any other calculated name. void FillPointInfo(place_page::Info & info, m2::PointD const & mercator, - std::string const & customTitle = {}, FeatureMatcher && matcher = nullptr) const; + std::string const & customTitle = {}, + FeatureMatcher && matcher = nullptr) const; + void FillNotMatchedPlaceInfo(place_page::Info & info, m2::PointD const & mercator, + std::string const & customTitle = {}) const; void FillPostcodeInfo(std::string const & postcode, m2::PointD const & mercator, place_page::Info & info) const; void FillInfoFromFeatureType(FeatureType & ft, place_page::Info & info) const; void FillApiMarkInfo(ApiMarkPoint const & api, place_page::Info & info) const; void FillSearchResultInfo(SearchMarkPoint const & smp, place_page::Info & info) const; - void FillMyPositionInfo(place_page::Info & info, df::TapInfo const & tapInfo) const; + void FillMyPositionInfo(place_page::Info & info, place_page::BuildInfo const & buildInfo) const; void FillRouteMarkInfo(RouteMarkPoint const & rmp, place_page::Info & info) const; void FillRoadTypeMarkInfo(RoadWarningMark const & roadTypeMark, place_page::Info & info) const; void FillPointInfoForBookmark(Bookmark const & bmk, place_page::Info & info) const; + void FillBookmarkInfo(Bookmark const & bmk, place_page::Info & info) const; + void SetPlacePageLocation(place_page::Info & info); + void FillLocalExperts(FeatureType & ft, place_page::Info & info) const; + void FillDescription(FeatureType & ft, place_page::Info & info) const; public: - void FillBookmarkInfo(Bookmark const & bmk, place_page::Info & info) const; - void ResetBookmarkInfo(Bookmark const & bmk, place_page::Info & info) const; - search::ReverseGeocoder::Address GetAddressAtPoint(m2::PointD const & pt) const; /// Get "best for the user" feature at given point even if it's invisible on the screen. @@ -864,7 +844,7 @@ public: /// @returns false if feature is invalid or can't be edited. bool GetEditableMapObject(FeatureID const & fid, osm::EditableMapObject & emo) const; osm::Editor::SaveResult SaveEditedMapObject(osm::EditableMapObject emo); - void DeleteFeature(FeatureID const & fid) const; + void DeleteFeature(FeatureID const & fid); osm::NewFeatureCategories GetEditorCategories() const; bool RollBackChanges(FeatureID const & fid); void CreateNote(osm::MapObject const & mapObject, osm::Editor::NoteProblemType const type, @@ -904,11 +884,7 @@ private: void InitCityFinder(); void InitTaxiEngine(); - void SetPlacePageLocation(place_page::Info & info); - void FillLocalExperts(FeatureType & ft, place_page::Info & info) const; - - void FillDescription(FeatureType & ft, place_page::Info & info) const; public: // UGC. @@ -948,8 +924,7 @@ public: bool HaveTransit(m2::PointD const & pt) const override; double GetLastBackgroundTime() const override; - bool MakePlacePageInfo(notifications::NotificationCandidate const & notification, - place_page::Info & info) const; + bool MakePlacePageForNotification(notifications::NotificationCandidate const & notification); power_management::PowerManager & GetPowerManager() { return m_powerManager; } diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp index 0ef7de602e..3d13fcb495 100644 --- a/map/place_page_info.hpp +++ b/map/place_page_info.hpp @@ -8,6 +8,9 @@ #include "map/routing_mark.hpp" +#include "drape_frontend/frontend_renderer.hpp" +#include "drape_frontend/selection_shape.hpp" + #include "storage/storage_defines.hpp" #include "editor/osm_editor.hpp" @@ -73,6 +76,55 @@ enum class OpeningMode auto constexpr kIncorrectRating = kInvalidRatingValue; +struct BuildInfo +{ + enum class Source : uint8_t + { + User, + Search, + Other + }; + + enum class Match : uint8_t + { + Everything = 0, + FeatureOnly, + UserMarkOnly, + Nothing + }; + + BuildInfo() = default; + + explicit BuildInfo(df::TapInfo const & info) + : m_source(Source::User) + , m_mercator(info.m_mercator) + , m_isLongTap(info.m_isLong) + , m_isMyPosition(info.m_isMyPositionTapped) + , m_featureId(info.m_featureTapped) + {} + + bool IsFeatureMatchingEnabled() const + { + return m_match == Match::Everything || m_match == Match::FeatureOnly; + } + + bool IsUserMarkMatchingEnabled() const + { + return m_match == Match::Everything || m_match == Match::UserMarkOnly; + } + + Source m_source = Source::Other; + m2::PointD m_mercator; + bool m_isLongTap = false; + bool m_isMyPosition = false; + FeatureID m_featureId; + Match m_match = Match::Everything; + kml::MarkId m_userMarkId = kml::kInvalidMarkId; + bool m_isGeometrySelectionAllowed = false; + bool m_needAnimationOnSelection = true; + std::string m_postcode; +}; + class Info : public osm::MapObject { public: @@ -81,10 +133,13 @@ public: static char const * const kMountainSymbol; static char const * const kPricingSymbol; + void SetBuildInfo(place_page::BuildInfo const & info) { m_buildInfo = info; } + place_page::BuildInfo const & GetBuildInfo() const { return m_buildInfo; } + /// Place traits bool IsFeature() const { return m_featureID.IsValid(); } bool IsBookmark() const { return m_markGroupId != kml::kInvalidMarkGroupId && m_markId != kml::kInvalidMarkId; } - bool IsMyPosition() const { return m_isMyPosition; } + bool IsMyPosition() const { return m_selectedObject == df::SelectionShape::ESelectedObject::OBJECT_MY_POSITION; } bool IsRoutePoint() const { return m_isRoutePoint; } bool IsRoadType() const { return m_roadType != RoadWarningMarkType::Count; } @@ -129,7 +184,6 @@ public: void SetCustomNames(std::string const & title, std::string const & subtitle); void SetCustomNameWithCoordinates(m2::PointD const & mercator, std::string const & name); void SetAddress(std::string const & address) { m_address = address; } - void SetIsMyPosition() { m_isMyPosition = true; } void SetCanEditOrAdd(bool canEditOrAdd) { m_canEditOrAdd = canEditOrAdd; } void SetLocalizedWifiString(std::string const & str) { m_localizedWifiString = str; } @@ -245,6 +299,9 @@ public: uint8_t GetPopularity() const { return m_popularity; } std::string const & GetPrimaryFeatureName() const { return m_primaryFeatureName; }; + void SetSelectedObject(df::SelectionShape::ESelectedObject selectedObject) { m_selectedObject = selectedObject; } + df::SelectionShape::ESelectedObject GetSelectedObject() const { return m_selectedObject; } + private: std::string FormatSubtitle(bool withType) const; void GetPrefferedNames(std::string & primaryName, std::string & secondaryName) const; @@ -253,6 +310,8 @@ private: std::string FormatStars() const; void SetTitlesForBookmark(); + place_page::BuildInfo m_buildInfo; + /// UI std::string m_uiTitle; std::string m_uiSubtitle; @@ -297,8 +356,6 @@ private: /// Road type RoadWarningMarkType m_roadType = RoadWarningMarkType::Count; - bool m_isMyPosition = false; - /// Editor /// True if editing of a selected point is allowed by basic logic. /// See initialization in framework. @@ -343,6 +400,8 @@ private: std::string m_primaryFeatureName; OpeningMode m_openingMode = OpeningMode::Preview; + + df::SelectionShape::ESelectedObject m_selectedObject = df::SelectionShape::ESelectedObject::OBJECT_EMPTY; }; namespace rating diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index ce2b913326..0bd759932e 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -59,8 +59,8 @@ DrawWidget::DrawWidget(Framework & framework, bool apiOpenGLES3, std::unique_ptr , m_rubberBand(nullptr) , m_emulatingLocation(false) { - m_framework.SetPlacePageListenners([this](place_page::Info const & info) { ShowPlacePage(info); }, - {} /* onClose */, {} /* onUpdate */); + m_framework.SetPlacePageListeners([this]() { ShowPlacePage(); }, + {} /* onClose */, {} /* onUpdate */); m_framework.GetRoutingManager().SetRouteBuildingListener( [](routing::RouterResultCode, storage::CountriesSet const &) {}); @@ -611,8 +611,9 @@ void DrawWidget::OnRouteRecommendation(RoutingManager::Recommendation recommenda } } -void DrawWidget::ShowPlacePage(place_page::Info const & info) +void DrawWidget::ShowPlacePage() { + place_page::Info const & info = m_framework.GetCurrentPlacePageInfo(); search::ReverseGeocoder::Address address; if (info.IsFeature()) { diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp index 8c4fa86466..74f810e87f 100644 --- a/qt/draw_widget.hpp +++ b/qt/draw_widget.hpp @@ -107,7 +107,7 @@ private: void SubmitFakeLocationPoint(m2::PointD const & pt); void SubmitRoutingPoint(m2::PointD const & pt); void SubmitBookmark(m2::PointD const & pt); - void ShowPlacePage(place_page::Info const & info); + void ShowPlacePage(); void UpdateCountryStatus(storage::CountryId const & countryId); diff --git a/search/search_quality/assessment_tool/main_view.cpp b/search/search_quality/assessment_tool/main_view.cpp index 57acceefaa..3c684c1482 100644 --- a/search/search_quality/assessment_tool/main_view.cpp +++ b/search/search_quality/assessment_tool/main_view.cpp @@ -58,8 +58,9 @@ MainView::MainView(Framework & framework) : m_framework(framework) InitDocks(); InitMenuBar(); - m_framework.SetPlacePageListenners( - [this](place_page::Info const & info) { + m_framework.SetPlacePageListeners( + [this]() { + auto const & info = m_framework.GetCurrentPlacePageInfo(); auto const & selectedFeature = info.GetID(); if (!selectedFeature.IsValid()) return;