Merge pull request #6585 from osmandapp/issue_6499_timescale

Issue 6499 timescale
This commit is contained in:
Alexey 2019-03-01 17:08:04 +03:00 committed by GitHub
commit 9135f9d169
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 30 deletions

View file

@ -9,7 +9,12 @@
3. If you modify the English strings file, please add new strings at the top of the file, this makes periodic reviews before releases easier. 3. If you modify the English strings file, please add new strings at the top of the file, this makes periodic reviews before releases easier.
- For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience - For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience
Thx - Hardy Thx - Hardy
--> -->
<string name="time_of_day">Time of day</string>
<string name="add_destination_query">Please add Destination first</string>
<string name="by_transport_type">By %1$s</string> <string name="by_transport_type">By %1$s</string>
<string name="step_by_step">Step by step</string> <string name="step_by_step">Step by step</string>
<string name="road_types">Road types</string> <string name="road_types">Road types</string>

View file

@ -74,6 +74,12 @@ public class OsmAndFormatter {
} }
} }
public static String getFormattedTimeShort(long seconds) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(seconds * 1000);
return SIMPLE_TIME_OF_DAY_FORMAT.format(calendar.getTime());
}
public static String getFormattedDate(Context context, long milliseconds) { public static String getFormattedDate(Context context, long milliseconds) {
return DateUtils.formatDateTime(context, milliseconds, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); return DateUtils.formatDateTime(context, milliseconds, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);
} }

View file

