diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index 3f57c4a133..8745e69055 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -41,6 +41,7 @@ jmethodID g_onCustomPropertiesReceivedMethod; jmethodID g_onUploadStartedMethod; jmethodID g_onUploadFinishedMethod; jmethodID g_onElevationActivePointChangedMethod; +jmethodID g_onElevationCurrentPositionChangedMethod; jclass g_bookmarkCategoryClass; jmethodID g_bookmarkCategoryConstructor; jclass g_catalogTagClass; @@ -186,8 +187,19 @@ void PrepareClassRefs(JNIEnv * env) jni::GetConstructorID(env, g_catalogCustomPropertyClass, "(Ljava/lang/String;Ljava/lang/String;Z" "[Lcom/mapswithme/maps/bookmarks/data/CatalogCustomPropertyOption;)V"); + g_onElevationCurrentPositionChangedMethod = + jni::GetMethodID(env, bookmarkManagerInstance, "onElevationCurPositionChanged", "()V"); g_onElevationActivePointChangedMethod = - jni::GetMethodID(env, bookmarkManagerInstance, "onElevationActivePointChanged", "()V"); + jni::GetMethodID(env, bookmarkManagerInstance, "onElevationActivePointChanged", "()V"); +} + +void OnElevationCurPositionChanged(JNIEnv * env) +{ + ASSERT(g_bookmarkManagerClass, ()); + jobject bookmarkManagerInstance = + env->GetStaticObjectField(g_bookmarkManagerClass, g_bookmarkManagerInstanceField); + env->CallVoidMethod(bookmarkManagerInstance, g_onElevationCurrentPositionChangedMethod); + jni::HandleJavaException(env); } void OnElevationActivePointChanged(JNIEnv * env) @@ -1396,6 +1408,29 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetBookmarkAddress return jni::ToJavaString(env, address); } +JNIEXPORT jdouble JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeGetElevationCurPositionDistance( + JNIEnv * env, jclass clazz, jlong trackId) +{ + auto & bm = frm()->GetBookmarkManager(); + return static_cast(bm.GetElevationMyPosition(static_cast(trackId))); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeSetElevationCurPositionChangedListener( + JNIEnv * env, jclass clazz) +{ + frm()->GetBookmarkManager().SetElevationMyPositionChangedCallback( + std::bind(&OnElevationCurPositionChanged, env)); +} + +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeRemoveElevationCurPositionChangedListener( + JNIEnv * env, jclass) +{ + frm()->GetBookmarkManager().SetElevationMyPositionChangedCallback(nullptr); +} + JNIEXPORT void JNICALL Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeSetElevationActivePoint( JNIEnv *env, jclass clazz, jlong trackId, jdouble distanceInMeters) diff --git a/android/src/com/mapswithme/maps/ChartController.java b/android/src/com/mapswithme/maps/ChartController.java index 05a5bdb869..409b55623c 100644 --- a/android/src/com/mapswithme/maps/ChartController.java +++ b/android/src/com/mapswithme/maps/ChartController.java @@ -28,6 +28,8 @@ import com.mapswithme.maps.widget.placepage.FloatingMarkerView; import com.mapswithme.util.StringUtils; import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.Utils; +import com.mapswithme.util.log.Logger; +import com.mapswithme.util.log.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; @@ -43,6 +45,10 @@ public class ChartController implements OnChartValueSelectedListener, Initializa private static final int CHART_ANIMATION_DURATION = 1500; private static final int CHART_FILL_ALPHA = (int) (0.12 * 255); private static final float CUBIC_INTENSITY = 0.2f; + private static final int CURRENT_POSITION_OUT_OF_TRACK = -1; + + private static final String TAG = ChartController.class.getName(); + private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.LOCATION); @SuppressWarnings("NullableProblems") @NonNull @@ -62,6 +68,7 @@ public class ChartController implements OnChartValueSelectedListener, Initializa @NonNull private final Context mContext; private long mTrackId = Utils.INVALID_ID; + private boolean mCurrentPositionOutOfTrack; public ChartController(@NonNull Context context) { @@ -101,12 +108,14 @@ public class ChartController implements OnChartValueSelectedListener, Initializa Legend l = mChart.getLegend(); l.setEnabled(false); initAxises(); + BookmarkManager.INSTANCE.setElevationCurPositionChangedListener(this::onCurrentPositionChanged); } @Override public void destroy() { BookmarkManager.INSTANCE.setElevationActivePointChangedListener(null); + BookmarkManager.INSTANCE.setElevationCurPositionChangedListener(null); } private void highlightChartCurrentLocation() @@ -170,23 +179,32 @@ public class ChartController implements OnChartValueSelectedListener, Initializa data.setDrawValues(false); mChart.setData(data); - highlightChartCurrentLocation(); + if (!mCurrentPositionOutOfTrack) + highlightChartCurrentLocation(); + mChart.animateX(CHART_ANIMATION_DURATION); mMinAltitude.setText(StringUtils.nativeFormatDistance(info.getMinAltitude())); mMaxAltitude.setText(StringUtils.nativeFormatDistance(info.getMaxAltitude())); - highlightActivePoint(); + highlightActivePointManually(); } @Override - public void onValueSelected(Entry e, Highlight h) - { + public void onValueSelected(Entry e, Highlight h) { mFloatingMarkerView.updateOffsets(e, h); Highlight curPos = getCurrentPosHighlight(); - mChart.highlightValues(Arrays.asList(curPos, h), - Arrays.asList(mCurrentLocationMarkerView, mFloatingMarkerView)); + mChart.highlightValues( + + mCurrentPositionOutOfTrack + ? Collections.singletonList(h) + : Arrays.asList(curPos, h), + + mCurrentPositionOutOfTrack + ? Collections.singletonList(mFloatingMarkerView) + : Arrays.asList(mCurrentLocationMarkerView, mFloatingMarkerView)); + if (mTrackId == Utils.INVALID_ID) return; @@ -196,34 +214,48 @@ public class ChartController implements OnChartValueSelectedListener, Initializa @NonNull private Highlight getCurrentPosHighlight() { - LineData data = mChart.getData(); - final Entry entryForIndex = data.getDataSetByIndex(0).getEntryForIndex(5); - return new Highlight(entryForIndex.getX(), 0, 5); + double activeX = BookmarkManager.INSTANCE.getElevationCurPositionDistance(mTrackId); + return new Highlight((float) activeX, 0f, 0); } @Override public void onNothingSelected() { + if (mCurrentPositionOutOfTrack) + return; + highlightChartCurrentLocation(); } + private void onCurrentPositionChanged() + { + if (mTrackId == Utils.INVALID_ID) + return; + + double distance = BookmarkManager.INSTANCE.getElevationCurPositionDistance(mTrackId); + mCurrentPositionOutOfTrack = distance == CURRENT_POSITION_OUT_OF_TRACK; + highlightActivePointManually(); + if (mCurrentPositionOutOfTrack) LOGGER.d(TAG, "mCurrentPositionOutOfTrack = true"); + } + @Override public void onElevationActivePointChanged() { if (mTrackId == Utils.INVALID_ID) return; - highlightActivePoint(); + highlightActivePointManually(); } - private void highlightActivePoint() + private void highlightActivePointManually() { - double activeX = BookmarkManager.INSTANCE.getElevationActivePointDistance(mTrackId); - Highlight highlight = new Highlight((float) activeX, 0, 0); - mFloatingMarkerView.updateOffsets(new Entry((float) activeX, 0f), highlight); - Highlight curPos = getCurrentPosHighlight(); + Highlight highlight = getActivePoint(); + mChart.highlightValue(highlight, true); + } - mChart.highlightValues(Arrays.asList(curPos, highlight), - Arrays.asList(mCurrentLocationMarkerView, mFloatingMarkerView)); + @NonNull + private Highlight getActivePoint() { + double activeX = BookmarkManager.INSTANCE.getElevationActivePointDistance(mTrackId); + return new Highlight((float) activeX, 0f, 0); } } diff --git a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java index 3f3ab50522..6db2acd7aa 100644 --- a/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java +++ b/android/src/com/mapswithme/maps/bookmarks/data/BookmarkManager.java @@ -98,6 +98,9 @@ public enum BookmarkManager @NonNull private final List mInvalidCategoriesListeners = new ArrayList<>(); + @Nullable + private OnElevationCurrentPositionChangedListener mOnElevationCurrentPositionChangedListener; + @Nullable private OnElevationActivePointChangedListener mOnElevationActivePointChangedListener; @@ -434,6 +437,25 @@ public enum BookmarkManager listener.onCheckInvalidCategories(hasInvalidCategories); } + // Called from JNI. + @SuppressWarnings("unused") + @MainThread + public void onElevationCurPositionChanged() + { + if (mOnElevationCurrentPositionChangedListener != null) + mOnElevationCurrentPositionChangedListener.onCurrentPositionChanged(); + } + + public void setElevationCurPositionChangedListener(@Nullable OnElevationCurrentPositionChangedListener listener) + { + if (listener != null) + nativeSetElevationCurPositionChangedListener(); + else + nativeRemoveElevationCurPositionChangedListener(); + + mOnElevationCurrentPositionChangedListener = listener; + } + // Called from JNI. @SuppressWarnings("unused") @MainThread @@ -946,6 +968,11 @@ public enum BookmarkManager } } + public double getElevationCurPositionDistance(long trackId) + { + return nativeGetElevationCurPositionDistance(trackId); + } + public void setElevationActivePoint(long trackId, double distance) { nativeSetElevationActivePoint(trackId, distance); @@ -1161,6 +1188,12 @@ public enum BookmarkManager @NonNull private static native String nativeGetBookmarkAddress(@IntRange(from = 0) long bookmarkId); + private static native double nativeGetElevationCurPositionDistance(long trackId); + + private static native void nativeSetElevationCurPositionChangedListener(); + + public static native void nativeRemoveElevationCurPositionChangedListener(); + private static native void nativeSetElevationActivePoint(long trackId, double distanceInMeters); private static native double nativeGetElevationActivePointDistance(long trackId); diff --git a/android/src/com/mapswithme/maps/bookmarks/data/OnElevationCurrentPositionChangedListener.java b/android/src/com/mapswithme/maps/bookmarks/data/OnElevationCurrentPositionChangedListener.java new file mode 100644 index 0000000000..1d2bf093ec --- /dev/null +++ b/android/src/com/mapswithme/maps/bookmarks/data/OnElevationCurrentPositionChangedListener.java @@ -0,0 +1,6 @@ +package com.mapswithme.maps.bookmarks.data; + +public interface OnElevationCurrentPositionChangedListener +{ + void onCurrentPositionChanged(); +} diff --git a/android/src/com/mapswithme/maps/widget/placepage/FloatingMarkerView.java b/android/src/com/mapswithme/maps/widget/placepage/FloatingMarkerView.java index 1e52ded5bd..9fba2c94d7 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/FloatingMarkerView.java +++ b/android/src/com/mapswithme/maps/widget/placepage/FloatingMarkerView.java @@ -84,23 +84,37 @@ public class FloatingMarkerView extends MarkerView private boolean isInvertedOrder(@NonNull Highlight highlight) { - float x = highlight.getXPx(); + float x = highlight.getX(); float halfImg = Math.abs(mImage.getWidth()) / 2f; int wholeText = Math.abs(mInfoFloatingContainer.getWidth()); - return x + halfImg + wholeText >= getChartView().getContentRect().right; + float factor = calcHorizontalFactor(); + return x + (halfImg + wholeText ) * factor >= getChartView().getXChartMax(); + } + + private float calcHorizontalFactor() { + float delta = getChartView().getXChartMax() - getChartView().getXChartMin(); + return delta / getChartView().getContentRect().width(); + } + + private float convertContainerHeight() + { + float height = getChartView().getContentRect().height(); + float delta = getChartView().getYMax() - getChartView().getYMin(); + float factor = delta / height; + return factor * mSlidingContainer.getHeight(); } private void updateVertical(@NonNull Entry entry) { LayoutParams layoutParams = (LayoutParams) mTextContentContainer.getLayoutParams(); float posY = entry.getY(); - if (posY + mSlidingContainer.getHeight() / 2f >= getChartView().getYChartMax()) + if (posY + convertContainerHeight() / 2f >= getChartView().getYChartMax()) { layoutParams.addRule(ALIGN_PARENT_BOTTOM); layoutParams.removeRule(ALIGN_PARENT_TOP); layoutParams.removeRule(CENTER_VERTICAL); } - else if (posY - mSlidingContainer.getHeight() / 2f <= getChartView().getYChartMin()) + else if (posY - convertContainerHeight() / 2f <= getChartView().getYChartMin()) { layoutParams.addRule(ALIGN_PARENT_TOP); layoutParams.removeRule(ALIGN_PARENT_BOTTOM);