Work on gpx details view

This commit is contained in:
Alexey Kulish 2017-03-06 18:31:12 +03:00
parent b93c380c68
commit 32a0dd426e
15 changed files with 773 additions and 582 deletions

View file

@ -6,7 +6,8 @@
android:layout_height="match_parent"
android:background="@color/color_transparent"
android:clickable="true"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
xmlns:osmand="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:id="@+id/top_bar_layout"
@ -14,6 +15,7 @@
android:layout_height="wrap_content"
android:minHeight="@dimen/dashboard_map_toolbar"
android:gravity="center_vertical"
android:clickable="true"
android:background="@drawable/gradient_toolbar"
android:orientation="horizontal">
@ -36,7 +38,7 @@
android:paddingBottom="10dp"
android:paddingTop="10dp">
<TextView
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/top_bar_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -45,8 +47,9 @@
android:gravity="center_vertical"
android:lines="1"
android:singleLine="true"
android:textColor="?android:textColorPrimary"
android:textColor="@color/color_white"
android:textSize="@dimen/abc_text_size_medium_material"
osmand:typeface="@string/font_roboto_medium"
android:text="@string/rendering_category_details"/>
<TextView
@ -63,6 +66,8 @@
</LinearLayout>
</LinearLayout>
<LinearLayout
@ -85,7 +90,7 @@
android:orientation="horizontal">
<LinearLayout
android:id="@+id/left_axis"
android:id="@+id/y_axis"
android:layout_width="0dp"
android:layout_height="@dimen/list_item_height"
android:layout_weight="1"
@ -95,7 +100,7 @@
android:gravity="center_vertical">
<ImageView
android:id="@+id/left_axis_icon"
android:id="@+id/y_axis_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/list_content_padding"
@ -103,7 +108,7 @@
android:src="@drawable/ic_action_altitude_average"/>
<TextView
android:id="@+id/left_axis_title"
android:id="@+id/y_axis_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -113,7 +118,7 @@
tools:text="@string/altitude"/>
<ImageView
android:id="@+id/left_axis_arrow"
android:id="@+id/y_axis_arrow"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/list_content_padding"
@ -122,7 +127,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/right_axis"
android:id="@+id/x_axis"
android:layout_width="0dp"
android:layout_height="@dimen/list_item_height"
android:layout_weight="1"
@ -139,25 +144,25 @@
android:focusable="false"/>
<ImageView
android:id="@+id/right_axis_icon"
android:id="@+id/x_axis_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/list_content_padding"
android:layout_marginRight="@dimen/list_content_padding"
android:src="@drawable/ic_action_speed"/>
android:src="@drawable/ic_action_marker_dark"/>
<TextView
android:id="@+id/right_axis_title"
android:id="@+id/x_axis_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginRight="@dimen/list_content_padding"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/map_widget_speed"/>
tools:text="@string/distance"/>
<ImageView
android:id="@+id/right_axis_arrow"
android:id="@+id/x_axis_arrow"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="@dimen/list_content_padding"

View file

@ -9,6 +9,7 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="shared_string_slope">Slope</string>
<string name="add_new_folder">Add new folder</string>
<string name="points_delete_multiple_succesful">Point(s) deleted successfully.</string>
<string name="points_delete_multiple">You are going to delete %1$d point(s). Are you sure?</string>

View file