@ -63,6 +63,7 @@ import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject; import net.osmand.CallbackWithObject;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GPXDatabase.GpxDataItem;
@ -107,6 +108,7 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log;
import static com.github.mikephil.charting.components.XAxis.XAxisPosition.BOTTOM; import static com.github.mikephil.charting.components.XAxis.XAxisPosition.BOTTOM;
import static net.osmand.binary.RouteDataObject.HEIGHT_UNDEFINED; import static net.osmand.binary.RouteDataObject.HEIGHT_UNDEFINED;
@ -123,6 +125,7 @@ import static net.osmand.plus.download.DownloadActivity.formatMb;
public class GpxUiHelper { public class GpxUiHelper {
private static final int OPEN_GPX_DOCUMENT_REQUEST = 1005; private static final int OPEN_GPX_DOCUMENT_REQUEST = 1005;
private static final Log LOG = PlatformUtil.getLog(GpxUiHelper.class);
public static String getDescription(OsmandApplication app, GPXFile result, File f, boolean html) { public static String getDescription(OsmandApplication app, GPXFile result, File f, boolean html) {
GPXTrackAnalysis analysis = result.getAnalysis(f == null ? 0 : f.lastModified()); GPXTrackAnalysis analysis = result.getAnalysis(f == null ? 0 : f.lastModified());
@ -1124,11 +1127,9 @@ public class GpxUiHelper {
} }
private static float setupXAxisTime(XAxis xAxis, long timeSpan) { private static float setupXAxisTime(XAxis xAxis, long timeSpan) {
final boolean useHours = timeSpan / 3600000 > 0; final boolean useHours = timeSpan / 3600000 > 0;
xAxis.setGranularity(1f); xAxis.setGranularity(1f);
xAxis.setValueFormatter(new IAxisValueFormatter() { xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override @Override
public String getFormattedValue(float value, AxisBase axis) { public String getFormattedValue(float value, AxisBase axis) {
int seconds = (int)value; int seconds = (int)value;
@ -1148,6 +1149,18 @@ public class GpxUiHelper {
return 1f; return 1f;
} }
private static float setupXAxisTimeOfDay(XAxis xAxis, final long startTime) {
xAxis.setGranularity(1f);
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
long seconds = (long) (startTime/1000 + value);
return OsmAndFormatter.getFormattedTimeShort(seconds);
}
});
return 1f;
}
private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, GPXDataSetAxisType axisType, private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, GPXDataSetAxisType axisType,
float divX, float convEle) { float divX, float convEle) {
List<Entry> values = new ArrayList<>(); List<Entry> values = new ArrayList<>();
@ -1165,7 +1178,11 @@ public class GpxUiHelper {
float x; float x;
for (Elevation e : elevationData) { for (Elevation e : elevationData) {
i++; i++;
x = axisType == GPXDataSetAxisType.TIME ? e.time : e.distance; if (axisType == GPXDataSetAxisType.TIME || axisType == GPXDataSetAxisType.TIMEOFDAY) {
x = e.time;
} else {
x = e.distance;
}
if (x > 0) { if (x > 0) {
nextX += x / divX; nextX += x / divX;
if (!Float.isNaN(e.elevation)) { if (!Float.isNaN(e.elevation)) {
@ -1323,6 +1340,8 @@ public class GpxUiHelper {
XAxis xAxis = mChart.getXAxis(); XAxis xAxis = mChart.getXAxis();
if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) { if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) {
divX = setupXAxisTime(xAxis, analysis.timeSpan); divX = setupXAxisTime(xAxis, analysis.timeSpan);
} else if (axisType == GPXDataSetAxisType.TIMEOFDAY && analysis.isTimeSpecified()) {
divX = setupXAxisTimeOfDay(xAxis, analysis.startTime);
} else { } else {
divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance); divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance);
} }
@ -1407,6 +1426,8 @@ public class GpxUiHelper {
XAxis xAxis = mChart.getXAxis(); XAxis xAxis = mChart.getXAxis();
if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) { if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) {
divX = setupXAxisTime(xAxis, analysis.timeSpan); divX = setupXAxisTime(xAxis, analysis.timeSpan);
} else if (axisType == GPXDataSetAxisType.TIMEOFDAY && analysis.isTimeSpecified()) {
divX = setupXAxisTimeOfDay(xAxis, analysis.startTime);
} else { } else {
divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance); divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance);
} }
@ -1452,9 +1473,19 @@ public class GpxUiHelper {
float nextY; float nextY;
float x; float x;
for (Speed s : speedData) { for (Speed s : speedData) {
x = axisType == GPXDataSetAxisType.TIME ? s.time : s.distance; switch(axisType) {
case TIMEOFDAY:
case TIME:
x = s.time;
break;
default:
x = s.distance;
break;
}
if (x > 0) { if (x > 0) {
if (axisType == GPXDataSetAxisType.TIME && x > 60) { if (axisType == GPXDataSetAxisType.TIME && x > 60 ||
axisType == GPXDataSetAxisType.TIMEOFDAY && x > 60) {
values.add(new Entry(nextX + 1, 0)); values.add(new Entry(nextX + 1, 0));
values.add(new Entry(nextX + x - 1, 0)); values.add(new Entry(nextX + x - 1, 0));
} }
@ -1550,7 +1581,7 @@ public class GpxUiHelper {
@Nullable List<Entry> eleValues, @Nullable List<Entry> eleValues,
boolean useRightAxis, boolean useRightAxis,
boolean drawFilled) { boolean drawFilled) {
if (axisType == GPXDataSetAxisType.TIME) { if (axisType == GPXDataSetAxisType.TIME || axisType == GPXDataSetAxisType.TIMEOFDAY) {
return null; return null;
} }
OsmandSettings settings = ctx.getSettings(); OsmandSettings settings = ctx.getSettings();
@ -1767,7 +1798,8 @@ public class GpxUiHelper {
public enum GPXDataSetAxisType { public enum GPXDataSetAxisType {
DISTANCE(R.string.distance, R.drawable.ic_action_marker_dark), DISTANCE(R.string.distance, R.drawable.ic_action_marker_dark),
TIME(R.string.shared_string_time, R.drawable.ic_action_time); TIME(R.string.shared_string_time, R.drawable.ic_action_time),
TIMEOFDAY(R.string.time_of_day, R.drawable.ic_action_time_span);
private int stringId; private int stringId;
private int imageId; private int imageId;

View file

@ -186,7 +186,8 @@ public class TrackDetailsMenu {
if (ds != null && ds.size() > 0) { if (ds != null && ds.size() > 0) {
TrkSegment segment = getTrackSegment(chart); TrkSegment segment = getTrackSegment(chart);
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0); OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) { if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME ||
gpxItem.chartAxisType == GPXDataSetAxisType.TIMEOFDAY) {
float time = pos * 1000; float time = pos * 1000;
for (WptPt p : segment.points) { for (WptPt p : segment.points) {
if (p.time - gpxItem.analysis.startTime >= time) { if (p.time - gpxItem.analysis.startTime >= time) {
@ -222,12 +223,11 @@ public class TrackDetailsMenu {
if (ds != null && ds.size() > 0) { if (ds != null && ds.size() > 0) {
TrkSegment segment = getTrackSegment(chart); TrkSegment segment = getTrackSegment(chart);
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0); OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) { if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME || gpxItem.chartAxisType == GPXDataSetAxisType.TIMEOFDAY) {
float startTime = startPos * 1000; float startTime = startPos * 1000;
float endTime = endPos * 1000; float endTime = endPos * 1000;
for (WptPt p : segment.points) { for (WptPt p : segment.points) {
if (p.time - gpxItem.analysis.startTime >= startTime && if (p.time - gpxItem.analysis.startTime >= startTime && p.time - gpxItem.analysis.startTime <= endTime) {
p.time - gpxItem.analysis.startTime <= endTime) {
if (left == 0 && right == 0) { if (left == 0 && right == 0) {
left = p.getLongitude(); left = p.getLongitude();
right = p.getLongitude(); right = p.getLongitude();
@ -501,14 +501,16 @@ public class TrackDetailsMenu {
boolean hasSlopeChart = false; boolean hasSlopeChart = false;
if (analysis.hasElevationData) { if (analysis.hasElevationData) {
availableTypes.add(new GPXDataSetType[] { GPXDataSetType.ALTITUDE }); availableTypes.add(new GPXDataSetType[] { GPXDataSetType.ALTITUDE });
if (gpxItem.chartAxisType != GPXDataSetAxisType.TIME) { if (gpxItem.chartAxisType != GPXDataSetAxisType.TIME
&& gpxItem.chartAxisType != GPXDataSetAxisType.TIMEOFDAY) {
availableTypes.add(new GPXDataSetType[]{GPXDataSetType.SLOPE}); availableTypes.add(new GPXDataSetType[]{GPXDataSetType.SLOPE});
} }
} }
if (analysis.hasSpeedData) { if (analysis.hasSpeedData) {
availableTypes.add(new GPXDataSetType[] { GPXDataSetType.SPEED }); availableTypes.add(new GPXDataSetType[] { GPXDataSetType.SPEED });
} }
if (analysis.hasElevationData && gpxItem.chartAxisType != GPXDataSetAxisType.TIME) { if (analysis.hasElevationData && gpxItem.chartAxisType != GPXDataSetAxisType.TIME
&& gpxItem.chartAxisType != GPXDataSetAxisType.TIMEOFDAY) {
availableTypes.add(new GPXDataSetType[] { GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE }); availableTypes.add(new GPXDataSetType[] { GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE });
} }
if (analysis.hasElevationData && analysis.hasSpeedData) { if (analysis.hasElevationData && analysis.hasSpeedData) {
@ -541,7 +543,6 @@ public class TrackDetailsMenu {
return true; return true;
} }
}); });
} }
optionsMenu.show(); optionsMenu.show();
} }
@ -560,6 +561,9 @@ public class TrackDetailsMenu {
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) { if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_time)); xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_time));
xAxisTitle.setText(app.getString(R.string.shared_string_time)); xAxisTitle.setText(app.getString(R.string.shared_string_time));
} else if (gpxItem.chartAxisType == GPXDataSetAxisType.TIMEOFDAY) {
xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_time_span));
xAxisTitle.setText(app.getString(R.string.time_of_day));
} else { } else {
xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_marker_dark)); xAxisIcon.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_marker_dark));
xAxisTitle.setText(app.getString(R.string.distance)); xAxisTitle.setText(app.getString(R.string.distance));
@ -570,23 +574,21 @@ public class TrackDetailsMenu {
public void onClick(View v) { public void onClick(View v) {
final PopupMenu optionsMenu = new PopupMenu(mapActivity, v); final PopupMenu optionsMenu = new PopupMenu(mapActivity, v);
DirectionsDialogs.setupPopUpMenuIcon(optionsMenu); DirectionsDialogs.setupPopUpMenuIcon(optionsMenu);
final GPXDataSetAxisType type; for (final GPXDataSetAxisType type : GPXDataSetAxisType.values()) {
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) { MenuItem menuItem = optionsMenu.getMenu()
type = GPXDataSetAxisType.DISTANCE; .add(type.getStringId()).setIcon(type.getImageDrawable(app));
} else { menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
type = GPXDataSetAxisType.TIME; @Override
public boolean onMenuItemClick(MenuItem mItem) {
gpxItem.chartAxisType = type;
gpxItem.chartHighlightPos = -1;
gpxItem.chartMatrix = null;
update();
return true;
}
});
} }
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(); optionsMenu.show();
} }
}); });