mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 04:53:36 +00:00
Implement Track Selection and elevation info display on PP
Signed-off-by: kavikhalique <kavikhalique3@gmail.com>
This commit is contained in:
committed by
Konstantin Pastbin
parent
ebb7c45d1a
commit
f1628c70bc
@@ -10,6 +10,8 @@ import androidx.core.content.ContextCompat;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import app.organicmaps.sdk.bookmarks.data.TrackStatistics;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.placepage.AxisValueFormatter;
|
||||
@@ -31,9 +33,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ChartController implements OnChartValueSelectedListener,
|
||||
BookmarkManager.OnElevationActivePointChangedListener,
|
||||
BookmarkManager.OnElevationCurrentPositionChangedListener
|
||||
public class ChartController implements OnChartValueSelectedListener
|
||||
{
|
||||
private static final int CHART_Y_LABEL_COUNT = 3;
|
||||
private static final int CHART_X_LABEL_COUNT = 6;
|
||||
@@ -42,6 +42,7 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
private static final int CHART_AXIS_GRANULARITY = 100;
|
||||
private static final float CUBIC_INTENSITY = 0.2f;
|
||||
private static final int CURRENT_POSITION_OUT_OF_TRACK = -1;
|
||||
private static final String ELEVATION_PROFILE_POINTS = "ELEVATION_PROFILE_POINTS";
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
@@ -62,6 +63,7 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
private final Context mContext;
|
||||
private long mTrackId = Utils.INVALID_ID;
|
||||
private boolean mCurrentPositionOutOfTrack = true;
|
||||
private boolean mInformSelectedActivePointToCore = true;
|
||||
|
||||
public ChartController(@NonNull Context context)
|
||||
{
|
||||
@@ -70,8 +72,6 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
|
||||
public void initialize(@NonNull View view)
|
||||
{
|
||||
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(this);
|
||||
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(this);
|
||||
final Resources resources = mContext.getResources();
|
||||
mChart = view.findViewById(R.id.elevation_profile_chart);
|
||||
|
||||
@@ -101,13 +101,6 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
initAxises();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void destroy()
|
||||
{
|
||||
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(null);
|
||||
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(null);
|
||||
}
|
||||
|
||||
private void highlightChartCurrentLocation()
|
||||
{
|
||||
mChart.highlightValues(Collections.singletonList(getCurrentPosHighlight()),
|
||||
@@ -142,15 +135,17 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
mChart.getAxisRight().setEnabled(false);
|
||||
}
|
||||
|
||||
public void setData(@NonNull ElevationInfo info)
|
||||
public void setData(Track track)
|
||||
{
|
||||
mTrackId = info.getId();
|
||||
mTrackId = track.getTrackId();
|
||||
ElevationInfo info = track.getElevationInfo();
|
||||
TrackStatistics stats = track.getTrackStatistics();
|
||||
List<Entry> values = new ArrayList<>();
|
||||
|
||||
for (ElevationInfo.Point point : info.getPoints())
|
||||
values.add(new Entry((float) point.getDistance(), point.getAltitude()));
|
||||
values.add(new Entry((float) point.getDistance(), point.getAltitude(), point));
|
||||
|
||||
LineDataSet set = new LineDataSet(values, "Elevation_profile_points");
|
||||
LineDataSet set = new LineDataSet(values, ELEVATION_PROFILE_POINTS);
|
||||
set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
|
||||
set.setCubicIntensity(CUBIC_INTENSITY);
|
||||
set.setDrawFilled(true);
|
||||
@@ -173,8 +168,8 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
mChart.setData(data);
|
||||
mChart.animateX(CHART_ANIMATION_DURATION);
|
||||
|
||||
mMinAltitude.setText(Framework.nativeFormatAltitude(info.getMinAltitude()));
|
||||
mMaxAltitude.setText(Framework.nativeFormatAltitude(info.getMaxAltitude()));
|
||||
mMinAltitude.setText(Framework.nativeFormatAltitude(stats.getMinElevation()));
|
||||
mMaxAltitude.setText(Framework.nativeFormatAltitude(stats.getMaxElevation()));
|
||||
|
||||
highlightActivePointManually();
|
||||
}
|
||||
@@ -192,7 +187,9 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
if (mTrackId == Utils.INVALID_ID)
|
||||
return;
|
||||
|
||||
BookmarkManager.INSTANCE.setElevationActivePoint(mTrackId, e.getX());
|
||||
if (mInformSelectedActivePointToCore)
|
||||
BookmarkManager.INSTANCE.setElevationActivePoint(mTrackId, e.getX(), (ElevationInfo.Point) e.getData());
|
||||
mInformSelectedActivePointToCore = true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -211,7 +208,6 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
highlightChartCurrentLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentPositionChanged()
|
||||
{
|
||||
if (mTrackId == Utils.INVALID_ID)
|
||||
@@ -222,7 +218,6 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
highlightActivePointManually();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onElevationActivePointChanged()
|
||||
{
|
||||
if (mTrackId == Utils.INVALID_ID)
|
||||
@@ -234,6 +229,7 @@ public class ChartController implements OnChartValueSelectedListener,
|
||||
private void highlightActivePointManually()
|
||||
{
|
||||
Highlight highlight = getActivePoint();
|
||||
mInformSelectedActivePointToCore = false;
|
||||
mChart.highlightValue(highlight, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package app.organicmaps.sdk.bookmarks.data;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -110,6 +111,14 @@ public class Bookmark extends MapObject
|
||||
mCategoryId = catId;
|
||||
}
|
||||
|
||||
public void setIconColor(@ColorInt int color)
|
||||
{
|
||||
Icon icon = new Icon(PredefinedColors.getPredefinedColorIndex(color),
|
||||
BookmarkManager.INSTANCE.getBookmarkIcon(mBookmarkId));
|
||||
BookmarkManager.INSTANCE.notifyParametersUpdating(this, getName(), icon, getBookmarkDescription());
|
||||
mIcon = icon;
|
||||
}
|
||||
|
||||
public void setParams(@NonNull String title, @Nullable Icon icon, @NonNull String description)
|
||||
{
|
||||
BookmarkManager.INSTANCE.notifyParametersUpdating(this, title, icon, description);
|
||||
|
||||
@@ -263,6 +263,12 @@ public enum BookmarkManager {
|
||||
return nativeUpdateBookmarkPlacePage(bmkId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public void updateTrackPlacePage(long trackId)
|
||||
{
|
||||
nativeUpdateTrackPlacePage(trackId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BookmarkInfo getBookmarkInfo(long bmkId)
|
||||
{
|
||||
@@ -729,9 +735,9 @@ public enum BookmarkManager {
|
||||
return nativeGetElevationCurPositionDistance(trackId);
|
||||
}
|
||||
|
||||
public void setElevationActivePoint(long trackId, double distance)
|
||||
public void setElevationActivePoint(long trackId, double distance, ElevationInfo.Point point)
|
||||
{
|
||||
nativeSetElevationActivePoint(trackId, distance);
|
||||
nativeSetElevationActivePoint(trackId, distance, point.getLatitude(), point.getLongitude());
|
||||
}
|
||||
|
||||
public double getElevationActivePointDistance(long trackId)
|
||||
@@ -739,9 +745,14 @@ public enum BookmarkManager {
|
||||
return nativeGetElevationActivePointDistance(trackId);
|
||||
}
|
||||
|
||||
private static native ElevationInfo.Point nativeGetElevationActivePointCoordinates(long trackId);
|
||||
|
||||
@Nullable
|
||||
private native Bookmark nativeUpdateBookmarkPlacePage(long bmkId);
|
||||
|
||||
@Nullable
|
||||
private native void nativeUpdateTrackPlacePage(long trackId);
|
||||
|
||||
@Nullable
|
||||
private native BookmarkInfo nativeGetBookmarkInfo(long bmkId);
|
||||
|
||||
@@ -892,14 +903,25 @@ public enum BookmarkManager {
|
||||
|
||||
public static native void nativeRemoveElevationCurrentPositionChangedListener();
|
||||
|
||||
private static native void nativeSetElevationActivePoint(long trackId, double distanceInMeters);
|
||||
private static native void nativeSetElevationActivePoint(long trackId, double distanceInMeters, double latitude,
|
||||
double longitude);
|
||||
|
||||
private static native double nativeGetElevationActivePointDistance(long trackId);
|
||||
|
||||
public ElevationInfo.Point getElevationActivePointCoordinates(long trackId)
|
||||
{
|
||||
return nativeGetElevationActivePointCoordinates(trackId);
|
||||
}
|
||||
|
||||
private static native void nativeSetElevationActiveChangedListener();
|
||||
|
||||
public static native void nativeRemoveElevationActiveChangedListener();
|
||||
|
||||
public static native ElevationInfo nativeGetTrackElevationInfo(long trackId);
|
||||
|
||||
public static native boolean nativeIsElevationInfoHasValue(long trackId);
|
||||
|
||||
public static native TrackStatistics nativeGetTrackStatistics(long trackId);
|
||||
public interface BookmarksLoadingListener
|
||||
{
|
||||
default void onBookmarksLoadingStarted() {}
|
||||
|
||||
@@ -15,42 +15,19 @@ import java.util.List;
|
||||
@SuppressWarnings("unused")
|
||||
public class ElevationInfo implements PlacePageData
|
||||
{
|
||||
private final long mId;
|
||||
@NonNull
|
||||
private final String mName;
|
||||
@NonNull
|
||||
private final List<Point> mPoints;
|
||||
private final int mAscent;
|
||||
private final int mDescent;
|
||||
private final int mMinAltitude;
|
||||
private final int mMaxAltitude;
|
||||
private final int mDifficulty;
|
||||
private final long mDuration;
|
||||
|
||||
public ElevationInfo(long trackId, @NonNull String name, @NonNull Point[] points, int ascent, int descent,
|
||||
int minAltitude, int maxAltitude, int difficulty, long duration)
|
||||
public ElevationInfo(@NonNull Point[] points, int difficulty)
|
||||
{
|
||||
mId = trackId;
|
||||
mName = name;
|
||||
mPoints = Arrays.asList(points);
|
||||
mAscent = ascent;
|
||||
mDescent = descent;
|
||||
mMinAltitude = minAltitude;
|
||||
mMaxAltitude = maxAltitude;
|
||||
mDifficulty = difficulty;
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
protected ElevationInfo(Parcel in)
|
||||
{
|
||||
mId = in.readLong();
|
||||
mName = in.readString();
|
||||
mAscent = in.readInt();
|
||||
mDescent = in.readInt();
|
||||
mMinAltitude = in.readInt();
|
||||
mMaxAltitude = in.readInt();
|
||||
mDifficulty = in.readInt();
|
||||
mDuration = in.readLong();
|
||||
mPoints = readPoints(in);
|
||||
}
|
||||
|
||||
@@ -62,53 +39,17 @@ public class ElevationInfo implements PlacePageData
|
||||
return points;
|
||||
}
|
||||
|
||||
public long getId()
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Point> getPoints()
|
||||
{
|
||||
return Collections.unmodifiableList(mPoints);
|
||||
}
|
||||
|
||||
public int getAscent()
|
||||
{
|
||||
return mAscent;
|
||||
}
|
||||
|
||||
public int getDescent()
|
||||
{
|
||||
return mDescent;
|
||||
}
|
||||
|
||||
public int getMinAltitude()
|
||||
{
|
||||
return mMinAltitude;
|
||||
}
|
||||
|
||||
public int getMaxAltitude()
|
||||
{
|
||||
return mMaxAltitude;
|
||||
}
|
||||
|
||||
public int getDifficulty()
|
||||
{
|
||||
return mDifficulty;
|
||||
}
|
||||
|
||||
public long getDuration()
|
||||
{
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents()
|
||||
{
|
||||
@@ -118,14 +59,7 @@ public class ElevationInfo implements PlacePageData
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags)
|
||||
{
|
||||
dest.writeLong(mId);
|
||||
dest.writeString(mName);
|
||||
dest.writeInt(mAscent);
|
||||
dest.writeInt(mDescent);
|
||||
dest.writeInt(mMinAltitude);
|
||||
dest.writeInt(mMaxAltitude);
|
||||
dest.writeInt(mDifficulty);
|
||||
dest.writeLong(mDuration);
|
||||
// All collections are deserialized AFTER non-collection and primitive type objects,
|
||||
// so collections must be always serialized at the end.
|
||||
dest.writeTypedList(mPoints);
|
||||
@@ -138,17 +72,23 @@ public class ElevationInfo implements PlacePageData
|
||||
{
|
||||
private final double mDistance;
|
||||
private final int mAltitude;
|
||||
private final double mLatitude;
|
||||
private final double mLongitude;
|
||||
|
||||
public Point(double distance, int altitude)
|
||||
public Point(double distance, int altitude, double latitude, double longitude)
|
||||
{
|
||||
mDistance = distance;
|
||||
mAltitude = altitude;
|
||||
mLatitude = latitude;
|
||||
mLongitude = longitude;
|
||||
}
|
||||
|
||||
protected Point(Parcel in)
|
||||
{
|
||||
mDistance = in.readDouble();
|
||||
mAltitude = in.readInt();
|
||||
mLatitude = in.readDouble();
|
||||
mLongitude = in.readDouble();
|
||||
}
|
||||
|
||||
public static final Creator<Point> CREATOR = new Creator<>() {
|
||||
@@ -175,6 +115,16 @@ public class ElevationInfo implements PlacePageData
|
||||
return mAltitude;
|
||||
}
|
||||
|
||||
public double getLatitude()
|
||||
{
|
||||
return mLatitude;
|
||||
}
|
||||
|
||||
public double getLongitude()
|
||||
{
|
||||
return mLongitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents()
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Objects;
|
||||
public class MapObject implements PlacePageData
|
||||
{
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({POI, API_POINT, BOOKMARK, MY_POSITION, SEARCH})
|
||||
@IntDef({POI, API_POINT, BOOKMARK, MY_POSITION, SEARCH, TRACK})
|
||||
public @interface MapObjectType
|
||||
{}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class MapObject implements PlacePageData
|
||||
public static final int BOOKMARK = 2;
|
||||
public static final int MY_POSITION = 3;
|
||||
public static final int SEARCH = 4;
|
||||
public static final int TRACK = 5;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({OPENING_MODE_PREVIEW, OPENING_MODE_PREVIEW_PLUS, OPENING_MODE_DETAILS, OPENING_MODE_FULL})
|
||||
@@ -315,6 +316,11 @@ public class MapObject implements PlacePageData
|
||||
return mMapObjectType == BOOKMARK;
|
||||
}
|
||||
|
||||
public final boolean isTrack()
|
||||
{
|
||||
return mMapObjectType == TRACK;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RoutePointInfo getRoutePointInfo()
|
||||
{
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
package app.organicmaps.sdk.bookmarks.data;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.organicmaps.sdk.routing.RoutePointInfo;
|
||||
import app.organicmaps.sdk.search.Popularity;
|
||||
import app.organicmaps.sdk.util.Distance;
|
||||
|
||||
// Called from JNI.
|
||||
@Keep
|
||||
@SuppressWarnings("unused")
|
||||
public class Track
|
||||
public class Track extends MapObject
|
||||
{
|
||||
private final long mTrackId;
|
||||
private final long mCategoryId;
|
||||
private long mCategoryId;
|
||||
private final String mName;
|
||||
private final Distance mLength;
|
||||
private final int mColor;
|
||||
private int mColor;
|
||||
@Nullable
|
||||
private ElevationInfo mElevationInfo;
|
||||
@Nullable
|
||||
private TrackStatistics mTrackStatistics;
|
||||
|
||||
Track(long trackId, long categoryId, String name, Distance length, int color)
|
||||
{
|
||||
super(FeatureId.fromFeatureIdString("1:2:3"), TRACK, name, "", "", "", 0, 0, "", null, OPENING_MODE_PREVIEW_PLUS,
|
||||
null, "", RoadWarningMarkType.UNKNOWN.ordinal(), null);
|
||||
mTrackId = trackId;
|
||||
mCategoryId = categoryId;
|
||||
mName = name;
|
||||
@@ -23,6 +34,34 @@ public class Track
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
// used by JNI
|
||||
Track(@NonNull FeatureId featureId, @IntRange(from = 0) long categoryId, @IntRange(from = 0) long trackId,
|
||||
String title, @Nullable String secondaryTitle, @Nullable String subtitle, @Nullable String address,
|
||||
@Nullable RoutePointInfo routePointInfo, @OpeningMode int openingMode, @NonNull Popularity popularity,
|
||||
@NonNull String description, @Nullable String[] rawTypes, int color, Distance length, double lat, double lon)
|
||||
{
|
||||
super(featureId, TRACK, title, secondaryTitle, subtitle, address, lat, lon, "", routePointInfo, openingMode,
|
||||
popularity, description, RoadWarningMarkType.UNKNOWN.ordinal(), rawTypes);
|
||||
mTrackId = trackId;
|
||||
mCategoryId = categoryId;
|
||||
mColor = color;
|
||||
mName = title;
|
||||
mLength = length;
|
||||
}
|
||||
|
||||
// modifying this categoryId will not change the core data
|
||||
// its just for temporary changes
|
||||
public void setCategoryId(@NonNull long categoryId)
|
||||
{
|
||||
mCategoryId = categoryId;
|
||||
}
|
||||
|
||||
public void setColor(@NonNull int color)
|
||||
{
|
||||
mColor = color;
|
||||
BookmarkManager.INSTANCE.changeTrackColor(getTrackId(), color);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
@@ -52,4 +91,25 @@ public class Track
|
||||
{
|
||||
return BookmarkManager.INSTANCE.getTrackDescription(mTrackId);
|
||||
}
|
||||
|
||||
public ElevationInfo getElevationInfo()
|
||||
{
|
||||
if (mElevationInfo != null)
|
||||
return mElevationInfo;
|
||||
mElevationInfo = BookmarkManager.nativeGetTrackElevationInfo(mTrackId);
|
||||
return mElevationInfo;
|
||||
}
|
||||
|
||||
public boolean isElevationInfoHasValue()
|
||||
{
|
||||
return BookmarkManager.nativeIsElevationInfoHasValue(mTrackId);
|
||||
}
|
||||
|
||||
public TrackStatistics getTrackStatistics()
|
||||
{
|
||||
if (mTrackStatistics != null)
|
||||
return mTrackStatistics;
|
||||
mTrackStatistics = BookmarkManager.nativeGetTrackStatistics(mTrackId);
|
||||
return mTrackStatistics;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package app.organicmaps.sdk.bookmarks.data;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
// Used by JNI
|
||||
@Keep
|
||||
public class TrackStatistics
|
||||
{
|
||||
private final double m_length;
|
||||
private final double m_duration;
|
||||
private final double m_ascent;
|
||||
private final double m_descent;
|
||||
private final int m_minElevation;
|
||||
private final int m_maxElevation;
|
||||
|
||||
@Keep
|
||||
public TrackStatistics(double length, double duration, double ascent, double descent, int minElevation,
|
||||
int maxElevation)
|
||||
{
|
||||
m_length = length;
|
||||
m_duration = duration;
|
||||
m_ascent = ascent;
|
||||
m_descent = descent;
|
||||
m_minElevation = minElevation;
|
||||
m_maxElevation = maxElevation;
|
||||
}
|
||||
|
||||
public double getLength()
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
public double getDuration()
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
public double getAscent()
|
||||
{
|
||||
return m_ascent;
|
||||
}
|
||||
|
||||
public double getDescent()
|
||||
{
|
||||
return m_descent;
|
||||
}
|
||||
|
||||
public int getMinElevation()
|
||||
{
|
||||
return m_minElevation;
|
||||
}
|
||||
|
||||
public int getMaxElevation()
|
||||
{
|
||||
return m_maxElevation;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.organicmaps.widget.placepage;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.util.StringUtils;
|
||||
import com.github.mikephil.charting.charts.BarLineChartBase;
|
||||
import com.github.mikephil.charting.formatter.DefaultValueFormatter;
|
||||
|
||||
@@ -20,6 +20,6 @@ public class AxisValueFormatter extends DefaultValueFormatter
|
||||
@Override
|
||||
public String getFormattedValue(float value)
|
||||
{
|
||||
return Framework.nativeFormatAltitude(value);
|
||||
return StringUtils.nativeFormatDistance(value).toString(mChart.getContext());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package app.organicmaps.widget.placepage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -12,18 +11,19 @@ import app.organicmaps.ChartController;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import app.organicmaps.sdk.bookmarks.data.TrackStatistics;
|
||||
import app.organicmaps.sdk.util.UiUtils;
|
||||
import app.organicmaps.sdk.widget.placepage.PlacePageData;
|
||||
import app.organicmaps.util.Utils;
|
||||
import java.util.Objects;
|
||||
|
||||
@SuppressWarnings("unused") // https://github.com/organicmaps/organicmaps/issues/2829
|
||||
public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
{
|
||||
// Must be correspond to map/elevation_info.hpp constants.
|
||||
private static final int MAX_DIFFICULTY_LEVEL = 3;
|
||||
private static final int UNKNOWN_DIFFICULTY = 0;
|
||||
|
||||
@NonNull
|
||||
private final View[] mDifficultyLevels = new View[MAX_DIFFICULTY_LEVEL];
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private NestedScrollView mScrollView;
|
||||
@@ -45,8 +45,6 @@ public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private TextView mTime;
|
||||
@NonNull
|
||||
private final View[] mDifficultyLevels = new View[MAX_DIFFICULTY_LEVEL];
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private ChartController mChartController;
|
||||
@@ -58,23 +56,7 @@ public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private View mTimeContainer;
|
||||
|
||||
public void render(@NonNull PlacePageData data)
|
||||
{
|
||||
final Context context = mAscent.getContext();
|
||||
|
||||
mElevationInfo = (ElevationInfo) data;
|
||||
mChartController.setData(mElevationInfo);
|
||||
mTitle.setText(mElevationInfo.getName());
|
||||
setDifficulty(mElevationInfo.getDifficulty());
|
||||
mAscent.setText(formatDistance(context, mElevationInfo.getAscent()));
|
||||
mDescent.setText(formatDistance(context, mElevationInfo.getDescent()));
|
||||
mMaxAltitude.setText(formatDistance(context, mElevationInfo.getMaxAltitude()));
|
||||
mMinAltitude.setText(formatDistance(context, mElevationInfo.getMinAltitude()));
|
||||
UiUtils.hideIf(mElevationInfo.getDuration() == 0, mTimeContainer);
|
||||
mTime.setText(
|
||||
Utils.formatRoutingTime(mTitle.getContext(), (int) mElevationInfo.getDuration(), R.dimen.text_size_body_2));
|
||||
}
|
||||
private View mTitleContainer;
|
||||
|
||||
@NonNull
|
||||
private static String formatDistance(final Context context, int distance)
|
||||
@@ -82,6 +64,24 @@ public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
return Framework.nativeFormatAltitude(distance);
|
||||
}
|
||||
|
||||
public void render(@NonNull Track track)
|
||||
{
|
||||
final Context context = mAscent.getContext();
|
||||
TrackStatistics stats = track.getTrackStatistics();
|
||||
|
||||
mElevationInfo = track.getElevationInfo();
|
||||
mChartController.setData(track);
|
||||
UiUtils.hide(mTitleContainer);
|
||||
mTitle.setText(track.getName());
|
||||
setDifficulty(mElevationInfo.getDifficulty());
|
||||
mAscent.setText(formatDistance(context, (int) stats.getAscent()));
|
||||
mDescent.setText(formatDistance(context, (int) stats.getDescent()));
|
||||
mMaxAltitude.setText(formatDistance(context, stats.getMaxElevation()));
|
||||
mMinAltitude.setText(formatDistance(context, stats.getMinElevation()));
|
||||
UiUtils.hide(mTimeContainer);
|
||||
mTime.setText(Utils.formatRoutingTime(mAscent.getContext(), (int) stats.getDuration(), R.dimen.text_size_body_2));
|
||||
}
|
||||
|
||||
public void initialize(@Nullable View view)
|
||||
{
|
||||
Objects.requireNonNull(view);
|
||||
@@ -89,6 +89,7 @@ public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
mChartController.initialize(view);
|
||||
mScrollView = (NestedScrollView) view;
|
||||
mTitle = view.findViewById(R.id.title);
|
||||
mTitleContainer = view.findViewById(R.id.title_container);
|
||||
mAscent = view.findViewById(R.id.ascent);
|
||||
mDescent = view.findViewById(R.id.descent);
|
||||
mMaxAltitude = view.findViewById(R.id.max_altitude);
|
||||
@@ -123,21 +124,13 @@ public class ElevationProfileViewRenderer implements PlacePageStateListener
|
||||
mDifficultyLevels[i].setEnabled(true);
|
||||
}
|
||||
|
||||
public void onSave(@NonNull Bundle outState)
|
||||
public void onChartElevationActivePointChanged()
|
||||
{
|
||||
// outState.putParcelable(PlacePageUtils.EXTRA_PLACE_PAGE_DATA, mElevationInfo);
|
||||
mChartController.onElevationActivePointChanged();
|
||||
}
|
||||
|
||||
public void onRestore(@NonNull Bundle inState)
|
||||
public void onChartCurrentPositionChanged()
|
||||
{
|
||||
// mElevationInfo = BundleCompat.getParcelable(inState, PlacePageUtils.EXTRA_PLACE_PAGE_DATA,
|
||||
// ElevationInfo.class); if (mElevationInfo != null)
|
||||
// render(mElevationInfo);
|
||||
}
|
||||
|
||||
public void onHide()
|
||||
{
|
||||
mScrollView.scrollTo(0, 0);
|
||||
mChartController.onHide();
|
||||
mChartController.onCurrentPositionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,6 @@ public class FloatingMarkerView extends RelativeLayout implements IMarker
|
||||
private TextView mAltitudeView;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private TextView mDistanceTextView;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private TextView mDistanceValueView;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
@@ -93,7 +90,6 @@ public class FloatingMarkerView extends RelativeLayout implements IMarker
|
||||
mTextContentContainer = findViewById(R.id.floating_text_container);
|
||||
mFloatingTriangle = findViewById(R.id.floating_triangle);
|
||||
mImage = findViewById(R.id.image);
|
||||
mDistanceTextView = findViewById(R.id.distance_text);
|
||||
mAltitudeView = findViewById(R.id.altitude);
|
||||
mDistanceValueView = findViewById(R.id.distance_value);
|
||||
}
|
||||
@@ -125,7 +121,7 @@ public class FloatingMarkerView extends RelativeLayout implements IMarker
|
||||
public void updateOffsets(@NonNull Entry entry, @NonNull Highlight highlight)
|
||||
{
|
||||
updateVertical(entry);
|
||||
final float halfImg = Math.abs(mImage.getWidth()) / 2f;
|
||||
final float halfImg = mImage.getResources().getDimensionPixelSize(R.dimen.elevation_profile_marker_width) / 2f;
|
||||
boolean isLeftToRightDirection = isInvertedOrder(highlight);
|
||||
mOffset = isLeftToRightDirection ? -getWidth() + halfImg : -halfImg;
|
||||
updateHorizontal(highlight);
|
||||
@@ -184,7 +180,6 @@ public class FloatingMarkerView extends RelativeLayout implements IMarker
|
||||
|
||||
private void updatePointValues(@NonNull Entry entry)
|
||||
{
|
||||
mDistanceTextView.setText(R.string.elevation_profile_distance);
|
||||
mDistanceValueView.setText(
|
||||
StringUtils.nativeFormatDistance(entry.getX()).toString(mDistanceValueView.getContext()));
|
||||
mAltitudeView.setText(Framework.nativeFormatAltitude(entry.getY()));
|
||||
|
||||
@@ -34,6 +34,11 @@ public class PlacePageButtonFactory
|
||||
titleId = R.string.delete;
|
||||
yield R.drawable.ic_bookmarks_on;
|
||||
}
|
||||
case TRACK_DELETE ->
|
||||
{
|
||||
titleId = R.string.delete;
|
||||
yield R.drawable.ic_delete;
|
||||
}
|
||||
case ROUTE_FROM ->
|
||||
{
|
||||
titleId = R.string.p2p_from_here;
|
||||
|
||||
@@ -136,6 +136,7 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
|
||||
BACK,
|
||||
BOOKMARK_SAVE,
|
||||
BOOKMARK_DELETE,
|
||||
TRACK_DELETE,
|
||||
ROUTE_FROM,
|
||||
ROUTE_TO,
|
||||
ROUTE_ADD,
|
||||
|
||||
@@ -2,6 +2,7 @@ package app.organicmaps.widget.placepage;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
@@ -30,6 +31,7 @@ import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.bookmarks.data.RoadWarningMarkType;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import app.organicmaps.sdk.routing.RoutingController;
|
||||
import app.organicmaps.sdk.settings.RoadType;
|
||||
import app.organicmaps.sdk.util.UiUtils;
|
||||
@@ -38,6 +40,7 @@ import app.organicmaps.util.ThemeUtils;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.shape.MaterialShapeDrawable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -74,6 +77,7 @@ public class PlacePageController
|
||||
|
||||
private ValueAnimator mCustomPeekHeightAnimator;
|
||||
private PlacePageRouteSettingsListener mPlacePageRouteSettingsListener;
|
||||
private Dialog mAlertDialog;
|
||||
|
||||
private final Observer<Integer> mPlacePageDistanceToTopObserver = new Observer<>() {
|
||||
private float mPlacePageCornerRadius;
|
||||
@@ -120,7 +124,6 @@ public class PlacePageController
|
||||
bg.setCornerSize(mPlacePageCornerRadius);
|
||||
}
|
||||
};
|
||||
|
||||
private final BottomSheetBehavior.BottomSheetCallback mDefaultBottomSheetCallback =
|
||||
new BottomSheetBehavior.BottomSheetCallback() {
|
||||
@Override
|
||||
@@ -145,6 +148,18 @@ public class PlacePageController
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private static PlacePageButtons.ButtonType toPlacePageButton(@NonNull RoadWarningMarkType type)
|
||||
{
|
||||
return switch (type)
|
||||
{
|
||||
case DIRTY -> PlacePageButtons.ButtonType.ROUTE_AVOID_UNPAVED;
|
||||
case FERRY -> PlacePageButtons.ButtonType.ROUTE_AVOID_FERRY;
|
||||
case TOLL -> PlacePageButtons.ButtonType.ROUTE_AVOID_TOLL;
|
||||
default -> throw new AssertionError("Unsupported road warning type: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@@ -202,18 +217,6 @@ public class PlacePageController
|
||||
ViewCompat.requestApplyInsets(mPlacePage);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static PlacePageButtons.ButtonType toPlacePageButton(@NonNull RoadWarningMarkType type)
|
||||
{
|
||||
return switch (type)
|
||||
{
|
||||
case DIRTY -> PlacePageButtons.ButtonType.ROUTE_AVOID_UNPAVED;
|
||||
case FERRY -> PlacePageButtons.ButtonType.ROUTE_AVOID_FERRY;
|
||||
case TOLL -> PlacePageButtons.ButtonType.ROUTE_AVOID_TOLL;
|
||||
default -> throw new AssertionError("Unsupported road warning type: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
private void stopCustomPeekHeightAnimation()
|
||||
{
|
||||
if (mCustomPeekHeightAnimator != null && mCustomPeekHeightAnimator.isStarted())
|
||||
@@ -415,6 +418,7 @@ public class PlacePageController
|
||||
switch (item)
|
||||
{
|
||||
case BOOKMARK_SAVE, BOOKMARK_DELETE -> onBookmarkBtnClicked();
|
||||
case TRACK_DELETE -> onTrackRemoveClicked();
|
||||
case BACK -> onBackBtnClicked();
|
||||
case ROUTE_FROM -> onRouteFromBtnClicked();
|
||||
case ROUTE_TO -> onRouteToBtnClicked();
|
||||
@@ -439,6 +443,48 @@ public class PlacePageController
|
||||
BookmarkManager.INSTANCE.addNewBookmark(mMapObject.getLat(), mMapObject.getLon());
|
||||
}
|
||||
|
||||
private void onTrackRemoveClicked()
|
||||
{
|
||||
// mMapObject is set to null when the place page closes
|
||||
// We don't want users to interact with the buttons when the PP is closing
|
||||
if (mMapObject == null)
|
||||
return;
|
||||
showTrackDeleteAlertDialog();
|
||||
}
|
||||
|
||||
void showTrackDeleteAlertDialog()
|
||||
{
|
||||
if (mMapObject == null)
|
||||
return;
|
||||
if (mAlertDialog != null)
|
||||
{
|
||||
mAlertDialog.dismiss();
|
||||
mAlertDialog.show();
|
||||
mViewModel.isAlertDialogShowing = true;
|
||||
return;
|
||||
}
|
||||
mViewModel.isAlertDialogShowing = true;
|
||||
mAlertDialog = new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
|
||||
.setTitle("Would you like to delete " + mMapObject.getTitle() + "?")
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton("delete",
|
||||
(dialog, which) -> {
|
||||
BookmarkManager.INSTANCE.deleteTrack(((Track) mMapObject).getTrackId());
|
||||
close();
|
||||
})
|
||||
.setOnDismissListener(dialog -> dismissAlertDialog())
|
||||
.show();
|
||||
}
|
||||
|
||||
void dismissAlertDialog()
|
||||
{
|
||||
if (mAlertDialog == null)
|
||||
return;
|
||||
mAlertDialog.dismiss();
|
||||
mViewModel.isAlertDialogShowing = false;
|
||||
}
|
||||
|
||||
private void onBackBtnClicked()
|
||||
{
|
||||
if (mMapObject == null)
|
||||
@@ -577,8 +623,12 @@ public class PlacePageController
|
||||
if (needToShowRoutingButtons && RoutingController.get().isStopPointAllowed())
|
||||
buttons.add(PlacePageButtons.ButtonType.ROUTE_ADD);
|
||||
else
|
||||
{
|
||||
buttons.add(mapObject.isBookmark() ? PlacePageButtons.ButtonType.BOOKMARK_DELETE
|
||||
: PlacePageButtons.ButtonType.BOOKMARK_SAVE);
|
||||
if (mapObject.isTrack())
|
||||
buttons.add(PlacePageButtons.ButtonType.TRACK_DELETE);
|
||||
}
|
||||
|
||||
if (needToShowRoutingButtons)
|
||||
{
|
||||
@@ -610,6 +660,8 @@ public class PlacePageController
|
||||
// Place page will automatically open when the bottom sheet content is loaded so we can compute the peek height
|
||||
createPlacePageFragments();
|
||||
updateButtons(mapObject, showBackButton, !mMapObject.isMyPosition());
|
||||
if (mViewModel.isAlertDialogShowing)
|
||||
showTrackDeleteAlertDialog();
|
||||
}
|
||||
else
|
||||
close();
|
||||
|
||||
@@ -6,6 +6,7 @@ import static app.organicmaps.sdk.util.Utils.getLocalizedFeatureType;
|
||||
import static app.organicmaps.sdk.util.Utils.getTagValueLocalized;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -16,25 +17,39 @@ import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentFactory;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.BookmarksSharingHelper;
|
||||
import app.organicmaps.bookmarks.ChooseBookmarkCategoryFragment;
|
||||
import app.organicmaps.downloader.DownloaderStatusIcon;
|
||||
import app.organicmaps.editor.OhState;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.Bookmark;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
|
||||
import app.organicmaps.sdk.bookmarks.data.DistanceAndAzimut;
|
||||
import app.organicmaps.sdk.bookmarks.data.Icon;
|
||||
import app.organicmaps.sdk.bookmarks.data.KmlFileType;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.bookmarks.data.Metadata;
|
||||
import app.organicmaps.sdk.bookmarks.data.PredefinedColors;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import app.organicmaps.sdk.downloader.CountryItem;
|
||||
import app.organicmaps.sdk.downloader.MapManager;
|
||||
import app.organicmaps.sdk.editor.Editor;
|
||||
@@ -49,13 +64,17 @@ import app.organicmaps.sdk.util.StringUtils;
|
||||
import app.organicmaps.sdk.util.UiUtils;
|
||||
import app.organicmaps.sdk.util.concurrency.UiThread;
|
||||
import app.organicmaps.sdk.widget.placepage.CoordinatesFormat;
|
||||
import app.organicmaps.util.Graphics;
|
||||
import app.organicmaps.util.SharingUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
|
||||
import app.organicmaps.widget.ArrowView;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageBookmarkFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageLinksFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageOpeningHoursFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePagePhoneFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageTrackFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageWikipediaFragment;
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
@@ -68,15 +87,19 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PlacePageView extends Fragment
|
||||
implements View.OnClickListener, View.OnLongClickListener, LocationListener, SensorListener, Observer<MapObject>
|
||||
implements View.OnClickListener, View.OnLongClickListener, LocationListener, SensorListener, Observer<MapObject>,
|
||||
ChooseBookmarkCategoryFragment.Listener, EditBookmarkFragment.EditBookmarkListener,
|
||||
MenuBottomSheetFragment.MenuBottomSheetInterface, BookmarkManager.BookmarksSharingListener
|
||||
|
||||
{
|
||||
private static final String PREF_COORDINATES_FORMAT = "coordinates_format";
|
||||
private static final String BOOKMARK_FRAGMENT_TAG = "BOOKMARK_FRAGMENT_TAG";
|
||||
private static final String TRACK_FRAGMENT_TAG = "TRACK_FRAGMENT_TAG";
|
||||
private static final String WIKIPEDIA_FRAGMENT_TAG = "WIKIPEDIA_FRAGMENT_TAG";
|
||||
private static final String PHONE_FRAGMENT_TAG = "PHONE_FRAGMENT_TAG";
|
||||
private static final String OPENING_HOURS_FRAGMENT_TAG = "OPENING_HOURS_FRAGMENT_TAG";
|
||||
private static final String LINKS_FRAGMENT_TAG = "LINKS_FRAGMENT_TAG";
|
||||
private static final String TRACK_SHARE_MENU_ID = "TRACK_SHARE_MENU_ID";
|
||||
|
||||
private static final List<CoordinatesFormat> visibleCoordsFormat =
|
||||
Arrays.asList(CoordinatesFormat.LatLonDMS, CoordinatesFormat.LatLonDecimal, CoordinatesFormat.OLCFull,
|
||||
@@ -124,12 +147,16 @@ public class PlacePageView extends Fragment
|
||||
private View mAddOrganisation;
|
||||
private View mAddPlace;
|
||||
private View mEditTopSpace;
|
||||
private ImageView mColorIcon;
|
||||
private TextView mTvCategory;
|
||||
private ImageView mEditBookmark;
|
||||
|
||||
// Data
|
||||
private CoordinatesFormat mCoordsFormat = CoordinatesFormat.LatLonDecimal;
|
||||
// Downloader`s stuff
|
||||
private DownloaderStatusIcon mDownloaderIcon;
|
||||
private MaterialTextView mDownloaderInfo;
|
||||
private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher;
|
||||
private int mStorageCallbackSlot;
|
||||
@Nullable
|
||||
private CountryItem mCurrentCountry;
|
||||
@@ -185,6 +212,7 @@ public class PlacePageView extends Fragment
|
||||
@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
mViewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
|
||||
shareLauncher = SharingUtils.RegisterLauncher(this);
|
||||
return inflater.inflate(R.layout.place_page, container, false);
|
||||
}
|
||||
|
||||
@@ -232,8 +260,12 @@ public class PlacePageView extends Fragment
|
||||
mTvAddress.setOnLongClickListener(this);
|
||||
mTvAddress.setOnClickListener(this);
|
||||
|
||||
mColorIcon = mFrame.findViewById(R.id.item_icon);
|
||||
mTvCategory = mFrame.findViewById(R.id.tv__category);
|
||||
mEditBookmark = mFrame.findViewById(R.id.edit_Bookmark);
|
||||
|
||||
MaterialButton shareButton = mPreview.findViewById(R.id.share_button);
|
||||
shareButton.setOnClickListener((v) -> SharingUtils.shareMapObject(requireContext(), mMapObject));
|
||||
shareButton.setOnClickListener(this::shareClickListener);
|
||||
|
||||
final MaterialButton closeButton = mPreview.findViewById(R.id.close_button);
|
||||
closeButton.setOnClickListener((v) -> mPlacePageViewListener.onPlacePageRequestClose());
|
||||
@@ -301,6 +333,7 @@ public class PlacePageView extends Fragment
|
||||
{
|
||||
super.onStart();
|
||||
mViewModel.getMapObject().observe(requireActivity(), this);
|
||||
BookmarkManager.INSTANCE.addSharingListener(this);
|
||||
MwmApplication.from(requireContext()).getLocationHelper().addListener(this);
|
||||
MwmApplication.from(requireContext()).getSensorHelper().addListener(this);
|
||||
}
|
||||
@@ -310,6 +343,7 @@ public class PlacePageView extends Fragment
|
||||
{
|
||||
super.onStop();
|
||||
mViewModel.getMapObject().removeObserver(this);
|
||||
BookmarkManager.INSTANCE.removeSharingListener(this);
|
||||
MwmApplication.from(requireContext()).getLocationHelper().removeListener(this);
|
||||
MwmApplication.from(requireContext()).getSensorHelper().removeListener(this);
|
||||
UiThread.cancelDelayedTasks(updateOpenState);
|
||||
@@ -334,6 +368,10 @@ public class PlacePageView extends Fragment
|
||||
refreshMyPosition(loc);
|
||||
else
|
||||
refreshDistanceToObject(loc);
|
||||
UiUtils.hideIf(mMapObject.isTrack(), mFrame.findViewById(R.id.ll__place_latlon),
|
||||
mFrame.findViewById(R.id.ll__place_open_in), mFrame.findViewById(R.id.ll__place_add), mEditTopSpace,
|
||||
mTvAzimuth, mTvDistance, mAvDirection);
|
||||
UiUtils.hideIf(MapObjectType.getMapObjectType(mMapObject) != MapObjectType.OTHER, mTvSubtitle);
|
||||
}
|
||||
|
||||
private <T extends Fragment> void updateViewFragment(Class<T> controllerClass, String fragmentTag,
|
||||
@@ -375,6 +413,12 @@ public class PlacePageView extends Fragment
|
||||
mMapObject.isBookmark());
|
||||
}
|
||||
|
||||
private void updateTrackView()
|
||||
{
|
||||
updateViewFragment(PlacePageTrackFragment.class, TRACK_FRAGMENT_TAG, R.id.place_page_track_fragment,
|
||||
mMapObject.isTrack());
|
||||
}
|
||||
|
||||
private boolean hasWikipediaEntry()
|
||||
{
|
||||
final String wikipediaLink = mMapObject.getMetadata(Metadata.MetadataType.FMD_WIKIPEDIA);
|
||||
@@ -416,6 +460,180 @@ public class PlacePageView extends Fragment
|
||||
mToolbar.setTitle(mMapObject.getTitle());
|
||||
setTextAndColorizeSubtitle();
|
||||
UiUtils.setTextAndHideIfEmpty(mTvAddress, mMapObject.getAddress());
|
||||
refreshCategoryPreview();
|
||||
}
|
||||
|
||||
void refreshCategoryPreview()
|
||||
{
|
||||
View categoryContainer = mFrame.findViewById(R.id.category_container);
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK ->
|
||||
{
|
||||
Track track = (Track) mMapObject;
|
||||
Drawable circle =
|
||||
Graphics.drawCircle(track.getColor(), R.dimen.place_page_icon_size, requireContext().getResources());
|
||||
mColorIcon.setImageDrawable(circle);
|
||||
mTvCategory.setText(BookmarkManager.INSTANCE.getCategoryById(track.getCategoryId()).getName());
|
||||
UiUtils.show(mColorIcon, mTvCategory, categoryContainer);
|
||||
}
|
||||
case BOOKMARK ->
|
||||
{
|
||||
Bookmark bookmark = (Bookmark) mMapObject;
|
||||
Icon icon = bookmark.getIcon();
|
||||
if (icon != null)
|
||||
{
|
||||
Drawable circle = Graphics.drawCircleAndImage(icon.argb(), R.dimen.place_page_icon_size,
|
||||
app.organicmaps.sdk.R.drawable.ic_bookmark_none,
|
||||
R.dimen.place_page_icon_mark_size, requireContext());
|
||||
mColorIcon.setImageDrawable(circle);
|
||||
mTvCategory.setText(BookmarkManager.INSTANCE.getCategoryById(bookmark.getCategoryId()).getName());
|
||||
UiUtils.show(mColorIcon, mTvCategory, categoryContainer);
|
||||
}
|
||||
}
|
||||
case OTHER -> UiUtils.hide(mColorIcon, mTvCategory, categoryContainer);
|
||||
}
|
||||
mColorIcon.setOnClickListener(this::onClick);
|
||||
mTvCategory.setOnClickListener(this::onClick);
|
||||
mEditBookmark.setOnClickListener(this::onClick);
|
||||
}
|
||||
|
||||
void showColorDialog()
|
||||
{
|
||||
final Bundle args = new Bundle();
|
||||
final FragmentManager manager = getChildFragmentManager();
|
||||
String className = BookmarkColorDialogFragment.class.getName();
|
||||
final FragmentFactory factory = manager.getFragmentFactory();
|
||||
final BookmarkColorDialogFragment dialogFragment =
|
||||
(BookmarkColorDialogFragment) factory.instantiate(getContext().getClassLoader(), className);
|
||||
dialogFragment.setArguments(args);
|
||||
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK ->
|
||||
{
|
||||
final Track mTrack = (Track) mMapObject;
|
||||
args.putInt(BookmarkColorDialogFragment.ICON_COLOR, PredefinedColors.getPredefinedColorIndex(mTrack.getColor()));
|
||||
dialogFragment.setOnColorSetListener((colorPos) -> {
|
||||
int from = mTrack.getColor();
|
||||
int to = PredefinedColors.getColor(colorPos);
|
||||
if (from == to)
|
||||
return;
|
||||
mViewModel.modifyMapObjectColorSilently(to);
|
||||
Drawable circle = Graphics.drawCircle(to, R.dimen.place_page_icon_size, requireContext().getResources());
|
||||
mColorIcon.setImageDrawable(circle);
|
||||
});
|
||||
dialogFragment.show(requireActivity().getSupportFragmentManager(), null);
|
||||
}
|
||||
case BOOKMARK ->
|
||||
{
|
||||
final Bookmark bookmark = (Bookmark) mMapObject;
|
||||
args.putInt(BookmarkColorDialogFragment.ICON_COLOR, bookmark.getIcon().getColor());
|
||||
args.putInt(BookmarkColorDialogFragment.ICON_RES, bookmark.getIcon().getResId());
|
||||
dialogFragment.setOnColorSetListener((colorPos) -> {
|
||||
int from = bookmark.getIcon().argb();
|
||||
int to = PredefinedColors.getColor(colorPos);
|
||||
if (from == to)
|
||||
return;
|
||||
mViewModel.modifyMapObjectColorSilently(to);
|
||||
Drawable circle = Graphics.drawCircleAndImage(to, R.dimen.place_page_icon_size,
|
||||
app.organicmaps.sdk.R.drawable.ic_bookmark_none,
|
||||
R.dimen.place_page_icon_mark_size, requireContext());
|
||||
mColorIcon.setImageDrawable(circle);
|
||||
});
|
||||
dialogFragment.show(requireActivity().getSupportFragmentManager(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showCategoryList()
|
||||
{
|
||||
final Bundle args = new Bundle();
|
||||
final List<BookmarkCategory> categories = BookmarkManager.INSTANCE.getCategories();
|
||||
final FragmentManager manager = getChildFragmentManager();
|
||||
String className = ChooseBookmarkCategoryFragment.class.getName();
|
||||
final FragmentFactory factory = manager.getFragmentFactory();
|
||||
final ChooseBookmarkCategoryFragment frag =
|
||||
(ChooseBookmarkCategoryFragment) factory.instantiate(getContext().getClassLoader(), className);
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK ->
|
||||
{
|
||||
Track track = (Track) mMapObject;
|
||||
BookmarkCategory currentCategory = BookmarkManager.INSTANCE.getCategoryById(track.getCategoryId());
|
||||
final int index = categories.indexOf(currentCategory);
|
||||
args.putInt(ChooseBookmarkCategoryFragment.CATEGORY_POSITION, index);
|
||||
frag.setArguments(args);
|
||||
frag.show(manager, null);
|
||||
}
|
||||
case BOOKMARK ->
|
||||
{
|
||||
Bookmark bookmark = (Bookmark) mMapObject;
|
||||
BookmarkCategory currentCategory = BookmarkManager.INSTANCE.getCategoryById(bookmark.getCategoryId());
|
||||
final int index = categories.indexOf(currentCategory);
|
||||
args.putInt(ChooseBookmarkCategoryFragment.CATEGORY_POSITION, index);
|
||||
frag.setArguments(args);
|
||||
frag.show(manager, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCategoryChanged(@NonNull BookmarkCategory newCategory)
|
||||
{
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK ->
|
||||
{
|
||||
Track track = (Track) mMapObject;
|
||||
BookmarkCategory previousCategory = BookmarkManager.INSTANCE.getCategoryById(track.getCategoryId());
|
||||
if (previousCategory == newCategory)
|
||||
return;
|
||||
BookmarkManager.INSTANCE.notifyCategoryChanging(track, newCategory.getId());
|
||||
mTvCategory.setText(newCategory.getName());
|
||||
mViewModel.modifyMapObjectCategoryIdSilently(newCategory.getId());
|
||||
}
|
||||
case BOOKMARK ->
|
||||
{
|
||||
Bookmark bookmark = (Bookmark) mMapObject;
|
||||
BookmarkCategory previousCategory = BookmarkManager.INSTANCE.getCategoryById(bookmark.getCategoryId());
|
||||
if (previousCategory == newCategory)
|
||||
return;
|
||||
mTvCategory.setText(newCategory.getName());
|
||||
mViewModel.modifyMapObjectCategoryIdSilently(newCategory.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showBookmarkEditFragment()
|
||||
{
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK ->
|
||||
{
|
||||
Track track = (Track) mMapObject;
|
||||
final FragmentActivity activity = requireActivity();
|
||||
EditBookmarkFragment.editTrack(track.getCategoryId(), track.getTrackId(), activity, getChildFragmentManager(),
|
||||
PlacePageView.this);
|
||||
}
|
||||
case BOOKMARK ->
|
||||
{
|
||||
Bookmark bookmark = (Bookmark) mMapObject;
|
||||
final FragmentActivity activity = requireActivity();
|
||||
EditBookmarkFragment.editBookmark(bookmark.getCategoryId(), bookmark.getBookmarkId(), activity,
|
||||
getChildFragmentManager(), PlacePageView.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBookmarkSaved(long bookmarkId, boolean movedFromCategory)
|
||||
{
|
||||
switch (MapObjectType.getMapObjectType(mMapObject))
|
||||
{
|
||||
case TRACK -> BookmarkManager.INSTANCE.updateTrackPlacePage(bookmarkId);
|
||||
case BOOKMARK -> BookmarkManager.INSTANCE.updateBookmarkPlacePage(bookmarkId);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshDetails()
|
||||
@@ -494,6 +712,7 @@ public class PlacePageView extends Fragment
|
||||
updateWikipediaView();
|
||||
updateBookmarkView();
|
||||
updatePhoneView();
|
||||
updateTrackView();
|
||||
}
|
||||
|
||||
private void refreshWiFi()
|
||||
@@ -532,6 +751,8 @@ public class PlacePageView extends Fragment
|
||||
|
||||
private void refreshDistanceToObject(Location l)
|
||||
{
|
||||
if (mMapObject.isTrack())
|
||||
return;
|
||||
UiUtils.showIf(l != null, mTvDistance);
|
||||
if (l == null)
|
||||
return;
|
||||
@@ -660,6 +881,12 @@ public class PlacePageView extends Fragment
|
||||
}
|
||||
else if (id == R.id.direction_frame)
|
||||
showBigDirection();
|
||||
else if (id == R.id.item_icon)
|
||||
showColorDialog();
|
||||
else if (id == R.id.edit_Bookmark)
|
||||
showBookmarkEditFragment();
|
||||
else if (id == R.id.tv__category)
|
||||
showCategoryList();
|
||||
}
|
||||
|
||||
private void showBigDirection()
|
||||
@@ -818,7 +1045,7 @@ public class PlacePageView extends Fragment
|
||||
@Override
|
||||
public void onCompassUpdated(double north)
|
||||
{
|
||||
if (mMapObject == null || mMapObject.isMyPosition())
|
||||
if (mMapObject == null || mMapObject.isMyPosition() || mMapObject.isTrack())
|
||||
return;
|
||||
|
||||
final Location location = MwmApplication.from(requireContext()).getLocationHelper().getSavedLocation();
|
||||
@@ -840,6 +1067,50 @@ public class PlacePageView extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
void shareClickListener(View v)
|
||||
{
|
||||
if (mMapObject.isTrack())
|
||||
{
|
||||
MenuBottomSheetFragment.newInstance(TRACK_SHARE_MENU_ID, getString(R.string.PP_track_bottom_sheet_title))
|
||||
.show(getChildFragmentManager(), TRACK_SHARE_MENU_ID);
|
||||
}
|
||||
else
|
||||
SharingUtils.shareMapObject(requireContext(), mMapObject);
|
||||
}
|
||||
|
||||
private void onShareTrackSelected(long trackId, KmlFileType kmlFileType)
|
||||
{
|
||||
BookmarksSharingHelper.INSTANCE.prepareTrackForSharing(requireActivity(), trackId, kmlFileType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id)
|
||||
{
|
||||
return switch (id)
|
||||
{
|
||||
case TRACK_SHARE_MENU_ID -> getTrackShareMenuItems();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
public ArrayList<MenuBottomSheetItem> getTrackShareMenuItems()
|
||||
{
|
||||
Track track = (Track) mMapObject;
|
||||
ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
|
||||
items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
|
||||
() -> onShareTrackSelected(track.getTrackId(), KmlFileType.Text)));
|
||||
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
|
||||
() -> onShareTrackSelected(track.getTrackId(), KmlFileType.Gpx)));
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreparedFileForSharing(@NonNull BookmarkSharingResult result)
|
||||
{
|
||||
BookmarksSharingHelper.INSTANCE.onPreparedFileForSharing(requireActivity(), shareLauncher, result);
|
||||
}
|
||||
|
||||
public interface PlacePageViewListener
|
||||
{
|
||||
// Called when the content has actually changed and we are ready to compute the peek height
|
||||
@@ -848,4 +1119,21 @@ public class PlacePageView extends Fragment
|
||||
void onPlacePageRequestToggleState();
|
||||
void onPlacePageRequestClose();
|
||||
}
|
||||
|
||||
public enum MapObjectType
|
||||
{
|
||||
TRACK,
|
||||
BOOKMARK,
|
||||
OTHER;
|
||||
|
||||
public static MapObjectType getMapObjectType(MapObject mapObject)
|
||||
{
|
||||
if (mapObject.isTrack())
|
||||
return TRACK;
|
||||
else if (mapObject.isBookmark())
|
||||
return BOOKMARK;
|
||||
else
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package app.organicmaps.widget.placepage;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import app.organicmaps.sdk.bookmarks.data.Bookmark;
|
||||
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import java.util.List;
|
||||
|
||||
public class PlacePageViewModel extends ViewModel
|
||||
@@ -12,6 +15,7 @@ public class PlacePageViewModel extends ViewModel
|
||||
private final MutableLiveData<MapObject> mMapObject = new MutableLiveData<>();
|
||||
private final MutableLiveData<Integer> mPlacePageWidth = new MutableLiveData<>();
|
||||
private final MutableLiveData<Integer> mPlacePageDistanceToTop = new MutableLiveData<>();
|
||||
public boolean isAlertDialogShowing = false;
|
||||
|
||||
public LiveData<List<PlacePageButtons.ButtonType>> getCurrentButtons()
|
||||
{
|
||||
@@ -33,6 +37,38 @@ public class PlacePageViewModel extends ViewModel
|
||||
mMapObject.setValue(mapObject);
|
||||
}
|
||||
|
||||
// These silent method are used to update data of map object silently without triggering
|
||||
// the observer which refreshes everything and puts extra load on device in calculation
|
||||
// which is not required
|
||||
public void modifyMapObjectPointSilently(ElevationInfo.Point point)
|
||||
{
|
||||
if (mMapObject.getValue() == null)
|
||||
return;
|
||||
mMapObject.getValue().setLat(point.getLatitude());
|
||||
mMapObject.getValue().setLon(point.getLongitude());
|
||||
}
|
||||
|
||||
public void modifyMapObjectCategoryIdSilently(long categoryId)
|
||||
{
|
||||
if (mMapObject.getValue() == null)
|
||||
return;
|
||||
switch (PlacePageView.MapObjectType.getMapObjectType(mMapObject.getValue()))
|
||||
{
|
||||
case TRACK -> ((Track) mMapObject.getValue()).setCategoryId(categoryId);
|
||||
case BOOKMARK -> ((Bookmark) mMapObject.getValue()).setCategoryId(categoryId);
|
||||
}
|
||||
}
|
||||
|
||||
public void modifyMapObjectColorSilently(int color)
|
||||
{
|
||||
if (mMapObject.getValue() == null)
|
||||
return;
|
||||
switch (PlacePageView.MapObjectType.getMapObjectType(mMapObject.getValue()))
|
||||
{
|
||||
case TRACK -> ((Track) mMapObject.getValue()).setColor(color);
|
||||
case BOOKMARK -> ((Bookmark) mMapObject.getValue()).setIconColor(color);
|
||||
}
|
||||
}
|
||||
public MutableLiveData<Integer> getPlacePageWidth()
|
||||
{
|
||||
return mPlacePageWidth;
|
||||
|
||||
@@ -16,23 +16,18 @@ import android.widget.LinearLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.bookmarks.data.Bookmark;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.util.StringUtils;
|
||||
import app.organicmaps.sdk.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.widget.placepage.EditBookmarkFragment;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
public class PlacePageBookmarkFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener,
|
||||
Observer<MapObject>,
|
||||
EditBookmarkFragment.EditBookmarkListener
|
||||
public class PlacePageBookmarkFragment extends Fragment implements View.OnLongClickListener, Observer<MapObject>
|
||||
{
|
||||
private View mFrame;
|
||||
private MaterialTextView mTvBookmarkNote;
|
||||
@@ -60,8 +55,6 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
|
||||
mFrame = view;
|
||||
mTvBookmarkNote = mFrame.findViewById(R.id.tv__bookmark_notes);
|
||||
mTvBookmarkNote.setOnLongClickListener(this);
|
||||
final View editBookmarkBtn = mFrame.findViewById(R.id.tv__bookmark_edit);
|
||||
editBookmarkBtn.setOnClickListener(this);
|
||||
}
|
||||
|
||||
private void initWebView()
|
||||
@@ -119,14 +112,6 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
final FragmentActivity activity = requireActivity();
|
||||
EditBookmarkFragment.editBookmark(currentBookmark.getCategoryId(), currentBookmark.getBookmarkId(), activity,
|
||||
getChildFragmentManager(), PlacePageBookmarkFragment.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v)
|
||||
{
|
||||
@@ -156,13 +141,4 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
|
||||
updateBookmarkDetails();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBookmarkSaved(long bookmarkId, boolean movedFromCategory)
|
||||
{
|
||||
Bookmark updatedBookmark = BookmarkManager.INSTANCE.updateBookmarkPlacePage(bookmarkId);
|
||||
if (updatedBookmark == null)
|
||||
return;
|
||||
mViewModel.setMapObject(updatedBookmark);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.bookmarks.data.Track;
|
||||
import app.organicmaps.sdk.util.UiUtils;
|
||||
import app.organicmaps.widget.placepage.ElevationProfileViewRenderer;
|
||||
import app.organicmaps.widget.placepage.PlacePageStateListener;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
|
||||
public class PlacePageTrackFragment extends Fragment
|
||||
implements PlacePageStateListener, Observer<MapObject>, BookmarkManager.OnElevationActivePointChangedListener,
|
||||
BookmarkManager.OnElevationCurrentPositionChangedListener
|
||||
{
|
||||
private PlacePageViewModel mViewModel;
|
||||
@Nullable
|
||||
private Track mTrack;
|
||||
private ElevationProfileViewRenderer mElevationProfileViewRenderer;
|
||||
private View mFrame;
|
||||
private View mElevationProfileView;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
mViewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
|
||||
return inflater.inflate(R.layout.placepage_track_fragment, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mElevationProfileViewRenderer = new ElevationProfileViewRenderer();
|
||||
|
||||
mFrame = view;
|
||||
mElevationProfileView = mFrame.findViewById(R.id.elevation_profile);
|
||||
mElevationProfileViewRenderer.initialize(mElevationProfileView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(this);
|
||||
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(this);
|
||||
mViewModel.getMapObject().observe(requireActivity(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
mViewModel.getMapObject().removeObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(null);
|
||||
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(@Nullable MapObject mapObject)
|
||||
{
|
||||
// MapObject could be something else than a Track if the user already has the place page
|
||||
// opened and clicks on a non-Track POI.
|
||||
// This callback would be called before the fragment had time to be destroyed
|
||||
if (mapObject != null && mapObject.isTrack())
|
||||
{
|
||||
Track track = (Track) mapObject;
|
||||
if (track.isElevationInfoHasValue())
|
||||
{
|
||||
if (mTrack == null || mTrack.getTrackId() != track.getTrackId())
|
||||
{
|
||||
mElevationProfileViewRenderer.render(track);
|
||||
UiUtils.show(mElevationProfileView);
|
||||
}
|
||||
}
|
||||
else
|
||||
UiUtils.hide(mElevationProfileView);
|
||||
mTrack = track;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onElevationActivePointChanged()
|
||||
{
|
||||
if (mTrack == null)
|
||||
return;
|
||||
mElevationProfileViewRenderer.onChartElevationActivePointChanged();
|
||||
ElevationInfo.Point point = BookmarkManager.INSTANCE.getElevationActivePointCoordinates(mTrack.getTrackId());
|
||||
mViewModel.modifyMapObjectPointSilently(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentPositionChanged()
|
||||
{
|
||||
mElevationProfileViewRenderer.onChartCurrentPositionChanged();
|
||||
}
|
||||
}
|
||||
10
android/app/src/main/res/drawable/ic_distance_travelled.xml
Normal file
10
android/app/src/main/res/drawable/ic_distance_travelled.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="590.91"
|
||||
android:viewportWidth="590.91"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M541.67,295.45l-86.21,-86.21l0,71.21l-320,0l0,-71.21l-86.21,86.21l86.21,86.21l0,-71.21l320,0l0,71.21z" />
|
||||
</vector>
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/elevation_profile"
|
||||
android:layout_width="@dimen/place_page_width"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/margin_base"
|
||||
android:paddingBottom="@dimen/margin_base"
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
<app.organicmaps.widget.placepage.ElevationProfileChart
|
||||
android:id="@+id/elevation_profile_chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true" />
|
||||
<app.organicmaps.widget.placepage.FloatingMarkerView
|
||||
android:id="@+id/floating_marker"
|
||||
android:visibility="gone"
|
||||
|
||||
@@ -1,37 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/elevation_profile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/margin_half_plus"
|
||||
android:paddingBottom="@dimen/margin_base"
|
||||
android:background="?cardBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:fillViewport="true"
|
||||
android:focusable="true"
|
||||
app:behavior_peekHeight="@dimen/elevation_profile_peek_height"
|
||||
app:layout_behavior="@string/placepage_behavior">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:id="@+id/pull_icon_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/margin_half"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:layout_marginBottom="@dimen/margin_eighth"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:id="@+id/pull_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
<include layout="@layout/elevation_profile_internal" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -4,22 +4,188 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="@layout/elevation_profile_bottom_sheet">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
<LinearLayout
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/margin_half"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:paddingBottom="@dimen/margin_base"
|
||||
android:textAppearance="?fontHeadline6"
|
||||
tools:text="Xindian Shitoushan Trail" />
|
||||
<include
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:paddingTop="@dimen/margin_half"
|
||||
android:paddingBottom="@dimen/margin_base"
|
||||
android:textAppearance="?fontHeadline6"
|
||||
tools:text="Xindian Shitoushan Trail" />
|
||||
<include
|
||||
layout="@layout/list_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
layout="@layout/list_divider" />
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:layout_marginTop="@dimen/margin_quarter"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_marginBottom="@dimen/margin_half_plus_eight"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
<!--card one-->
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
<LinearLayout
|
||||
android:id="@+id/ascent_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="@dimen/margin_base_plus_quarter"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
app:srcCompat="@drawable/ic_ascent"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:id="@+id/ascent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/ascent_container"
|
||||
android:layout_alignStart="@+id/ascent_container"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_ascent"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
</RelativeLayout>
|
||||
<!--card two-->
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
<LinearLayout
|
||||
android:id="@+id/descent_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="@dimen/margin_base_plus_quarter"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
app:srcCompat="@drawable/ic_descent"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:id="@+id/descent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/descent_container"
|
||||
android:layout_alignStart="@+id/descent_container"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_descent"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
</RelativeLayout>
|
||||
<!--card three-->
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:id="@+id/max_height_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
app:srcCompat="@drawable/ic_maxalt"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:id="@+id/max_altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/max_height_container"
|
||||
android:layout_alignStart="@+id/max_height_container"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_max_elevation"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
</RelativeLayout>
|
||||
<!--card four-->
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:id="@+id/min_elevation_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
app:srcCompat="@drawable/ic_minalt"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:id="@+id/min_altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/min_elevation_container"
|
||||
android:layout_alignStart="@+id/min_elevation_container"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_min_elevation"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/chart_container"
|
||||
android:layout_width="match_parent"
|
||||
@@ -27,142 +193,13 @@
|
||||
android:gravity="center"
|
||||
android:minHeight="@dimen/elevation_profile_chart_min_height"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/elevation_profile"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_base"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:minHeight="@dimen/elevation_profile_chart_info_min_height"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
android:layout_weight="1"
|
||||
android:background="?elevationProfilePropertyBg"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_quarter_plus">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_ascent"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_eighth"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_ascent"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
<TextView
|
||||
android:id="@+id/ascent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
android:layout_weight="1"
|
||||
android:background="?elevationProfilePropertyBg"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_quarter_plus">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_descent"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_eighth"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_descent"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
<TextView
|
||||
android:id="@+id/descent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
android:layout_weight="1"
|
||||
android:background="?elevationProfilePropertyBg"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_quarter_plus">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_maxalt"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_eighth"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_max_elevation"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
<TextView
|
||||
android:id="@+id/max_altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?elevationProfilePropertyBg"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_quarter_plus">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_minalt"
|
||||
app:tint="?elevationProfilePropIconTint" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_eighth"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/elevation_profile_min_elevation"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body5" />
|
||||
<TextView
|
||||
android:id="@+id/min_altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
tools:text="10000 m" />
|
||||
</LinearLayout>
|
||||
<include layout="@layout/elevation_profile" />
|
||||
</LinearLayout>
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_base"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginTop="@dimen/margin_quarter_plus"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:orientation="horizontal">
|
||||
<LinearLayout
|
||||
@@ -174,21 +211,21 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:text="@string/elevation_profile_difficulty"/>
|
||||
android:text="@string/elevation_profile_difficulty"
|
||||
android:textAppearance="?android:textAppearance" />
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="@dimen/elevation_profile_dot_levels_margin"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="@dimen/margin_half_plus_eight">
|
||||
android:layout_marginStart="@dimen/margin_half_plus_eight"
|
||||
android:layout_marginBottom="@dimen/elevation_profile_dot_levels_margin"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:id="@+id/difficulty_level_1"
|
||||
android:layout_width="@dimen/elevation_profile_difficulty_dot_size"
|
||||
android:layout_height="@dimen/elevation_profile_difficulty_dot_size"
|
||||
android:background="@drawable/dot_elevation_difficulty"
|
||||
android:enabled="false"/>
|
||||
android:enabled="false" />
|
||||
<TextView
|
||||
android:id="@+id/difficulty_level_2"
|
||||
android:layout_width="@dimen/elevation_profile_difficulty_dot_size"
|
||||
@@ -196,37 +233,37 @@
|
||||
android:layout_marginStart="@dimen/margin_quarter"
|
||||
android:layout_marginEnd="@dimen/margin_quarter"
|
||||
android:background="@drawable/dot_elevation_difficulty"
|
||||
android:enabled="false"/>
|
||||
android:enabled="false" />
|
||||
<TextView
|
||||
android:id="@+id/difficulty_level_3"
|
||||
android:layout_width="@dimen/elevation_profile_difficulty_dot_size"
|
||||
android:layout_height="@dimen/elevation_profile_difficulty_dot_size"
|
||||
android:background="@drawable/dot_elevation_difficulty"
|
||||
android:enabled="false"/>
|
||||
android:enabled="false" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_toEndOf="@id/difficulty_container"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:id="@+id/time_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_toEndOf="@id/difficulty_container"
|
||||
android:gravity="end"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:text="@string/elevation_profile_time" />
|
||||
android:text="@string/elevation_profile_time"
|
||||
android:textAppearance="?android:textAppearance" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_half"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textStyle="bold"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
tools:text="3 h. 25 min." />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
tools:ignore="Overdraw">
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="@dimen/elevation_profile_marker_width"
|
||||
android:layout_height="@dimen/elevation_profile_marker_width"
|
||||
android:layout_centerVertical="true"
|
||||
app:srcCompat="@drawable/ic_graph_point" />
|
||||
<RelativeLayout
|
||||
@@ -43,39 +43,41 @@
|
||||
android:maxWidth="@dimen/dialog_min_height"
|
||||
android:padding="@dimen/margin_quarter_plus"
|
||||
tools:ignore="UnusedAttribute">
|
||||
<TextView
|
||||
android:id="@+id/distance_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxWidth="@dimen/dialog_min_height"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/margin_half_plus_eight" />
|
||||
<ImageView
|
||||
android:id="@+id/distance_icon"
|
||||
android:layout_width="@dimen/margin_half_plus"
|
||||
android:layout_height="@dimen/margin_half_plus"
|
||||
app:srcCompat="@drawable/ic_distance_travelled"
|
||||
app:tint="?ppFloatingMarkerIconColor" />
|
||||
<TextView
|
||||
android:id="@+id/distance_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/distance_text"
|
||||
android:layout_marginStart="@dimen/margin_quarter"
|
||||
android:layout_toEndOf="@+id/distance_icon"
|
||||
android:ellipsize="end"
|
||||
android:maxWidth="@dimen/dialog_min_height"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/margin_half_plus_eight" />
|
||||
android:textSize="@dimen/margin_half_plus_eight"
|
||||
tools:text="10 km" />
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/distance_icon"
|
||||
android:layout_below="@id/distance_value"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:id="@+id/triangle"
|
||||
android:layout_width="@dimen/margin_half_plus"
|
||||
android:layout_height="@dimen/margin_half_plus"
|
||||
android:layout_width="@dimen/margin_half_plus_eight"
|
||||
android:layout_height="@dimen/margin_half_plus_eight"
|
||||
app:srcCompat="?elevationProfileSelectedPointTriangle" />
|
||||
<TextView
|
||||
android:id="@+id/altitude"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="900 m"
|
||||
android:layout_marginStart="@dimen/margin_quarter"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
|
||||
@@ -18,16 +18,6 @@
|
||||
android:textAppearance="?android:attr/textAppearance"
|
||||
tools:text="Long, long text Long, long text Long, long text Long, long text Long, long text Long, long text "/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tv__bookmark_edit"
|
||||
style="@style/PlacePageMetadataText.Button"
|
||||
android:gravity="center"
|
||||
android:layout_height="@dimen/height_block_base"
|
||||
android:background="?clickableBackground"
|
||||
android:paddingEnd="@dimen/margin_base"
|
||||
android:paddingStart="@dimen/margin_base"
|
||||
android:text="@string/placepage_edit_bookmark_button"/>
|
||||
|
||||
<include
|
||||
layout="@layout/divider_horizontal"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:layout="@layout/place_page_bookmark_fragment" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/place_page_wikipedia_fragment"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/margin_quarter">
|
||||
android:orientation="vertical">
|
||||
<include
|
||||
android:id="@+id/pull_icon_container"
|
||||
layout="@layout/bottom_sheet_handle" />
|
||||
@@ -180,4 +179,62 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/category_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/place_page_shadow_gap" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?ppBackground">
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?clickableBackground"
|
||||
android:layout_centerVertical="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingVertical="5dp" />
|
||||
<TextView
|
||||
android:id="@+id/tv__category"
|
||||
style="@style/PlacePageMetadataText.Button"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@id/edit_Bookmark"
|
||||
android:layout_toEndOf="@id/item_icon"
|
||||
android:background="?clickableBackground"
|
||||
android:paddingStart="@dimen/margin_quarter"
|
||||
android:paddingEnd="@dimen/margin_quarter"
|
||||
android:textAllCaps="false"
|
||||
tools:text="@string/categories" />
|
||||
<ImageView
|
||||
android:id="@+id/edit_Bookmark"
|
||||
style="@style/MwmWidget.Editor.MetadataIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?clickableBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/ic_edit" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/place_page_track_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:layout="@layout/placepage_track_fragment" />
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:background="@color/black_8"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/margin_half" />
|
||||
12
android/app/src/main/res/layout/placepage_track_fragment.xml
Normal file
12
android/app/src/main/res/layout/placepage_track_fragment.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/place_page_track_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/place_page_shadow_gap" />
|
||||
<include
|
||||
android:id="@+id/elevation_profile"
|
||||
layout="@layout/elevation_profile_bottom_sheet" />
|
||||
</LinearLayout>
|
||||
@@ -46,6 +46,8 @@
|
||||
<dimen name="place_page_width">320dp</dimen>
|
||||
<dimen name="place_page_buttons_height">56dp</dimen>
|
||||
<dimen name="place_page_top_button">40dp</dimen>
|
||||
<dimen name="place_page_icon_size">32dp</dimen>
|
||||
<dimen name="place_page_icon_mark_size">20dp</dimen>
|
||||
|
||||
<dimen name="downloader_status_size">40dp</dimen>
|
||||
<dimen name="search_progress_size">32dp</dimen>
|
||||
@@ -75,12 +77,13 @@
|
||||
<dimen name="viewport_min_width">300dp</dimen>
|
||||
<dimen name="elevation_profile_peek_height">260dp</dimen>
|
||||
<dimen name="elevation_profile_chart_min_height">144dp</dimen>
|
||||
<dimen name="elevation_profile_chart_info_min_height">68dp</dimen>
|
||||
<dimen name="elevation_profile_chart_info_min_height">54dp</dimen>
|
||||
<dimen name="elevation_profile_difficulty_dot_size">10dp</dimen>
|
||||
<dimen name="elevation_profile_content_height">144dp</dimen>
|
||||
<dimen name="elevation_profile_height">108dp</dimen>
|
||||
<dimen name="elevation_profile_half_height">54dp</dimen>
|
||||
<dimen name="elevation_profile_height">80dp</dimen>
|
||||
<dimen name="elevation_profile_half_height">40dp</dimen>
|
||||
<dimen name="elevation_profile_dot_levels_margin">3dp</dimen>
|
||||
<dimen name="elevation_profile_marker_width">25dp</dimen>
|
||||
<dimen name="map_button_size">48dp</dimen>
|
||||
<dimen name="map_button_icon_size">28dp</dimen>
|
||||
<dimen name="map_button_arrow_icon_size">34dp</dimen>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<dimen name="text_size_body_3">14sp</dimen>
|
||||
<dimen name="text_size_body_4">12sp</dimen>
|
||||
<dimen name="text_size_body_5">10sp</dimen>
|
||||
<dimen name="text_size_body_6">8sp</dimen>
|
||||
<dimen name="text_size_caption">14sp</dimen>
|
||||
<dimen name="text_size_icon_title">10sp</dimen>
|
||||
<dimen name="text_size_button">16sp</dimen>
|
||||
|
||||
@@ -971,4 +971,5 @@
|
||||
<string name="closed_now">Closed now</string>
|
||||
<!-- Used in place page preview for next open/close time. eg. "closing in 30 min • at 19:30" -->
|
||||
<string name="at">at %s</string>
|
||||
<string name="PP_track_bottom_sheet_title">Save Track As</string>
|
||||
</resources>
|
||||
|
||||
@@ -93,6 +93,11 @@
|
||||
<item name="android:textColor">?android:textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmTextAppearance.Body6">
|
||||
<item name="android:textSize">@dimen/text_size_body_6</item>
|
||||
<item name="android:textColor">?android:textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmTextAppearance.Button">
|
||||
<item name="android:textSize">@dimen/text_size_button</item>
|
||||
<item name="android:textColor">?colorSecondary</item>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<attr name="iconTintLight" format="color" />
|
||||
<attr name="ppBackground" format="color" />
|
||||
<attr name="ppButtonsBackground" format="color" />
|
||||
<attr name="ppFloatingMarkerIconColor" format="color" />
|
||||
<attr name="navNextTurnFrame" format="reference" />
|
||||
<attr name="navNextNextTurnFrame" format="reference" />
|
||||
<attr name="navLanesBackgroundColor" format="reference" />
|
||||
|
||||
@@ -921,17 +921,7 @@ JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Framework_nativePlacePageActivat
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
auto const & info = frm()->GetCurrentPlacePageInfo();
|
||||
jni::TScopedLocalRef placePageDataRef(env, nullptr);
|
||||
if (info.IsTrack())
|
||||
{
|
||||
// todo: (KK) implement elevation info handling for the proper track selection
|
||||
auto const & track = frm()->GetBookmarkManager().GetTrack(info.GetTrackId());
|
||||
auto const & elevationInfo = track->GetElevationInfo();
|
||||
if (elevationInfo.has_value())
|
||||
placePageDataRef.reset(usermark_helper::CreateElevationInfo(env, elevationInfo.value()));
|
||||
}
|
||||
if (!placePageDataRef)
|
||||
placePageDataRef.reset(usermark_helper::CreateMapObject(env, info));
|
||||
|
||||
placePageDataRef.reset(usermark_helper::CreateMapObject(env, info));
|
||||
env->CallVoidMethod(g_placePageActivationListener, activatedId, placePageDataRef.get());
|
||||
};
|
||||
auto const closePlacePage = [deactivateId]()
|
||||
|
||||
@@ -88,6 +88,47 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info, int mapObje
|
||||
return mapObject;
|
||||
}
|
||||
|
||||
jobject CreateTrack(JNIEnv * env, place_page::Info const & info, jni::TScopedLocalObjectArrayRef const & jrawTypes,
|
||||
jni::TScopedLocalRef const & routingPointInfo, jobject const & popularity)
|
||||
{
|
||||
static jmethodID const ctorId =
|
||||
jni::GetConstructorID(env, g_trackClazz,
|
||||
"(Lapp/organicmaps/sdk/bookmarks/data/FeatureId;JJLjava/lang/String;"
|
||||
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
|
||||
"Lapp/organicmaps/sdk/routing/RoutePointInfo;"
|
||||
"ILapp/organicmaps/sdk/search/Popularity;Ljava/lang/String;"
|
||||
"[Ljava/lang/String;ILapp/organicmaps/sdk/util/Distance;DD)V");
|
||||
static jmethodID const featureCtorId = jni::GetConstructorID(env, g_featureIdClazz, "(Ljava/lang/String;JI)V");
|
||||
|
||||
auto const trackId = info.GetTrackId();
|
||||
auto const track = frm()->GetBookmarkManager().GetTrack(trackId);
|
||||
dp::Color nColor = track->GetColor(0);
|
||||
|
||||
jint androidColor =
|
||||
shift(nColor.GetAlpha(), 24) + shift(nColor.GetRed(), 16) + shift(nColor.GetGreen(), 8) + nColor.GetBlue();
|
||||
|
||||
auto const categoryId = track->GetGroupId();
|
||||
ms::LatLon const ll = info.GetLatLon();
|
||||
jni::TScopedLocalRef jMwmName(env, jni::ToJavaString(env, info.GetID().GetMwmName()));
|
||||
jni::TScopedLocalRef jFeatureId(env, env->NewObject(g_featureIdClazz, featureCtorId, jMwmName.get(),
|
||||
(jlong)info.GetID().GetMwmVersion(), (jint)info.GetID().m_index));
|
||||
jni::TScopedLocalRef jTitle(env, jni::ToJavaString(env, info.GetTitle()));
|
||||
jni::TScopedLocalRef jSecondaryTitle(env, jni::ToJavaString(env, info.GetSecondaryTitle()));
|
||||
jni::TScopedLocalRef jSubtitle(env, jni::ToJavaString(env, info.GetSubtitle()));
|
||||
jni::TScopedLocalRef jAddress(env, jni::ToJavaString(env, info.GetSecondarySubtitle()));
|
||||
jni::TScopedLocalRef jWikiDescription(env, jni::ToJavaString(env, info.GetWikiDescription()));
|
||||
jobject mapObject =
|
||||
env->NewObject(g_trackClazz, ctorId, jFeatureId.get(), static_cast<jlong>(categoryId),
|
||||
static_cast<jlong>(trackId), jTitle.get(), jSecondaryTitle.get(), jSubtitle.get(), jAddress.get(),
|
||||
routingPointInfo.get(), info.GetOpeningMode(), popularity, jWikiDescription.get(), jrawTypes.get(),
|
||||
androidColor, ToJavaDistance(env, platform::Distance::CreateFormatted(track->GetLengthMeters())),
|
||||
static_cast<jdouble>(ll.m_lat), static_cast<jdouble>(ll.m_lon));
|
||||
|
||||
if (info.HasMetadata())
|
||||
InjectMetadata(env, g_mapObjectClazz, mapObject, info);
|
||||
return mapObject;
|
||||
}
|
||||
|
||||
jobject CreateBookmark(JNIEnv * env, place_page::Info const & info, jni::TScopedLocalObjectArrayRef const & jrawTypes,
|
||||
jni::TScopedLocalRef const & routingPointInfo, jobject const & popularity)
|
||||
{
|
||||
@@ -129,10 +170,11 @@ jobject CreateElevationPoint(JNIEnv * env, ElevationInfo::Point const & point)
|
||||
{
|
||||
static jclass const pointClass =
|
||||
jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/ElevationInfo$Point");
|
||||
// public Point(double distance, int altitude)
|
||||
static jmethodID const pointCtorId = jni::GetConstructorID(env, pointClass, "(DI)V");
|
||||
return env->NewObject(pointClass, pointCtorId, static_cast<jdouble>(point.m_distance),
|
||||
static_cast<jint>(point.m_point.GetAltitude()));
|
||||
// public Point(double distance, int altitude, double latitude, double longitude)
|
||||
static jmethodID const pointCtorId = jni::GetConstructorID(env, pointClass, "(DIDD)V");
|
||||
return env->NewObject(
|
||||
pointClass, pointCtorId, static_cast<jdouble>(point.m_distance), static_cast<jint>(point.m_point.GetAltitude()),
|
||||
static_cast<jdouble>(point.m_point.GetPoint().x), static_cast<jdouble>(point.m_point.GetPoint().y));
|
||||
}
|
||||
|
||||
jobjectArray ToElevationPointArray(JNIEnv * env, ElevationInfo::Points const & points)
|
||||
@@ -146,22 +188,12 @@ jobjectArray ToElevationPointArray(JNIEnv * env, ElevationInfo::Points const & p
|
||||
|
||||
jobject CreateElevationInfo(JNIEnv * env, ElevationInfo const & info)
|
||||
{
|
||||
// public ElevationInfo(long trackId, @NonNull String name, @NonNull Point[] points,
|
||||
// int ascent, int descent, int minAltitude, int maxAltitude, int difficulty,
|
||||
// long m_duration)
|
||||
static jmethodID const ctorId = jni::GetConstructorID(env, g_elevationInfoClazz,
|
||||
"(JLjava/lang/String;Ljava/lang/String;"
|
||||
"[Lapp/organicmaps/sdk/bookmarks/data/ElevationInfo$Point;"
|
||||
"IIIIIJ)V");
|
||||
// public ElevationInfo(@NonNull Point[] points, int difficulty);
|
||||
static jmethodID const ctorId =
|
||||
jni::GetConstructorID(env, g_elevationInfoClazz, "([Lapp/organicmaps/sdk/bookmarks/data/ElevationInfo$Point;I)V");
|
||||
|
||||
jni::TScopedLocalObjectArrayRef jPoints(env, ToElevationPointArray(env, info.GetPoints()));
|
||||
// TODO (KK): elevation info should have only the elevation data - see the
|
||||
// https://github.com/organicmaps/organicmaps/pull/10063
|
||||
return env->NewObject(g_elevationInfoClazz, ctorId, jPoints.get(),
|
||||
// static_cast<jint>(info.GetAscent()),
|
||||
// static_cast<jint>(info.GetDescent()),
|
||||
// static_cast<jint>(info.GetMinAltitude()),
|
||||
// static_cast<jint>(info.GetMaxAltitude()),
|
||||
static_cast<jint>(info.GetDifficulty()));
|
||||
return env->NewObject(g_elevationInfoClazz, ctorId, jPoints.get(), static_cast<jint>(info.GetDifficulty()));
|
||||
}
|
||||
|
||||
jobject CreateMapObject(JNIEnv * env, place_page::Info const & info)
|
||||
@@ -193,6 +225,9 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info)
|
||||
routingPointInfo.get(), popularity, jrawTypes.get());
|
||||
}
|
||||
|
||||
if (info.IsTrack())
|
||||
return CreateTrack(env, info, jrawTypes, routingPointInfo, popularity);
|
||||
|
||||
return CreateMapObject(env, info, kPoi, ll.m_lat, ll.m_lon, true /* parseMeta */, false /* parseApi */,
|
||||
routingPointInfo.get(), popularity, jrawTypes.get());
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ static constexpr int kApiPoint = 1;
|
||||
static constexpr int kBookmark = 2;
|
||||
static constexpr int kMyPosition = 3;
|
||||
static constexpr int kSearch = 4;
|
||||
static constexpr int kTrack = 5;
|
||||
|
||||
static constexpr int kPriceRateUndefined = -1;
|
||||
|
||||
@@ -34,6 +35,9 @@ void InjectMetadata(JNIEnv * env, jclass clazz, jobject const mapObject, feature
|
||||
|
||||
jobject CreateMapObject(JNIEnv * env, place_page::Info const & info);
|
||||
|
||||
jobject CreateTrack(JNIEnv * env, place_page::Info const & info, jni::TScopedLocalObjectArrayRef const & jrawTypes,
|
||||
jni::TScopedLocalRef const & routingPointInfo, jobject const & popularity);
|
||||
|
||||
jobject CreateElevationInfo(JNIEnv * env, ElevationInfo const & info);
|
||||
|
||||
jobjectArray ToRatingArray(JNIEnv * env, std::vector<std::string> const & ratingCategories);
|
||||
|
||||
@@ -447,6 +447,16 @@ JNIEXPORT jobject JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManage
|
||||
return usermark_helper::CreateMapObject(env, g_framework->GetPlacePageInfo());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeUpdateTrackPlacePage(JNIEnv * env,
|
||||
jobject,
|
||||
jlong trackId)
|
||||
{
|
||||
if (!frm()->HasPlacePageInfo())
|
||||
return;
|
||||
|
||||
frm()->UpdatePlacePageInfoForCurrentSelection();
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeGetBookmarkInfo(JNIEnv * env,
|
||||
jobject,
|
||||
jlong bmkId)
|
||||
@@ -824,14 +834,12 @@ Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeRemoveElevationCur
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeSetElevationActivePoint(
|
||||
JNIEnv *, jclass, jlong trackId, jdouble distanceInMeters)
|
||||
JNIEnv *, jclass, jlong trackId, jdouble distanceInMeters, jdouble latitude, jdouble longitude)
|
||||
{
|
||||
auto & bm = frm()->GetBookmarkManager();
|
||||
bm.SetElevationActivePoint(
|
||||
static_cast<kml::TrackId>(trackId),
|
||||
{0,
|
||||
0}, // todo(KK): replace with coordinates from the elevation profile point to show selection mark on the track
|
||||
static_cast<double>(distanceInMeters));
|
||||
bm.SetElevationActivePoint(static_cast<kml::TrackId>(trackId),
|
||||
m2::PointD(static_cast<double>(latitude), static_cast<double>(longitude)),
|
||||
static_cast<double>(distanceInMeters));
|
||||
}
|
||||
|
||||
JNIEXPORT jdouble JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeGetElevationActivePointDistance(
|
||||
@@ -858,4 +866,41 @@ Java_app_organicmaps_sdk_widget_placepage_PlacePageButtonFactory_nativeHasRecent
|
||||
{
|
||||
return frm()->GetBookmarkManager().HasRecentlyDeletedBookmark();
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeGetTrackElevationInfo(
|
||||
JNIEnv * env, jclass clazz, jlong track_id)
|
||||
{
|
||||
auto const & track = frm()->GetBookmarkManager().GetTrack(track_id);
|
||||
auto const & elevationInfo = track->GetElevationInfo();
|
||||
return usermark_helper::CreateElevationInfo(env, elevationInfo.value());
|
||||
}
|
||||
JNIEXPORT jboolean JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeIsElevationInfoHasValue(
|
||||
JNIEnv * env, jclass clazz, jlong track_id)
|
||||
{
|
||||
return static_cast<jboolean>(frm()->GetBookmarkManager().GetTrack(track_id)->GetElevationInfo().has_value());
|
||||
}
|
||||
JNIEXPORT jobject JNICALL Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeGetTrackStatistics(
|
||||
JNIEnv * env, jclass clazz, jlong track_id)
|
||||
{
|
||||
static jmethodID const cId = jni::GetConstructorID(env, g_trackStatisticsClazz, "(DDDDII)V");
|
||||
auto const trackStats = frm()->GetBookmarkManager().GetTrack(track_id)->GetStatistics();
|
||||
return env->NewObject(g_trackStatisticsClazz, cId, static_cast<jdouble>(trackStats.m_length),
|
||||
static_cast<jdouble>(trackStats.m_duration), static_cast<jdouble>(trackStats.m_ascent),
|
||||
static_cast<jdouble>(trackStats.m_descent), static_cast<jint>(trackStats.m_minElevation),
|
||||
static_cast<jint>(trackStats.m_maxElevation));
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_app_organicmaps_sdk_bookmarks_data_BookmarkManager_nativeGetElevationActivePointCoordinates(JNIEnv * env,
|
||||
jclass clazz,
|
||||
jlong track_id)
|
||||
{
|
||||
static jclass const pointClass =
|
||||
jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/ElevationInfo$Point");
|
||||
static jmethodID const pointCtorId = jni::GetConstructorID(env, pointClass, "(DIDD)V");
|
||||
auto const & trackInfo = frm()->GetBookmarkManager().GetTrackSelectionInfo(track_id);
|
||||
auto const latlon = mercator::ToLatLon(trackInfo.m_trackPoint);
|
||||
return env->NewObject(pointClass, pointCtorId, 0.0, 0, static_cast<jdouble>(latlon.m_lat),
|
||||
static_cast<jdouble>(latlon.m_lon));
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -21,6 +21,8 @@ extern JavaVM * GetJVM()
|
||||
jclass g_mapObjectClazz;
|
||||
jclass g_featureIdClazz;
|
||||
jclass g_bookmarkClazz;
|
||||
jclass g_trackClazz;
|
||||
jclass g_trackStatisticsClazz;
|
||||
jclass g_httpClientClazz;
|
||||
jclass g_httpParamsClazz;
|
||||
jclass g_platformSocketClazz;
|
||||
@@ -57,6 +59,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * jvm, void *)
|
||||
JNIEnv * env = jni::GetEnv();
|
||||
g_mapObjectClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/MapObject");
|
||||
g_featureIdClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/FeatureId");
|
||||
g_trackClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/Track");
|
||||
g_trackStatisticsClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/TrackStatistics");
|
||||
g_bookmarkClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/bookmarks/data/Bookmark");
|
||||
g_httpClientClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/util/HttpClient");
|
||||
g_httpParamsClazz = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/util/HttpClient$Params");
|
||||
@@ -85,6 +89,8 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *)
|
||||
env->DeleteGlobalRef(g_mapObjectClazz);
|
||||
env->DeleteGlobalRef(g_featureIdClazz);
|
||||
env->DeleteGlobalRef(g_bookmarkClazz);
|
||||
env->DeleteGlobalRef(g_trackClazz);
|
||||
env->DeleteGlobalRef(g_trackStatisticsClazz);
|
||||
env->DeleteGlobalRef(g_httpClientClazz);
|
||||
env->DeleteGlobalRef(g_httpParamsClazz);
|
||||
env->DeleteGlobalRef(g_platformSocketClazz);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
extern jclass g_mapObjectClazz;
|
||||
extern jclass g_featureIdClazz;
|
||||
extern jclass g_bookmarkClazz;
|
||||
extern jclass g_trackClazz;
|
||||
extern jclass g_trackStatisticsClazz;
|
||||
extern jclass g_httpClientClazz;
|
||||
extern jclass g_httpParamsClazz;
|
||||
extern jclass g_platformSocketClazz;
|
||||
|
||||
@@ -866,7 +866,7 @@ void BookmarkManager::SetElevationActivePoint(kml::TrackId const & trackId, m2::
|
||||
auto const track = GetTrack(trackId);
|
||||
CHECK(track != nullptr, ());
|
||||
|
||||
SetTrackSelectionInfo({trackId, pt, targetDistance}, false /* notifyListeners */);
|
||||
SetTrackSelectionInfo({trackId, pt, targetDistance}, true /* notifyListeners */);
|
||||
|
||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SelectObject, df::SelectionShape::ESelectedObject::OBJECT_TRACK, pt,
|
||||
FeatureID(), false /* isAnim */, false /* isGeometrySelectionAllowed */,
|
||||
|
||||
@@ -2173,16 +2173,8 @@ place_page::Info Framework::BuildPlacePageInfo(place_page::BuildInfo const & bui
|
||||
FeatureID selectedFeature = buildInfo.m_featureId;
|
||||
auto const isFeatureMatchingEnabled = buildInfo.IsFeatureMatchingEnabled();
|
||||
|
||||
// @TODO: (KK) Enable track selection.
|
||||
// The isTrackSelectionEnabled should be removed to enable the track selection when the UI will be implemented.
|
||||
#if defined(TARGET_OS_IPHONE)
|
||||
bool constexpr isTrackSelectionEnabled = true;
|
||||
#else
|
||||
bool constexpr isTrackSelectionEnabled = false;
|
||||
#endif
|
||||
|
||||
// Using VisualParams inside FindTrackInTapPosition/GetDefaultTapRect requires drapeEngine.
|
||||
if (isTrackSelectionEnabled && m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() &&
|
||||
if (m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() &&
|
||||
!(isFeatureMatchingEnabled && selectedFeature.IsValid()))
|
||||
{
|
||||
Track::TrackSelectionInfo trackSelectionInfo;
|
||||
|
||||
Reference in New Issue
Block a user