diff --git a/src/main/java/de/dennisguse/opentracks/chart/ChartFragment.java b/src/main/java/de/dennisguse/opentracks/chart/ChartFragment.java index a847f8a26..11a735734 100644 --- a/src/main/java/de/dennisguse/opentracks/chart/ChartFragment.java +++ b/src/main/java/de/dennisguse/opentracks/chart/ChartFragment.java @@ -86,6 +86,7 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener { }); } } + if (PreferencesUtils.isKey(R.string.stats_rate_key, key)) { boolean reportSpeed = PreferencesUtils.isReportSpeed(activityTypeLocalized); if (reportSpeed != viewBinding.chartView.getReportSpeed()) { @@ -99,6 +100,21 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener { }); } } + + if (PreferencesUtils.isKey(R.string.chart_display_elevation_key, key)) { + viewBinding.chartView.setShowElevation(PreferencesUtils.shouldShowElevation()); + refreshChart(); + } + + if (PreferencesUtils.isKey(R.string.chart_display_pace_or_speed_key, key)) { + viewBinding.chartView.setShowPaceOrSpeed(PreferencesUtils.shouldShowPaceOrSpeed()); + refreshChart(); + } + + if (PreferencesUtils.isKey(R.string.chart_display_heart_rate_key, key)) { + viewBinding.chartView.setShowHeartRate(PreferencesUtils.shouldShowHeartRate()); + refreshChart(); + } } }; @@ -273,4 +289,13 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener { fragmentActivity.runOnUiThread(runnable); } } + + private void refreshChart() { + runOnUiThread(() -> { + if (isResumed()) { + viewBinding.chartView.invalidate(); + viewBinding.chartView.requestLayout(); + } + }); + } } diff --git a/src/main/java/de/dennisguse/opentracks/chart/ChartView.java b/src/main/java/de/dennisguse/opentracks/chart/ChartView.java index ff96cac67..b95a390cd 100644 --- a/src/main/java/de/dennisguse/opentracks/chart/ChartView.java +++ b/src/main/java/de/dennisguse/opentracks/chart/ChartView.java @@ -86,8 +86,10 @@ public class ChartView extends View { } private final List seriesList = new LinkedList<>(); + private final ChartValueSeries elevationSeries; private final ChartValueSeries speedSeries; private final ChartValueSeries paceSeries; + private final ChartValueSeries heartRateSeries; private final LinkedList chartPoints = new LinkedList<>(); private final List markers = new LinkedList<>(); @@ -123,6 +125,7 @@ public class ChartView extends View { private boolean chartByDistance = false; private UnitSystem unitSystem = UnitSystem.defaultUnitSystem(); private boolean reportSpeed = true; + private boolean showPaceOrSpeed = true; private boolean showPointer = false; private final GestureDetectorCompat detectorScrollFlingTab = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() { @@ -176,17 +179,17 @@ public class ChartView extends View { int fontSizeSmall = ThemeUtils.getFontSizeSmallInPx(context); int fontSizeMedium = ThemeUtils.getFontSizeMediumInPx(context); - seriesList.add(new ChartValueSeries(context, - Integer.MIN_VALUE, - Integer.MAX_VALUE, - new int[]{5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000}, - R.string.description_altitude_metric, - R.string.description_altitude_imperial, - R.string.description_altitude_imperial, - R.color.chart_altitude_fill, - R.color.chart_altitude_border, - fontSizeSmall, - fontSizeMedium) { + elevationSeries = new ChartValueSeries(context, + Integer.MIN_VALUE, + Integer.MAX_VALUE, + new int[]{5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000}, + R.string.description_altitude_metric, + R.string.description_altitude_imperial, + R.string.description_altitude_imperial, + R.color.chart_altitude_fill, + R.color.chart_altitude_border, + fontSizeSmall, + fontSizeMedium) { @Override protected Double extractDataFromChartPoint(@NonNull ChartPoint chartPoint) { return chartPoint.altitude(); @@ -196,7 +199,8 @@ public class ChartView extends View { protected boolean drawIfChartPointHasNoData() { return false; } - }); + }; + seriesList.add(elevationSeries); speedSeries = new ChartValueSeries(context, 0, @@ -244,10 +248,15 @@ public class ChartView extends View { }; seriesList.add(paceSeries); - seriesList.add(new ChartValueSeries(context, + heartRateSeries = new ChartValueSeries(context, 0, Integer.MAX_VALUE, - new int[]{25, 50}, + // For Zone 5 cardio, the 25 value should result in nice visuals, as the values + // will range from ~70 - ~180 (around 4.5 intervals). + // For Zone 1 cardio, the 15 value should result in nice visuals, as the values + // will range from ~70 - ~120 (around 3.5 intervals) + // The fallback of 50 should give appropriate visuals for values outside this range. + new int[]{15, 25, 50}, R.string.description_sensor_heart_rate, R.string.description_sensor_heart_rate, R.string.description_sensor_heart_rate, @@ -264,7 +273,8 @@ public class ChartView extends View { protected boolean drawIfChartPointHasNoData() { return false; } - }); + }; + seriesList.add(heartRateSeries); seriesList.add(new ChartValueSeries(context, 0, @@ -343,9 +353,15 @@ public class ChartView extends View { setClickable(true); updateDimensions(); - // either speedSeries or paceSeries should be enabled. - speedSeries.setEnabled(reportSpeed); - paceSeries.setEnabled(!reportSpeed); + // Either speedSeries or paceSeries should be enabled, if one is shown. + if (showPaceOrSpeed) { + speedSeries.setEnabled(reportSpeed); + paceSeries.setEnabled(!reportSpeed); + } + + // Defaults for our chart series. + heartRateSeries.setEnabled(true); + elevationSeries.setEnabled(true); } @Override @@ -379,6 +395,12 @@ public class ChartView extends View { } public boolean applyReportSpeed() { + if (!showPaceOrSpeed) { + paceSeries.setEnabled(false); + speedSeries.setEnabled(false); + return true; + } + if (reportSpeed) { if (!speedSeries.isEnabled()) { speedSeries.setEnabled(true); @@ -396,6 +418,20 @@ public class ChartView extends View { return false; } + void setShowElevation(boolean value) { + elevationSeries.setEnabled(value); + } + void setShowPaceOrSpeed(boolean value) { + showPaceOrSpeed = value; + + // we want to make sure we show whatever version the user has + // selected when we turn this back on. + applyReportSpeed(); + } + void setShowHeartRate(boolean value) { + heartRateSeries.setEnabled(value); + } + public void setShowPointer(boolean value) { showPointer = value; } @@ -644,10 +680,18 @@ public class ChartView extends View { */ private void drawSeriesTitles(Canvas canvas) { Iterator tpI = titleDimensions.titlePositions.iterator(); + for (ChartValueSeries chartValueSeries : seriesList) { if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) { String title = getContext().getString(chartValueSeries.getTitleId(unitSystem)); Paint paint = chartValueSeries.getTitlePaint(); + + // It is possible for the titlePositions to become empty temporarily, while switching between + // chart screens quickly. + if (!tpI.hasNext()) { + return; + } + TitlePosition tp = tpI.next(); int y = topBorder - spacer - (titleDimensions.lineCount - tp.line) * (titleDimensions.lineHeight + spacer); canvas.drawText(title, tp.xPos + getScrollX(), y, paint); @@ -774,7 +818,7 @@ public class ChartView extends View { //TODO int markerXPosition = x - spacer; - int index = titleDimensions.titlePositions.size() - 1; // index only onver the visible chart series + int index = titleDimensions.titlePositions.size() - 1; // index only over the visible chart series final int lastDrawn2ndLineMarkerIndex = getYmarkerCountOn1stLine(); for (int i = seriesList.size()-1; i>=0 ;--i) { // draw markers from the last series to achieve right alignment ChartValueSeries chartValueSeries = seriesList.get(i); diff --git a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java index 38cfbe60a..af3f002c2 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java @@ -318,6 +318,21 @@ public class PreferencesUtils { return getBoolean(R.string.stats_fullscreen_while_recording_key, DEFAULT); } + public static boolean shouldShowElevation() { + final boolean DEFAULT = resources.getBoolean(R.bool.chart_display_elevation_default); + return getBoolean(R.string.chart_display_elevation_key, DEFAULT); + } + + public static boolean shouldShowPaceOrSpeed() { + final boolean DEFAULT = resources.getBoolean(R.bool.chart_display_pace_or_speed_default); + return getBoolean(R.string.chart_display_pace_or_speed_key, DEFAULT); + } + + public static boolean shouldShowHeartRate() { + final boolean DEFAULT = resources.getBoolean(R.bool.chart_display_heart_rate_default); + return getBoolean(R.string.chart_display_heart_rate_key, DEFAULT); + } + public static boolean shouldUseDynamicColors() { final boolean DEFAULT = resources.getBoolean(R.bool.settings_ui_dynamic_colors_default); return getBoolean(R.string.settings_ui_dynamic_colors_key, DEFAULT); diff --git a/src/main/res/values/settings.xml b/src/main/res/values/settings.xml index 4a3ac2651..db5faac93 100644 --- a/src/main/res/values/settings.xml +++ b/src/main/res/values/settings.xml @@ -1,14 +1,6 @@ - trackdetail_show_on_lockscreen_while_recording - false - - trackdetail_keep_screen_on_while_recording - false - - trackdetail_fullscreen_while_recording - false settingsDefaults @@ -279,9 +271,32 @@ showIntroduction true + + uiDynamicColors false + + trackdetail_show_on_lockscreen_while_recording + false + + trackdetail_keep_screen_on_while_recording + false + + trackdetail_fullscreen_while_recording + false + + + chart_display_elevation + true + + chart_display_pace_or_speed + true + + chart_display_heart_rate + true + + localeKey diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index f9de7b82f..baf41380f 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -344,6 +344,11 @@ limitations under the License. By distance By time + Charts + Display elevation + Display pace or speed + Display heart rate + Recording Theme changes may require a manual restart. diff --git a/src/main/res/xml/settings_user_interface.xml b/src/main/res/xml/settings_user_interface.xml index e1eb4fa90..9596502f6 100644 --- a/src/main/res/xml/settings_user_interface.xml +++ b/src/main/res/xml/settings_user_interface.xml @@ -58,4 +58,23 @@ android:title="@string/settings_recording_fullscreen_on_while_recording_title" /> + + + + + + + \ No newline at end of file