@ -92,10 +92,14 @@ public class GPXUtilities {
}
public static class Elevation {
public double distance, elevation;
public double distance;
public int time;
public double elevation;
}
public static class Speed {
public double distance, speed;
public double distance;
public int time;
public double speed;
}
public static class WptPt extends GPXExtensions implements LocationPoint {
@ -311,6 +315,7 @@ public class GPXUtilities {
float totalElevation = 0;
int elevationPoints = 0;
int speedCount = 0;
int timeDiff = 0;
double totalSpeedSum = 0;
points = 0;
@ -443,6 +448,8 @@ public class GPXUtilities {
// a little more exact, also seems slightly faster:
net.osmand.Location.distanceBetween(prev.lat, prev.lon, point.lat, point.lon, calculations);
totalDistance += calculations[0];
point.distance = totalDistance;
timeDiff = (int)((point.time - prev.time) / 1000);
// Motion detection:
// speed > 0 uses GPS chipset's motion detection
@ -459,8 +466,10 @@ public class GPXUtilities {
}
elevation1.time = timeDiff;
elevation1.distance = (j > 0) ? calculations[0] : 0;
elevationData.add(elevation1);
speed1.time = timeDiff;
speed1.distance = elevation1.distance;
speedData.add(speed1);
}

View file

@ -15,6 +15,8 @@ import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmandSettings.MetricsConstants;
import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.util.Algorithms;
import org.json.JSONArray;
@ -662,6 +664,10 @@ public class GpxSelectionHelper {
public Bitmap image;
public boolean expanded;
public WptPt locationOnMap;
public GPXDataSetType chartType;
public GPXDataSetAxisType chartAxisType = GPXDataSetAxisType.DISTANCE;
public Matrix chartMatrix;
public float chartHighlightPos = -1f;
}

View file

@ -45,7 +45,7 @@ public class OsmAndFormatter {
}
}
public static String getFormattedDurationShort(int seconds, OsmandApplication ctx) {
public static String getFormattedDurationShort(int seconds) {
int hours = seconds / (60 * 60);
int minutes = (seconds / 60) % 60;
int sec = seconds % 60;

View file

@ -54,6 +54,8 @@ import net.osmand.plus.AppInitializer;
import net.osmand.plus.AppInitializer.AppInitializeListener;
import net.osmand.plus.AppInitializer.InitEvents;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.MapMarkersHelper.MapMarker;
import net.osmand.plus.MapMarkersHelper.MapMarkerChangedListener;
import net.osmand.plus.OnDismissDialogFragmentListener;
@ -88,6 +90,8 @@ import net.osmand.plus.mapcontextmenu.MapContextMenuFragment;
import net.osmand.plus.mapcontextmenu.other.DestinationReachedMenu;
import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenu;
import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenuFragment;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenuFragment;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routing.RoutingHelper;
@ -442,6 +446,9 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
showQuickSearch(ShowQuickSearchMode.CURRENT, false);
return;
}
if (TrackDetailsMenu.isVisible()) {
getMapLayers().getMapControlsLayer().getTrackDetailsMenu().hide();
}
if (prevActivityIntent != null && getSupportFragmentManager().getBackStackEntryCount() == 0) {
prevActivityIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
LatLon loc = getMapLocation();
@ -780,7 +787,11 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
//mapContextMenu.setMapZoom(settings.getMapZoomToShow());
mapContextMenu.setMapZoom(tb.getZoom());
if (MapRouteInfoMenu.isVisible()) {
if (toShow instanceof GpxDisplayItem) {
TrackDetailsMenu trackDetailsMenu = mapLayers.getMapControlsLayer().getTrackDetailsMenu();
trackDetailsMenu.setGpxItem((GpxDisplayItem) toShow);
trackDetailsMenu.show();
} else if (MapRouteInfoMenu.isVisible()) {
mapContextMenu.showMinimized(latLonToShow, mapLabelToShow, toShow);
mapLayers.getMapControlsLayer().getMapRouteInfoMenu().updateMenu();
MapRouteInfoMenu.showLocationOnMap(this, latLonToShow.getLatitude(), latLonToShow.getLongitude());

View file

@ -43,6 +43,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenu;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper;
@ -227,10 +228,12 @@ public class ShowRouteInfoDialogFragment extends DialogFragment {
GPXTrackAnalysis analysis = gpx.getAnalysis(0);
if (analysis.totalDistance > 0) {
List<ILineDataSet> dataSets = new ArrayList<>();
GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, false, true);
GpxUiHelper.OrderedLineDataSet elevationDataSet =
GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, GPXDataSetAxisType.DISTANCE, false, true);
dataSets.add(elevationDataSet);
if (analysis.elevationData.size() > 1) {
GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, elevationDataSet.getValues(), true, true);
GpxUiHelper.OrderedLineDataSet slopeDataSet =
GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, GPXDataSetAxisType.DISTANCE, elevationDataSet.getValues(), true, true);
dataSets.add(slopeDataSet);
}
LineData data = new LineData(dataSets);

View file

@ -36,6 +36,7 @@ public class TrackActivity extends TabActivity {
public static final String TRACK_FILE_NAME = "TRACK_FILE_NAME";
public static final String CURRENT_RECORDING = "CURRENT_RECORDING";
protected List<WeakReference<Fragment>> fragList = new ArrayList<>();
protected PagerSlidingTabStrip slidingTabLayout;
private File file = null;
private GPXFile gpxFile;
private GpxDataItem gpxDataItem;
@ -43,6 +44,7 @@ public class TrackActivity extends TabActivity {
private long modifiedTime = -1;
private List<GpxDisplayGroup> displayGroups;
private List<GpxDisplayGroup> originalGroups = new ArrayList<>();
private boolean stopped = false;
@Override
public void onCreate(Bundle icicle) {
@ -69,7 +71,7 @@ public class TrackActivity extends TabActivity {
}
setContentView(R.layout.tab_content);
final PagerSlidingTabStrip slidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs);
slidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs);
if (slidingTabLayout != null) {
slidingTabLayout.setShouldExpand(true);
@ -85,34 +87,54 @@ public class TrackActivity extends TabActivity {
@Override
protected GPXFile doInBackground(Void... params) {
long startTime = System.currentTimeMillis();
GPXFile result = null;
if (file == null) {
return getMyApplication().getSavingTrackHelper().getCurrentGpx();
result = getMyApplication().getSavingTrackHelper().getCurrentGpx();
} else {
SelectedGpxFile selectedGpxFile = getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(file.getAbsolutePath());
if (selectedGpxFile != null && selectedGpxFile.getGpxFile() != null) {
result = selectedGpxFile.getGpxFile();
} else {
result = GPXUtilities.loadGPXFile(TrackActivity.this, file);
}
}
return GPXUtilities.loadGPXFile(TrackActivity.this, file);
if (result != null) {
while (System.currentTimeMillis() - startTime < 200) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// ignore
}
}
}
return result;
}
protected void onPostExecute(GPXFile result) {
setSupportProgressBarIndeterminateVisibility(false);
setGpx(result);
setGpxDataItem(getMyApplication().getGpxDatabase().getItem(file));
if (!stopped) {
setGpx(result);
setGpxDataItem(getMyApplication().getGpxDatabase().getItem(file));
for (WeakReference<Fragment> f : fragList) {
Fragment frag = f.get();
if (frag instanceof TrackSegmentFragment) {
((TrackSegmentFragment) frag).setContent();
} else if (frag instanceof TrackPointFragment) {
((TrackPointFragment) frag).setContent();
for (WeakReference<Fragment> f : fragList) {
Fragment frag = f.get();
if (frag instanceof TrackSegmentFragment) {
((TrackSegmentFragment) frag).updateContent();
} else if (frag instanceof TrackPointFragment) {
((TrackPointFragment) frag).setContent();
}
}
}
((OsmandFragmentPagerAdapter) mViewPager.getAdapter()).addTab(
getTabIndicator(R.string.gpx_track, TrackSegmentFragment.class));
if (isHavingWayPoints() || isHavingRoutePoints()) {
((OsmandFragmentPagerAdapter) mViewPager.getAdapter()).addTab(
getTabIndicator(R.string.points, TrackPointFragment.class));
} else {
slidingTabLayout.setVisibility(View.GONE);
getSupportActionBar().setElevation(AndroidUtils.dpToPx(getMyApplication(), 4f));
getTabIndicator(R.string.gpx_track, TrackSegmentFragment.class));
if (isHavingWayPoints() || isHavingRoutePoints()) {
((OsmandFragmentPagerAdapter) mViewPager.getAdapter()).addTab(
getTabIndicator(R.string.points, TrackPointFragment.class));
} else {
slidingTabLayout.setVisibility(View.GONE);
getSupportActionBar().setElevation(AndroidUtils.dpToPx(getMyApplication(), 4f));
}
}
}
}.execute((Void) null);
@ -164,7 +186,6 @@ public class TrackActivity extends TabActivity {
@Override
protected void onResume() {
super.onResume();
}
public OsmandApplication getMyApplication() {
@ -175,8 +196,12 @@ public class TrackActivity extends TabActivity {
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
stopped = true;
}
public Toolbar getClearToolbar(boolean visible) {
final Toolbar tb = (Toolbar) findViewById(R.id.bottomControls);

View file

@ -9,8 +9,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
@ -36,7 +34,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
@ -45,18 +42,13 @@ import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.ChartData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IFillFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.renderer.LineChartRenderer;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.ViewPortHandler;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
@ -67,6 +59,7 @@ import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.Elevation;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GPXUtilities.Speed;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.IconsCache;
@ -874,8 +867,6 @@ public class GpxUiHelper {
mChart.setExtraTopOffset(24f);
mChart.setExtraBottomOffset(16f);
mChart.setRenderer(new SplineRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler()));
// create a custom MarkerView (extend MarkerView) and specify the layout
// to use for it
GPXMarkerView mv = new GPXMarkerView(mChart.getContext());
@ -914,7 +905,7 @@ public class GpxUiHelper {
legend.setEnabled(false);
}
private static float getXAxisParams(OsmandApplication ctx, float meters, float[] koef, StringBuilder format, StringBuilder unit) {
private static float setupXAxisDistance(OsmandApplication ctx, XAxis xAxis, float meters) {
OsmandSettings settings = ctx.getSettings();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
float divX;
@ -970,33 +961,70 @@ public class GpxUiHelper {
}
}
koef[0] = divX;
if (fmt != null) {
format.append(fmt);
}
unit.append(ctx.getString(mainUnitStr));
return granularity;
final String formatX = fmt;
final String mainUnitX = ctx.getString(mainUnitStr);
xAxis.setGranularity(granularity);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
if (!Algorithms.isEmpty(formatX)) {
return MessageFormat.format(formatX + mainUnitX, value);
} else {
return (int)value + " " + mainUnitX;
}
}
});
return divX;
}
private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, float divX, float convEle) {
private static float setupXAxisTime(XAxis xAxis, long timeSpan) {
final boolean useHours = timeSpan / 3600000 > 0;
xAxis.setGranularity(1f);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
int seconds = (int)value;
if (useHours) {
int hours = seconds / (60 * 60);
int minutes = (seconds / 60) % 60;
int sec = seconds % 60;
return hours + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (sec < 10 ? "0" + sec : sec);
} else {
int minutes = (seconds / 60) % 60;
int sec = seconds % 60;
return (minutes < 10 ? "0" + minutes : minutes) + ":" + (sec < 10 ? "0" + sec : sec);
}
}
});
return 1f;
}
private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, GPXDataSetAxisType axisType,
float divX, float convEle) {
List<Entry> values = new ArrayList<>();
List<Elevation> elevationData = analysis.elevationData;
float nextX = 0;
float nextY;
float prevYM;
float elev;
float prevElevOrig = -80000;
float prevElev = 0;
int i = -1;
int lastIndex = elevationData.size() - 1;
float shift = 0f;
Entry lastEntry = null;
float lastXSameY = -1;
boolean hasSameY = false;
float x;
for (Elevation e : elevationData) {
i++;
if (e.distance > 0) {
nextX += (float) e.distance / divX;
x = axisType == GPXDataSetAxisType.TIME ? e.time : (float) e.distance;
if (x > 0) {
nextX += x / divX;
elev = (float) e.elevation;
if (prevElevOrig != -80000) {
if (elev > prevElevOrig) {
@ -1026,36 +1054,23 @@ public class GpxUiHelper {
return values;
}
public static OrderedLineDataSet createGPXElevationDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
public static OrderedLineDataSet createGPXElevationDataSet(OsmandApplication ctx, LineChart mChart,
GPXTrackAnalysis analysis,
GPXDataSetAxisType axisType,
boolean useRightAxis, boolean drawFilled) {
OsmandSettings settings = ctx.getSettings();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
boolean useFeet = (mc == OsmandSettings.MetricsConstants.MILES_AND_FEET) || (mc == OsmandSettings.MetricsConstants.MILES_AND_YARDS);
boolean light = settings.isLightContent();
final float convEle = useFeet ? 3.28084f : 1.0f;
final float meters = analysis.totalDistance;
float[] koef = new float[] { 1f };
StringBuilder fmt = new StringBuilder();
StringBuilder unitX = new StringBuilder();
float granularity = getXAxisParams(ctx, meters, koef, fmt, unitX);
float divX = koef[0];
final String formatX = fmt.toString();
final String mainUnitX = unitX.toString();
float divX;
XAxis xAxis = mChart.getXAxis();
xAxis.setGranularity(granularity);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
if (!Algorithms.isEmpty(formatX)) {
return MessageFormat.format(formatX + mainUnitX, value);
} else {
return (int)value + " " + mainUnitX;
}
}
});
if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) {
divX = setupXAxisTime(xAxis, analysis.timeSpan);
} else {
divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance);
}
final String mainUnitY = useFeet ? ctx.getString(R.string.foot) : ctx.getString(R.string.m);
@ -1069,6 +1084,7 @@ public class GpxUiHelper {
yAxis.setTextColor(ActivityCompat.getColor(mChart.getContext(), R.color.gpx_chart_blue));
yAxis.setGridColor(ActivityCompat.getColor(mChart.getContext(), R.color.gpx_chart_blue_grid));
yAxis.setGranularity(1f);
yAxis.resetAxisMinimum();
yAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
@ -1077,10 +1093,13 @@ public class GpxUiHelper {
}
});
List<Entry> values = calculateElevationArray(analysis, divX, convEle);
List<Entry> values = calculateElevationArray(analysis, axisType, divX, convEle);
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.ALTITUDE);
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.ALTITUDE, axisType);
dataSet.priority = (float) (analysis.avgElevation - analysis.minElevation) * convEle;
dataSet.divX = divX;
dataSet.mulY = convEle;
dataSet.divY = Float.NaN;
dataSet.units = mainUnitY;
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_blue));
@ -1107,7 +1126,6 @@ public class GpxUiHelper {
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
//dataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
//dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
dataSet.setFillFormatter(new IFillFormatter() {
@Override
@ -1121,41 +1139,20 @@ public class GpxUiHelper {
return dataSet;
}
public static void setGPXElevationChartData(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
LineDataSet dataSet = createGPXElevationDataSet(ctx, mChart, analysis, useRightAxis, drawFilled);
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(dataSet);
LineData data = new LineData(dataSets);
mChart.setData(data);
}
public static OrderedLineDataSet createGPXSpeedDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
public static OrderedLineDataSet createGPXSpeedDataSet(OsmandApplication ctx, LineChart mChart,
GPXTrackAnalysis analysis,
GPXDataSetAxisType axisType,
boolean useRightAxis, boolean drawFilled) {
OsmandSettings settings = ctx.getSettings();
boolean light = settings.isLightContent();
final float meters = analysis.totalDistance;
float[] koef = new float[] { 1f };
StringBuilder fmt = new StringBuilder();
StringBuilder unitX = new StringBuilder();
float granularity = getXAxisParams(ctx, meters, koef, fmt, unitX);
float divX = koef[0];
final String formatX = fmt.toString();
final String mainUnitX = unitX.toString();
float divX;
XAxis xAxis = mChart.getXAxis();
xAxis.setGranularity(granularity);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
if (!Algorithms.isEmpty(formatX)) {
return MessageFormat.format(formatX + mainUnitX, value);
} else {
return (int)value + " " + mainUnitX;
}
}
});
if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) {
divX = setupXAxisTime(xAxis, analysis.timeSpan);
} else {
divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance);
}
OsmandSettings.SpeedConstants sps = settings.SPEED_SYSTEM.get();
float mulSpeed = Float.NaN;
@ -1194,12 +1191,14 @@ public class GpxUiHelper {
});
ArrayList<Entry> values = new ArrayList<>();
List<GPXUtilities.Speed> speedData = analysis.speedData;
List<Speed> speedData = analysis.speedData;
float nextX = 0;
float nextY;
for (GPXUtilities.Speed s : speedData) {
if (s.distance > 0) {
nextX += (float) s.distance / divX;
float x;
for (Speed s : speedData) {
x = axisType == GPXDataSetAxisType.TIME ? s.time : (float) s.distance;
if (x > 0) {
nextX += x / divX;
if (Float.isNaN(divSpeed)) {
nextY = (float) (s.speed * mulSpeed);
} else {
@ -1212,13 +1211,21 @@ public class GpxUiHelper {
}
}
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.SPEED);
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.SPEED, axisType);
if (Float.isNaN(divSpeed)) {
dataSet.priority = analysis.avgSpeed * mulSpeed;
} else {
dataSet.priority = divSpeed / analysis.avgSpeed;
}
dataSet.divX = divX;
if (Float.isNaN(divSpeed)) {
dataSet.mulY = mulSpeed;
dataSet.divY = Float.NaN;
} else {
dataSet.divY = divSpeed;
dataSet.mulY = Float.NaN;
}
dataSet.units = mainUnitY;
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_orange));
@ -1251,15 +1258,11 @@ public class GpxUiHelper {
return dataSet;
}
public static void setGPXSpeedChartData(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
LineDataSet dataSet = createGPXSpeedDataSet(ctx, mChart, analysis, useRightAxis, drawFilled);
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(dataSet);
LineData data = new LineData(dataSets);
mChart.setData(data);
}
public static OrderedLineDataSet createGPXSlopeDataSet(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, List<Entry> eleValues, boolean useRightAxis, boolean drawFilled) {
public static OrderedLineDataSet createGPXSlopeDataSet(OsmandApplication ctx, LineChart mChart,
GPXTrackAnalysis analysis,
GPXDataSetAxisType axisType,
List<Entry> eleValues,
boolean useRightAxis, boolean drawFilled) {
OsmandSettings settings = ctx.getSettings();
boolean light = settings.isLightContent();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
@ -1267,28 +1270,13 @@ public class GpxUiHelper {
final float convEle = useFeet ? 3.28084f : 1.0f;
final float totalDistance = analysis.totalDistance;
float[] koef = new float[] { 1f };
StringBuilder fmt = new StringBuilder();
StringBuilder unitX = new StringBuilder();
float granularity = getXAxisParams(ctx, totalDistance, koef, fmt, unitX);
float divX = koef[0];
final String formatX = fmt.toString();
final String mainUnitX = unitX.toString();
float divX;
XAxis xAxis = mChart.getXAxis();
xAxis.setGranularity(granularity);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
if (!Algorithms.isEmpty(formatX)) {
return MessageFormat.format(formatX + mainUnitX, value);
} else {
return (int)value + " " + mainUnitX;
}
}
});
if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) {
divX = setupXAxisTime(xAxis, analysis.timeSpan);
} else {
divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance);
}
final String mainUnitY = "%";
@ -1302,6 +1290,7 @@ public class GpxUiHelper {
yAxis.setTextColor(ActivityCompat.getColor(mChart.getContext(), R.color.gpx_chart_green));
yAxis.setGridColor(ActivityCompat.getColor(mChart.getContext(), R.color.gpx_chart_green_grid));
yAxis.setGranularity(1f);
yAxis.resetAxisMinimum();
yAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
@ -1311,8 +1300,8 @@ public class GpxUiHelper {
});
List<Entry> values;
if (eleValues == null) {
values = calculateElevationArray(analysis, 1f, 1f);
if (eleValues == null || axisType == GPXDataSetAxisType.TIME) {
values = calculateElevationArray(analysis, GPXDataSetAxisType.DISTANCE, 1f, 1f);
} else {
values = new ArrayList<>(eleValues.size());
for (Entry e : eleValues) {
@ -1328,6 +1317,12 @@ public class GpxUiHelper {
double STEP = 5;
float timeDistKoef = 1f;
if (axisType == GPXDataSetAxisType.TIME) {
timeDistKoef = analysis.timeSpan / totalDistance / 1000;
divX = 1f;
}
double[] calculatedDist = new double[(int) (totalDistance / STEP) + 1];
double[] calculatedH = new double[(int) (totalDistance / STEP) + 1];
int nextW = 0;
@ -1350,7 +1345,7 @@ public class GpxUiHelper {
int index = (int) ((SLOPE_PROXIMITY / STEP) / 2);
for (int k = 0; k < calculatedSlopeDist.length; k++) {
calculatedSlopeDist[k] = calculatedDist[index + k];
calculatedSlopeDist[k] = calculatedDist[index + k] * timeDistKoef;
calculatedSlope[k] = (calculatedH[ 2 * index + k] - calculatedH[k]) * 100 / SLOPE_PROXIMITY;
if (Double.isNaN(calculatedSlope[k])) {
calculatedSlope[k] = 0;
@ -1384,7 +1379,8 @@ public class GpxUiHelper {
slopeValues.add(lastEntry);
}
OrderedLineDataSet dataSet = new OrderedLineDataSet(slopeValues, "", GPXDataSetType.SLOPE);
OrderedLineDataSet dataSet = new OrderedLineDataSet(slopeValues, "", GPXDataSetType.SLOPE, axisType);
dataSet.divX = divX;
dataSet.units = mainUnitY;
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_green));
@ -1411,7 +1407,6 @@ public class GpxUiHelper {
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
//dataSet.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
//dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
/*
dataSet.setFillFormatter(new IFillFormatter() {
@ -1427,51 +1422,108 @@ public class GpxUiHelper {
return dataSet;
}
public static void setGPXSlopeChartData(OsmandApplication ctx, LineChart mChart, GPXTrackAnalysis analysis, boolean useRightAxis, boolean drawFilled) {
LineDataSet dataSet = createGPXSlopeDataSet(ctx, mChart, analysis, null, useRightAxis, drawFilled);
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(dataSet);
LineData data = new LineData(dataSets);
mChart.setData(data);
public enum GPXDataSetType {
ALTITUDE(R.string.altitude, R.drawable.ic_action_altitude_average),
SPEED(R.string.map_widget_speed, R.drawable.ic_action_speed),
SLOPE(R.string.shared_string_slope, R.drawable.ic_action_altitude_ascent);
private int stringId;
private int imageId;
private GPXDataSetType(int stringId, int imageId) {
this.stringId = stringId;
this.imageId = imageId;
}
public String getName(Context ctx) {
return ctx.getString(stringId);
}
public int getStringId() {
return stringId;
}
public int getImageId() {
return imageId;
}
public Drawable getImageDrawable(OsmandApplication app) {
return app.getIconsCache().getThemedIcon(imageId);
}
}
public enum GPXDataSetType {
ALTITUDE,
SPEED,
SLOPE
public enum GPXDataSetAxisType {
DISTANCE(R.string.distance, R.drawable.ic_action_marker_dark),
TIME(R.string.shared_string_time, R.drawable.ic_action_time);
private int stringId;
private int imageId;
private GPXDataSetAxisType(int stringId, int imageId) {
this.stringId = stringId;
this.imageId = imageId;
}
public String getName(Context ctx) {
return ctx.getString(stringId);
}
public int getStringId() {
return stringId;
}
public int getImageId() {
return imageId;
}
public Drawable getImageDrawable(OsmandApplication app) {
return app.getIconsCache().getThemedIcon(imageId);
}
}
public static class OrderedLineDataSet extends LineDataSet {
private GPXDataSetType dataSetType;
private GPXDataSetAxisType dataSetAxisType;
public float priority;
public String units;
public List<Segment> spline;
float priority;
String units;
float divX = 1f;
float divY = 1f;
float mulY = 1f;
public OrderedLineDataSet(List<Entry> yVals, String label, GPXDataSetType dataSetType) {
OrderedLineDataSet(List<Entry> yVals, String label, GPXDataSetType dataSetType, GPXDataSetAxisType dataSetAxisType) {
super(yVals, label);
this.dataSetType = dataSetType;
/*
List<Point2D> points = new ArrayList<>(yVals.size());
for (Entry e : yVals) {
points.add(new Point2D(e.getX(), e.getY()));
}
spline = calculateSpline(points);
*/
this.dataSetAxisType = dataSetAxisType;
}
public GPXDataSetType getDataSetType() {
return dataSetType;
}
public Segment getSegmentForEntryIndex(int index) {
if (index < spline.size()) {
return spline.get(index);
} else {
return spline.get(spline.size() - 1);
}
public GPXDataSetAxisType getDataSetAxisType() {
return dataSetAxisType;
}
public float getPriority() {
return priority;
}
public float getDivX() {
return divX;
}
public float getDivY() {
return divY;
}
public float getMulY() {
return mulY;
}
public String getUnits() {
return units;
}
}
@ -1613,7 +1665,7 @@ public class GpxUiHelper {
private long fileSize;
private boolean selected;
public GPXInfo(String fileName, long lastModified, long fileSize) {
GPXInfo(String fileName, long lastModified, long fileSize) {
this.fileName = fileName;
this.lastModified = lastModified;
this.fileSize = fileSize;
@ -1639,228 +1691,4 @@ public class GpxUiHelper {
this.selected = selected;
}
}
public static class Point2D {
double x, y;
Point2D() {
x = 0.0;
y = 0.0;
}
Point2D(double x, double y) {
this.x = x;
this.y = y;
}
Point2D(Point2D p) {
this.x = p.x;
this.y = p.y;
}
Point2D minus(Point2D point) {
return new Point2D(x - point.x, y - point.y);
}
Point2D plus(Point2D point) {
return new Point2D(x + point.x, y + point.y);
}
Point2D mult(double v) {
return new Point2D(x * v, y * v);
}
void thisMinus(Point2D point) {
x -= point.x;
y -= point.y;
}
void thisPlus(Point2D point) {
x += point.x;
y += point.y;
}
void normalize()
{
double l = Math.sqrt(x * x + y * y);
x /= l;
y /= l;
}
}
public static class Segment {
Point2D[] points = new Point2D[4];
Segment() {
}
void calc(double t, Point2D p)
{
double t2 = t * t;
double t3 = t2 * t;
double nt = 1.0 - t;
double nt2 = nt * nt;
double nt3 = nt2 * nt;
p.x = nt3 * points[0].x + 3.0 * t * nt2 * points[1].x + 3.0 * t2 * nt * points[2].x + t3 * points[3].x;
p.y = nt3 * points[0].y + 3.0 * t * nt2 * points[1].y + 3.0 * t2 * nt * points[2].y + t3 * points[3].y;
}
}
public static List<Segment> calculateSpline(List<Point2D> values) {
final double EPSILON = 1.0e-5;
int n = values.size() - 1;
if (n < 2)
return null;
List<Segment> bezier = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
bezier.add(new Segment());
}
Point2D tgL = new Point2D();
Point2D tgR = new Point2D();
Point2D cur;
Point2D next = values.get(1).minus(values.get(0));
next.normalize();
double l1, l2, tmp, x;
--n;
for (int i = 0; i < n; ++i)
{
bezier.get(i).points[0] = new Point2D(values.get(i));
bezier.get(i).points[1] = new Point2D(values.get(i));
bezier.get(i).points[2] = new Point2D(values.get(i + 1));
bezier.get(i).points[3] = new Point2D(values.get(i + 1));
cur = next;
next = values.get(i + 2).minus(values.get(i + 1));
next.normalize();
tgL = tgR;
tgR = cur.plus(next);
tgR.normalize();
if (Math.abs(values.get(i + 1).y - values.get(i).y) < EPSILON)
{
l1 = 0.0;
l2 = 0.0;
}
else
{
tmp = values.get(i + 1).x - values.get(i).x;
l1 = Math.abs(tgL.x) > EPSILON ? tmp / (2.0 * tgL.x) : 1.0;
l2 = Math.abs(tgR.x) > EPSILON ? tmp / (2.0 * tgR.x) : 1.0;
}
if (Math.abs(tgL.x) > EPSILON && Math.abs(tgR.x) > EPSILON)
{
tmp = tgL.y / tgL.x - tgR.y / tgR.x;
if (Math.abs(tmp) > EPSILON)
{
x = (values.get(i + 1).y - tgR.y / tgR.x * values.get(i + 1).x - values.get(i).y + tgL.y / tgL.x * values.get(i).x) / tmp;
if (x > values.get(i).x && x < values.get(i + 1).x)
{
if (tgL.y > 0.0)
{
if (l1 > l2)
l1 = 0.0;
else
l2 = 0.0;
}
else
{
if (l1 < l2)
l1 = 0.0;
else
l2 = 0.0;
}
}
}
}
bezier.get(i).points[1].thisPlus(tgL.mult(l1));
bezier.get(i).points[2].thisMinus(tgR.mult(l2));
}
l1 = Math.abs(tgL.x) > EPSILON ? (values.get(n + 1).x - values.get(n).x) / (2.0 * tgL.x) : 1.0;
bezier.get(n).points[0] = new Point2D(values.get(n));
bezier.get(n).points[1] = new Point2D(values.get(n));
bezier.get(n).points[2] = new Point2D(values.get(n + 1));
bezier.get(n).points[3] = new Point2D(values.get(n + 1));
bezier.get(n).points[1].thisPlus(tgR.mult(l1));
return bezier;
}
public static class SplineRenderer extends LineChartRenderer {
public SplineRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
@Override
protected void drawCubicBezier(ILineDataSet dataSet) {
if (!(dataSet instanceof OrderedLineDataSet)) {
super.drawCubicBezier(dataSet);
} else {
OrderedLineDataSet ds = (OrderedLineDataSet) dataSet;
float phaseY = mAnimator.getPhaseY();
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mXBounds.set(mChart, dataSet);
cubicPath.reset();
if (mXBounds.range >= 1) {
final int firstIndex = mXBounds.min + 1;
final int lastIndex = mXBounds.min + mXBounds.range;
Segment seg = ds.getSegmentForEntryIndex(Math.max(firstIndex - 1, 0));
if (seg == null) return;
// let the spline start
cubicPath.moveTo((float) seg.points[0].x, (float) seg.points[0].y * phaseY);
for (int j = firstIndex; j <= lastIndex; j++) {
seg = ds.getSegmentForEntryIndex(j);
cubicPath.cubicTo((float) seg.points[1].x, (float) seg.points[1].y * phaseY,
(float) seg.points[2].x, (float) seg.points[2].y * phaseY,
(float) seg.points[3].x, (float) seg.points[3].y * phaseY);
}
}
// if filled is enabled, close the path
if (ds.isDrawFilledEnabled()) {
cubicFillPath.reset();
cubicFillPath.addPath(cubicPath);
drawCubicFill(mBitmapCanvas, ds, cubicFillPath, trans, mXBounds);
}
mRenderPaint.setColor(ds.getColor());
mRenderPaint.setStyle(Paint.Style.STROKE);
trans.pathValueToPixel(cubicPath);
mBitmapCanvas.drawPath(cubicPath, mRenderPaint);
mRenderPaint.setPathEffect(null);
}
}
}
}

View file

@ -1,23 +1,49 @@
package net.osmand.plus.mapcontextmenu.other;
import android.graphics.Matrix;
import android.support.v4.app.Fragment;
import android.support.v7.widget.PopupMenu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import net.osmand.data.LatLon;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.IconsCache;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.DirectionsDialogs;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.views.MapControlsLayer;
import net.osmand.plus.views.OsmandMapTileView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class TrackDetailsMenu {
private MapActivity mapActivity;
private OsmandMapTileView mapView;
private MapControlsLayer mapControlsLayer;
private GpxDisplayItem gpxItem;
private static boolean VISIBLE;
private boolean nightMode;
@ -28,6 +54,18 @@ public class TrackDetailsMenu {
mapView = mapActivity.getMapView();
}
public GpxDisplayItem getGpxItem() {
return gpxItem;
}
public void setGpxItem(GpxDisplayItem gpxItem) {
this.gpxItem = gpxItem;
}
public static boolean isVisible() {
return VISIBLE;
}
public void show() {
if (!VISIBLE) {
VISIBLE = true;
@ -40,12 +78,7 @@ public class TrackDetailsMenu {
TrackDetailsMenuFragment.showInstance(mapActivity);
if (!AndroidUiHelper.isXLargeDevice(mapActivity)) {
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_right_widgets_panel), false);
}
if (!portrait) {
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_route_land_left_margin), true);
}
mapActivity.findViewById(R.id.MapHudButtonsOverlay).setVisibility(View.INVISIBLE);
}
}
@ -58,6 +91,13 @@ public class TrackDetailsMenu {
}
}
public void update() {
WeakReference<TrackDetailsMenuFragment> fragmentRef = findMenuFragment();
if (fragmentRef != null) {
fragmentRef.get().updateInfo();
}
}
public WeakReference<TrackDetailsMenuFragment> findMenuFragment() {
Fragment fragment = mapActivity.getSupportFragmentManager().findFragmentByTag(TrackDetailsMenuFragment.TAG);
if (fragment != null && !fragment.isDetached()) {
@ -69,10 +109,10 @@ public class TrackDetailsMenu {
public void onDismiss() {
VISIBLE = false;
mapActivity.getMapLayers().getGpxLayer().setSelectedPointLatLon(null);
mapActivity.getMapView().setMapPositionX(0);
mapActivity.getMapView().refreshMap();
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_route_land_left_margin), false);
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_right_widgets_panel), true);
mapActivity.findViewById(R.id.MapHudButtonsOverlay).setVisibility(View.VISIBLE);
}
public void updateInfo(final View main) {
@ -81,29 +121,217 @@ public class TrackDetailsMenu {
}
private void updateView(final View parentView) {
/*
String via = generateViaDescription();
View viaLayout = parentView.findViewById(R.id.ViaLayout);
if (via.length() == 0) {
viaLayout.setVisibility(View.GONE);
parentView.findViewById(R.id.viaLayoutDivider).setVisibility(View.GONE);
} else {
viaLayout.setVisibility(View.VISIBLE);
parentView.findViewById(R.id.viaLayoutDivider).setVisibility(View.VISIBLE);
((TextView) parentView.findViewById(R.id.ViaView)).setText(via);
}
viaLayout.setOnClickListener(new View.OnClickListener() {
final LineChart chart = (LineChart) parentView.findViewById(R.id.chart);
chart.setOnChartGestureListener(new OnChartGestureListener() {
@Override
public void onClick(View v) {
if (getTargets().checkPointToNavigateShort()) {
mapActivity.getMapActions().openIntermediatePointsDialog();
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
}
@Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
Highlight[] highlights = chart.getHighlighted();
if (highlights != null && highlights.length > 0) {
gpxItem.chartHighlightPos = highlights[0].getX();
List<ILineDataSet> ds = chart.getLineData().getDataSets();
if (ds != null && ds.size() > 0) {
GPXUtilities.TrkSegment segment = null;
for (GPXUtilities.Track t : gpxItem.group.getGpx().tracks) {
for (GPXUtilities.TrkSegment s : t.segments) {
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
segment = s;
break;
}
}
if (segment != null) {
break;
}
}
if (segment != null) {
WptPt wpt = null;
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
float time = gpxItem.chartHighlightPos * 1000;
for (WptPt p : segment.points) {
if (p.time - gpxItem.analysis.startTime >= time) {
wpt = p;
break;
}
}
} else {
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
for (WptPt p : segment.points) {
if (p.distance >= distance) {
wpt = p;
break;
}
}
}
if (wpt != null) {
mapActivity.getMapLayers().getGpxLayer().setSelectedPointLatLon(new LatLon(wpt.lat, wpt.lon));
mapActivity.setMapLocation(wpt.lat, wpt.lon);
}
}
}
} else {
gpxItem.chartHighlightPos = -1;
}
}
@Override
public void onChartLongPressed(MotionEvent me) {
}
@Override
public void onChartDoubleTapped(MotionEvent me) {
}
@Override
public void onChartSingleTapped(MotionEvent me) {
}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
}
});
ImageView viaIcon = (ImageView) parentView.findViewById(R.id.viaIcon);
viaIcon.setImageDrawable(getIconOrig(R.drawable.list_intermediate));
*/
final OsmandApplication app = mapActivity.getMyApplication();
final IconsCache ic = app.getIconsCache();
GPXTrackAnalysis analysis = gpxItem.analysis;
if (analysis != null) {
GpxUiHelper.setupGPXChart(app, chart, 4);
if (gpxItem.chartType != null) {
List<ILineDataSet> dataSets = new ArrayList<>();
OrderedLineDataSet dataSet = null;
if (gpxItem.chartType != null) {
switch (gpxItem.chartType) {
case ALTITUDE:
dataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis,
gpxItem.chartAxisType, false, true);
break;
case SPEED:
dataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, analysis,
gpxItem.chartAxisType, false, true);
break;
case SLOPE:
dataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis,
gpxItem.chartAxisType, null, false, true);
break;
}
}
dataSets.add(dataSet);
chart.setData(new LineData(dataSets));
updateChart(chart);
}
}
View yAxis = parentView.findViewById(R.id.y_axis);
ImageView yAxisIcon = (ImageView) parentView.findViewById(R.id.y_axis_icon);
TextView yAxisTitle = (TextView) parentView.findViewById(R.id.y_axis_title);
View yAxisArrow = parentView.findViewById(R.id.y_axis_arrow);
final List<GPXDataSetType> availableTypes = new ArrayList<>();
if (analysis != null) {
if (analysis.elevationData != null) {
availableTypes.add(GPXDataSetType.ALTITUDE);
availableTypes.add(GPXDataSetType.SLOPE);
}
if (analysis.isSpeedSpecified()) {
availableTypes.add(GPXDataSetType.SPEED);
}
}
availableTypes.remove(gpxItem.chartType);
yAxisIcon.setImageDrawable(gpxItem.chartType.getImageDrawable(app));
yAxisTitle.setText(gpxItem.chartType.getName(app));
if (availableTypes.size() > 0) {
yAxis.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final PopupMenu optionsMenu = new PopupMenu(mapActivity, v);
DirectionsDialogs.setupPopUpMenuIcon(optionsMenu);
for (final GPXDataSetType type : availableTypes) {
MenuItem menuItem = optionsMenu.getMenu().add(type.getStringId()).setIcon(type.getImageDrawable(app));
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem mItem) {
gpxItem.chartType = type;
update();
return true;
}
});
}
optionsMenu.show();
}
});
yAxisArrow.setVisibility(View.VISIBLE);
} else {
yAxis.setOnClickListener(null);
yAxisArrow.setVisibility(View.GONE);
}
View xAxis = parentView.findViewById(R.id.x_axis);
ImageView xAxisIcon = (ImageView) parentView.findViewById(R.id.x_axis_icon);
TextView xAxisTitle = (TextView) parentView.findViewById(R.id.x_axis_title);
View xAxisArrow = parentView.findViewById(R.id.x_axis_arrow);
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_time));
xAxisTitle.setText(app.getString(R.string.shared_string_time));
} else {
xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_marker_dark));
xAxisTitle.setText(app.getString(R.string.distance));
}
if (analysis != null && analysis.isTimeSpecified()) {
xAxis.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final PopupMenu optionsMenu = new PopupMenu(mapActivity, v);
DirectionsDialogs.setupPopUpMenuIcon(optionsMenu);
final GPXDataSetAxisType type;
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
type = GPXDataSetAxisType.DISTANCE;
} else {
type = GPXDataSetAxisType.TIME;
}
MenuItem menuItem = optionsMenu.getMenu().add(type.getStringId()).setIcon(type.getImageDrawable(app));
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem mItem) {
gpxItem.chartAxisType = type;
gpxItem.chartHighlightPos = -1;
gpxItem.chartMatrix = null;
update();
return true;
}
});
optionsMenu.show();
}
});
xAxisArrow.setVisibility(View.VISIBLE);
} else {
xAxis.setOnClickListener(null);
xAxisArrow.setVisibility(View.GONE);
}
}
private void updateChart(LineChart chart) {
if (gpxItem.chartMatrix != null) {
chart.getViewPortHandler().refresh(new Matrix(gpxItem.chartMatrix), chart, true);
}
if (gpxItem.chartHighlightPos != -1) {
chart.highlightValue(gpxItem.chartHighlightPos, 0);
} else {
chart.highlightValue(null);
}
}
}

View file

@ -7,6 +7,8 @@ import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.AndroidUtils;
@ -19,6 +21,7 @@ public class TrackDetailsMenuFragment extends Fragment {
private TrackDetailsMenu menu;
private View mainView;
private View topBar;
private MapActivity getMapActivity() {
return (MapActivity) getActivity();
@ -30,7 +33,7 @@ public class TrackDetailsMenuFragment extends Fragment {
MapActivity mapActivity = getMapActivity();
menu = mapActivity.getMapLayers().getMapControlsLayer().getTrackDetailsMenu();
View view = inflater.inflate(R.layout.plan_route_info, container, false);
View view = inflater.inflate(R.layout.track_details, container, false);
if (menu == null) {
return view;
}
@ -38,11 +41,22 @@ public class TrackDetailsMenuFragment extends Fragment {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MapActivity.clearPrevActivityIntent();
dismiss();
}
});
mainView = view.findViewById(R.id.main_view);
topBar = view.findViewById(R.id.top_bar_layout);
ImageButton backButton = (ImageButton) topBar.findViewById(R.id.top_bar_back_button);
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().onBackPressed();
}
});
updateInfo();
return view;
@ -90,7 +104,7 @@ public class TrackDetailsMenuFragment extends Fragment {
int slideOutAnim = R.anim.slide_out_bottom;
mapActivity.getSupportFragmentManager().beginTransaction()
.setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
//.setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
.add(R.id.routeMenuContainer, this, TAG)
.addToBackStack(TAG)
.commitAllowingStateLoss();
@ -100,7 +114,7 @@ public class TrackDetailsMenuFragment extends Fragment {
FragmentActivity activity = getActivity();
if (activity != null) {
try {
activity.getSupportFragmentManager().popBackStack(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
activity.getSupportFragmentManager().popBackStackImmediate(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} catch (Exception e) {
// ignore
}
@ -117,42 +131,16 @@ public class TrackDetailsMenuFragment extends Fragment {
} else {
AndroidUtils.setBackground(ctx, mainView, nightMode, R.drawable.bg_left_menu_light, R.drawable.bg_left_menu_dark);
}
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerModesLayout), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerFromDropDown), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.viaLayoutDivider), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerToDropDown), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerButtons), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
ImageButton backButton = (ImageButton) topBar.findViewById(R.id.top_bar_back_button);
backButton.setImageDrawable(ctx.getMyApplication().getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha, R.color.color_white));
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerBtn1), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerBtn2), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setBackground(ctx, mainView.findViewById(R.id.dividerBtn3), nightMode,
R.color.dashboard_divider_light, R.color.dashboard_divider_dark);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.y_axis_title), nightMode);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.x_axis_title), nightMode);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.ViaView), nightMode);
AndroidUtils.setTextSecondaryColor(ctx, (TextView) mainView.findViewById(R.id.ViaSubView), nightMode);
AndroidUtils.setTextSecondaryColor(ctx, (TextView) mainView.findViewById(R.id.toTitle), nightMode);
AndroidUtils.setTextSecondaryColor(ctx, (TextView) mainView.findViewById(R.id.fromTitle), nightMode);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.InfoTextView), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.FromLayout), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.ViaLayout), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.ToLayout), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.Info), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.Next), nightMode);
AndroidUtils.setDashButtonBackground(ctx, mainView.findViewById(R.id.Prev), nightMode);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.DistanceText), nightMode);
AndroidUtils.setTextSecondaryColor(ctx, (TextView) mainView.findViewById(R.id.DistanceTitle), nightMode);
AndroidUtils.setTextPrimaryColor(ctx, (TextView) mainView.findViewById(R.id.DurationText), nightMode);
AndroidUtils.setTextSecondaryColor(ctx, (TextView) mainView.findViewById(R.id.DurationTitle), nightMode);
ImageView yAxisArrow = (ImageView) mainView.findViewById(R.id.y_axis_arrow);
ImageView xAxisArrow = (ImageView) mainView.findViewById(R.id.x_axis_arrow);
yAxisArrow.setImageDrawable(ctx.getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_arrow_drop_down));
xAxisArrow.setImageDrawable(ctx.getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_arrow_drop_down));
}
public static boolean showInstance(final MapActivity mapActivity) {
@ -168,9 +156,9 @@ public class TrackDetailsMenuFragment extends Fragment {
slideOutAnim = R.anim.slide_out_left;
}
MapRouteInfoMenuFragment fragment = new MapRouteInfoMenuFragment();
TrackDetailsMenuFragment fragment = new TrackDetailsMenuFragment();
mapActivity.getSupportFragmentManager().beginTransaction()
.setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
//.setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
.add(R.id.routeMenuContainer, fragment, TAG)
.addToBackStack(TAG).commitAllowingStateLoss();

View file

@ -195,7 +195,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment {
if (isRecording) {
currentGpxView.findViewById(R.id.segment_time_div).setVisibility(View.VISIBLE);
TextView segmentTime = (TextView) currentGpxView.findViewById(R.id.segment_time);
segmentTime.setText(OsmAndFormatter.getFormattedDurationShort((int)(sth.getDuration() / 1000), app));
segmentTime.setText(OsmAndFormatter.getFormattedDurationShort((int)(sth.getDuration() / 1000)));
segmentTime.setVisibility(View.VISIBLE);
stop.setCompoundDrawablesWithIntrinsicBounds(app.getIconsCache()
.getIcon(R.drawable.ic_action_rec_stop, light ? R.color.color_dialog_buttons_light : R.color.color_dialog_buttons_dark), null, null, null);

View file

@ -796,6 +796,9 @@ public class TrackPointFragment extends OsmandExpandableListFragment {
public boolean onMenuItemClick(MenuItem mItem) {
final OsmandSettings settings = app.getSettings();
LatLon location = new LatLon(gpxItem.locationStart.lat, gpxItem.locationStart.lon);
if (gpxItem.group.getGpx() != null) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpxItem.group.getGpx());
}
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name),

View file

@ -38,11 +38,14 @@ import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.GPXDatabase;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GPXUtilities.Track;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
@ -60,6 +63,8 @@ import net.osmand.plus.dialogs.ConfigureMapMenu.AppearanceListItem;
import net.osmand.plus.dialogs.ConfigureMapMenu.GpxAppearanceAdapter;
import net.osmand.plus.dialogs.ConfigureMapMenu.GpxAppearanceAdapter.GpxAppearanceAdapterType;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
@ -75,7 +80,6 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -89,7 +93,6 @@ public class TrackSegmentFragment extends OsmAndListFragment {
private OsmandApplication app;
private SegmentGPXAdapter adapter;
private View headerView;
private GpxDisplayItemType[] filterTypes = { GpxSelectionHelper.GpxDisplayItemType.TRACK_SEGMENT };
private List<String> options = new ArrayList<>();
@ -97,7 +100,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
private TIntArrayList timeSplit = new TIntArrayList();
private int selectedSplitInterval;
private boolean updateEnable;
private View headerView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -117,14 +120,22 @@ public class TrackSegmentFragment extends OsmAndListFragment {
setHasOptionsMenu(true);
View view = getActivity().getLayoutInflater().inflate(R.layout.update_index, container, false);
view.findViewById(R.id.header_layout).setVisibility(View.GONE);
ListView listView = (ListView) view.findViewById(android.R.id.list);
listView.setDivider(null);
listView.setDividerHeight(0);
TextView tv = new TextView(getActivity());
tv.setText(R.string.none_selected_gpx);
tv.setTextSize(24);
listView.setEmptyView(tv);
setContent(listView);
adapter = new SegmentGPXAdapter(new ArrayList<GpxDisplayItem>());
headerView = getActivity().getLayoutInflater().inflate(R.layout.gpx_item_list_header, null, false);
listView.addHeaderView(headerView);
listView.addFooterView(getActivity().getLayoutInflater().inflate(R.layout.list_shadow_footer, null, false));
updateHeader();
setListAdapter(adapter);
return view;
}
@ -200,12 +211,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
updateEnable = false;
}
private void setupListView(ListView listView) {
if (headerView == null) {
headerView = getActivity().getLayoutInflater().inflate(R.layout.gpx_item_list_header, null, false);
listView.addHeaderView(headerView);
listView.addFooterView(getActivity().getLayoutInflater().inflate(R.layout.list_shadow_footer, null, false));
}
private void updateHeader() {
final ImageView imageView = (ImageView) headerView.findViewById(R.id.imageView);
final View splitColorView = headerView.findViewById(R.id.split_color_view);
final View divider = headerView.findViewById(R.id.divider);
@ -216,13 +222,8 @@ public class TrackSegmentFragment extends OsmAndListFragment {
vis.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(getGpx(), vis.isChecked(), false);
if (vis.isChecked() && sf.getModifiableGpxFile() != null) {
sf.processPoints();
updateColorView(colorView);
} else {
updateColorView(colorView);
}
app.getSelectedGpxHelper().selectGpxFile(getGpx(), vis.isChecked(), false);
updateColorView(colorView);
}
});
imageView.setOnClickListener(new View.OnClickListener() {
@ -239,7 +240,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
false,
item);
} else {
GPXUtilities.WptPt wpt = sf.getGpxFile().findPointToShow();
WptPt wpt = sf.getGpxFile().findPointToShow();
if (wpt != null) {
app.getSettings().setMapLocationToShow(wpt.getLatitude(), wpt.getLongitude(),
15,
@ -427,24 +428,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
return groups;
}
public void setContent() {
setContent(getListView());
}
public void setContent(ListView listView) {
if (adapter == null) {
adapter = new SegmentGPXAdapter(new ArrayList<GpxDisplayItem>());
} else {
adapter.clear();
}
updateContent();
setupListView(listView);
if (listView.getAdapter() == null) {
setListAdapter(adapter);
}
}
protected void updateContent() {
public void updateContent() {
adapter.clear();
List<GpxDisplayGroup> groups = getOriginalGroups();
adapter.setNotifyOnChange(false);
@ -453,6 +437,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
adapter.setNotifyOnChange(true);
adapter.notifyDataSetChanged();
updateHeader();
}
protected List<GpxDisplayItem> flatten(List<GpxDisplayGroup> groups) {
@ -523,30 +508,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
}
/*
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
GpxDisplayItem child = adapter.getItem(position);
if (child != null) {
if (child.group.getGpx() != null) {
app.getSelectedGpxHelper().setGpxFileToDisplay(child.group.getGpx());
}
final OsmandSettings settings = app.getSettings();
LatLon location = new LatLon(child.locationStart.lat, child.locationStart.lon);
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_GPX_ITEM, child.group.getGpxName()),
false,
child);
MapActivity.launchMapActivityMoveToTop(getActivity());
}
}
*/
class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
private class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
private Map<GpxDisplayItem, GPXItemPagerAdapter> pagerAdaptersMap = new HashMap<>();
@ -603,11 +565,14 @@ public class TrackSegmentFragment extends OsmAndListFragment {
tabLayout = (PagerSlidingTabStrip) row.findViewById(R.id.sliding_tabs);
pager = (WrapContentHeightViewPager) row.findViewById(R.id.pager);
}
pager.setAdapter(getPagerAdapter(tabLayout, getItem(position)));
if (create) {
tabLayout.setViewPager(pager);
} else {
tabLayout.notifyDataSetChanged(true);
GpxDisplayItem item = getItem(position);
if (item != null) {
pager.setAdapter(getPagerAdapter(tabLayout, item));
if (create) {
tabLayout.setViewPager(pager);
} else {
tabLayout.notifyDataSetChanged(true);
}
}
return row;
}
@ -626,6 +591,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
private GpxDisplayItem gpxItem;
private GPXTabItemType[] tabTypes;
private String[] titles;
private Map<GPXTabItemType, List<ILineDataSet>> dataSetsMap = new HashMap<>();
GPXItemPagerAdapter(PagerSlidingTabStrip tabs, GpxDisplayItem gpxItem) {
super();
@ -665,6 +631,59 @@ public class TrackSegmentFragment extends OsmAndListFragment {
}
}
private List<ILineDataSet> getDataSets(GPXTabItemType tabType, LineChart chart) {
List<ILineDataSet> dataSets = dataSetsMap.get(tabType);
if (dataSets == null && chart != null) {
dataSets = new ArrayList<>();
GPXTrackAnalysis analysis = gpxItem.analysis;
switch (tabType) {
case GPX_TAB_ITEM_GENERAL: {
OrderedLineDataSet speedDataSet = null;
OrderedLineDataSet elevationDataSet = null;
if (analysis.isSpeedSpecified()) {
speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, true, true);
}
if (analysis.elevationData != null) {
elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, false, true);
}
if (speedDataSet != null) {
dataSets.add(speedDataSet);
if (elevationDataSet != null) {
dataSets.add(elevationDataSet.getPriority() < speedDataSet.getPriority()
? 1 : 0, elevationDataSet);
}
} else if (elevationDataSet != null) {
dataSets.add(elevationDataSet);
}
dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_GENERAL, dataSets);
break;
}
case GPX_TAB_ITEM_ALTITUDE: {
OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, false, true);
dataSets.add(elevationDataSet);
if (analysis.elevationData.size() > 1) {
OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, elevationDataSet.getValues(), true, true);
dataSets.add(slopeDataSet);
}
dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, dataSets);
break;
}
case GPX_TAB_ITEM_SPEED: {
OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, false, true);
dataSets.add(speedDataSet);
dataSetsMap.put(GPXTabItemType.GPX_TAB_ITEM_SPEED, dataSets);
break;
}
}
}
return dataSets;
}
@Override
public int getCount() {
return tabTypes.length;
@ -756,29 +775,11 @@ public class TrackSegmentFragment extends OsmAndListFragment {
switch (tabType) {
case GPX_TAB_ITEM_GENERAL:
if (analysis != null) {
List<ILineDataSet> dataSets = new LinkedList<>();
if ((analysis.elevationData != null && analysis.totalDistance > 0)
|| analysis.isSpeedSpecified()) {
GpxUiHelper.setupGPXChart(app, chart, 4);
OrderedLineDataSet speedDataSet = null;
OrderedLineDataSet elevationDataSet = null;
if (analysis.isSpeedSpecified()) {
speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, analysis, true, true);
}
if (analysis.elevationData != null) {
elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis, false, true);
}
if (speedDataSet != null) {
dataSets.add(speedDataSet);
if (elevationDataSet != null) {
dataSets.add(elevationDataSet.priority < speedDataSet.priority ? 1 : 0, elevationDataSet);
}
} else if (elevationDataSet != null) {
dataSets.add(elevationDataSet);
}
LineData data = new LineData(dataSets);
chart.setData(data);
chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_GENERAL, chart)));
updateChart(chart);
chart.setVisibility(View.VISIBLE);
} else {
chart.setVisibility(View.GONE);
@ -821,7 +822,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//todo
openDetails(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
}
});
@ -830,15 +831,8 @@ public class TrackSegmentFragment extends OsmAndListFragment {
if (analysis != null) {
if (analysis.elevationData != null && analysis.totalDistance > 0) {
GpxUiHelper.setupGPXChart(app, chart, 4);
List<ILineDataSet> dataSets = new ArrayList<>();
OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis, false, true);
dataSets.add(elevationDataSet);
if (analysis.elevationData.size() > 1) {
OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis, elevationDataSet.getValues(), true, true);
dataSets.add(slopeDataSet);
}
LineData data = new LineData(dataSets);
chart.setData(data);
chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, chart)));
updateChart(chart);
chart.setVisibility(View.VISIBLE);
} else {
chart.setVisibility(View.GONE);
@ -872,7 +866,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//todo
openDetails(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
}
});
@ -881,7 +875,8 @@ public class TrackSegmentFragment extends OsmAndListFragment {
if (analysis != null && analysis.isSpeedSpecified()) {
if (analysis.totalDistance > 0) {
GpxUiHelper.setupGPXChart(app, chart, 4);
GpxUiHelper.setGPXSpeedChartData(app, chart, analysis, false, true);
chart.setData(new LineData(getDataSets(GPXTabItemType.GPX_TAB_ITEM_SPEED, chart)));
updateChart(chart);
chart.setVisibility(View.VISIBLE);
} else {
chart.setVisibility(View.GONE);
@ -914,7 +909,7 @@ public class TrackSegmentFragment extends OsmAndListFragment {
view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//todo
openDetails(GPXTabItemType.GPX_TAB_ITEM_SPEED);
}
});
break;
@ -1008,11 +1003,79 @@ public class TrackSegmentFragment extends OsmAndListFragment {
if (gpxItem.chartMatrix != null) {
chart.getViewPortHandler().refresh(new Matrix(gpxItem.chartMatrix), chart, true);
}
chart.highlightValue(gpxItem.chartHighlightPos, 0);
if (gpxItem.chartHighlightPos != -1) {
chart.highlightValue(gpxItem.chartHighlightPos, 0);
} else {
chart.highlightValue(null);
}
}
void openDetails(GPXTabItemType tabType) {
LatLon location = null;
WptPt wpt = null;
gpxItem.chartType = null;
List<ILineDataSet> ds = getDataSets(tabType, null);
if (ds != null && ds.size() > 0) {
for (ILineDataSet dataSet : ds) {
OrderedLineDataSet orderedDataSet = (OrderedLineDataSet) dataSet;
if (orderedDataSet.getDataSetType() == GPXDataSetType.ALTITUDE) {
gpxItem.chartType = GPXDataSetType.ALTITUDE;
break;
}
gpxItem.chartType = orderedDataSet.getDataSetType();
}
if (gpxItem.chartHighlightPos != -1) {
TrkSegment segment = null;
for (Track t : gpxItem.group.getGpx().tracks) {
for (TrkSegment s : t.segments) {
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
segment = s;
break;
}
}
if (segment != null) {
break;
}
}
if (segment != null) {
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
for (WptPt p : segment.points) {
if (p.distance >= distance) {
wpt = p;
break;
}
}
if (wpt != null) {
location = new LatLon(wpt.lat, wpt.lon);
}
}
}
}
if (location == null) {
location = new LatLon(gpxItem.locationStart.lat, gpxItem.locationStart.lon);
}
if (wpt != null) {
gpxItem.locationOnMap = wpt;
} else {
gpxItem.locationOnMap = gpxItem.locationStart;
}
if (gpxItem.group.getGpx() != null) {
app.getSelectedGpxHelper().setGpxFileToDisplay(gpxItem.group.getGpx());
}
final OsmandSettings settings = app.getSettings();
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name),
false,
gpxItem);
MapActivity.launchMapActivityMoveToTop(getActivity());
}
}
class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
private class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
@Nullable
private final SelectedGpxFile mSelectedGpxFile;
@NonNull private final TrackSegmentFragment mFragment;

View file

@ -67,6 +67,9 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private Paint paintIcon;
private Bitmap pointSmall;
private Bitmap selectedPoint;
private LatLon selectedPointLatLon;
private static final int startZoom = 7;
@ -141,6 +144,7 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
paintIcon = new Paint();
pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small);
selectedPoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_default_location);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
@ -343,6 +347,16 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
drawBigPoint(canvas, o, fileColor, x, y);
}
}
if (selectedPointLatLon != null
&& selectedPointLatLon.getLatitude() >= latLonBounds.bottom
&& selectedPointLatLon.getLatitude() <= latLonBounds.top
&& selectedPointLatLon.getLongitude() >= latLonBounds.left
&& selectedPointLatLon.getLongitude() <= latLonBounds.right) {
float x = tileBox.getPixXFromLatLon(selectedPointLatLon.getLatitude(), selectedPointLatLon.getLongitude());
float y = tileBox.getPixYFromLatLon(selectedPointLatLon.getLatitude(), selectedPointLatLon.getLongitude());
paintIcon.setColorFilter(null);
canvas.drawBitmap(selectedPoint, x - selectedPoint.getWidth() / 2, y - selectedPoint.getHeight() / 2, paintIcon);
}
this.fullObjectsLatLon = fullObjectsLatLon;
this.smallObjectsLatLon = smallObjectsLatLon;
}
@ -402,10 +416,17 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
}
private List<WptPt> getListStarPoints(SelectedGpxFile g) {
return g.getGpxFile().points;
}
public LatLon getSelectedPointLatLon() {
return selectedPointLatLon;
}
public void setSelectedPointLatLon(LatLon selectedPointLatLon) {
this.selectedPointLatLon = selectedPointLatLon;
}
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return (Math.abs(objx - ex) <= radius * 2 && Math.abs(objy - ey) <= radius * 2);
// return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ;