diff --git a/app/src/main/assets/sports_pingpong.svg b/app/src/main/assets/sports_pingpong.svg index 48e523f21..9c840213f 100644 --- a/app/src/main/assets/sports_pingpong.svg +++ b/app/src/main/assets/sports_pingpong.svg @@ -23,7 +23,7 @@ image/svg+xml - + @@ -53,7 +53,8 @@ inkscape:window-x="0" inkscape:window-y="38" inkscape:window-maximized="1" - inkscape:current-layer="svg12"> + inkscape:current-layer="svg12" + inkscape:document-rotation="0"> + id="g1460"> + + + + + + - - - - - - - - - - - - - + sodipodi:cy="-18.507776" + sodipodi:cx="2.4408588" + transform="rotate(110)" + d="m 6.5814574,-15.795621 a 4.9498253,4.9496808 0 0 1 -5.5597185,2.029738 4.9498253,4.9496808 0 0 1 -3.5306986,-4.750094 4.9498253,4.9496808 0 0 1 3.5464206,-4.73837 4.9498253,4.9496808 0 0 1 5.5529616,2.048152" /> + + + + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesChartFragment.java new file mode 100644 index 000000000..394c01bef --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesChartFragment.java @@ -0,0 +1,176 @@ +/* Copyright (C) 2015-2020 Andreas Shimokawa, Carsten Pfeiffer, Daniele + Gobbetti, Dikay900, Pavel Elagin + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.activities; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.LegendEntry; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.activities.charts.AbstractChartFragment; +import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsData; +import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsHost; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; + + +public class ActivitySummariesChartFragment extends AbstractChartFragment { + private static final Logger LOG = LoggerFactory.getLogger(ActivitySummariesChartFragment.class); + + private LineChart mChart; + private int startTime; + private int endTime; + private GBDevice gbDevice; + + public void setDateAndGetData(GBDevice gbDevice, long startTime, long endTime) { + this.startTime = (int) startTime; + this.endTime = (int) endTime; + this.gbDevice = gbDevice; + populate_charts_data(); + } + + private void populate_charts_data() { + try (DBHandler handler = GBApplication.acquireDB()) { + int LEGEND_TEXT_COLOR = GBApplication.getTextColor(getContext()); + List samples = getSamples(handler, gbDevice, this.startTime, this.endTime); + DefaultChartsData dcd = refresh(this.gbDevice, samples); + + mChart.getLegend().setTextColor(LEGEND_TEXT_COLOR); + mChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317 + mChart.getXAxis().setValueFormatter(dcd.getXValueFormatter()); + mChart.setData((LineData) dcd.getData()); + mChart.invalidate(); + } catch (Exception e) { + LOG.error("unable to get charts data", e); + } + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + init(); + View rootView = inflater.inflate(R.layout.fragment_charts, container, false); + mChart = rootView.findViewById(R.id.activitysleepchart); + setupChart(); + populate_charts_data(); + return rootView; + } + + @Override + public String getTitle() { + return getString(R.string.activity_sleepchart_activity_and_sleep); + } + + private void setupChart() { + mChart.setBackgroundColor(BACKGROUND_COLOR); + mChart.getDescription().setTextColor(DESCRIPTION_COLOR); + configureBarLineChartDefaults(mChart); + + XAxis x = mChart.getXAxis(); + x.setDrawLabels(true); + x.setDrawGridLines(false); + x.setEnabled(true); + x.setTextColor(CHART_TEXT_COLOR); + x.setDrawLimitLinesBehindData(true); + + YAxis y = mChart.getAxisLeft(); + y.setDrawGridLines(false); +// y.setDrawLabels(false); + // TODO: make fixed max value optional + y.setAxisMaximum(1f); + y.setAxisMinimum(0); + y.setDrawTopYLabelEntry(false); + y.setTextColor(CHART_TEXT_COLOR); + +// y.setLabelCount(5); + y.setEnabled(true); + + YAxis yAxisRight = mChart.getAxisRight(); + yAxisRight.setDrawGridLines(false); + yAxisRight.setEnabled(supportsHeartrate(gbDevice)); + yAxisRight.setDrawLabels(true); + yAxisRight.setDrawTopYLabelEntry(true); + yAxisRight.setTextColor(CHART_TEXT_COLOR); + yAxisRight.setAxisMaximum(HeartRateUtils.getInstance().getMaxHeartRate()); + yAxisRight.setAxisMinimum(HeartRateUtils.getInstance().getMinHeartRate()); + + } + + @Override + protected List getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) { + return getAllSamples(db, device, tsFrom, tsTo); + } + + @Override + protected void setupLegend(Chart chart) { + List legendEntries = new ArrayList<>(5); + + LegendEntry activityEntry = new LegendEntry(); + activityEntry.label = akActivity.label; + activityEntry.formColor = akActivity.color; + legendEntries.add(activityEntry); + + if (supportsHeartrate(gbDevice)) { + LegendEntry hrEntry = new LegendEntry(); + hrEntry.label = HEARTRATE_LABEL; + hrEntry.formColor = HEARTRATE_COLOR; + legendEntries.add(hrEntry); + } + + chart.getLegend().setCustom(legendEntries); + chart.getLegend().setWordWrapEnabled(true); + chart.getLegend().setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); + } + + @Override + protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) { + return null; + } + + @Override + protected void renderCharts() { + } + + protected Entry createLineEntry(float value, int xValue) { + return new Entry(xValue, value); + } + + @Override + protected void updateChartsnUIThread(ChartsData chartsData) { + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummaryDetail.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummaryDetail.java index 439f89dcd..60c6a350e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummaryDetail.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummaryDetail.java @@ -67,7 +67,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.SwipeEvents; - //import nodomain.freeyourgadget.gadgetbridge.util.OnSwipeTouchListener; public class ActivitySummaryDetail extends AbstractGBActivity { @@ -123,6 +122,13 @@ public class ActivitySummaryDetail extends AbstractGBActivity { this, R.anim.bounceright); + final ActivitySummariesChartFragment activitySummariesChartFragment = new ActivitySummariesChartFragment(); + + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.fragmentHolder, activitySummariesChartFragment) + .commit(); + layout.setOnTouchListener(new SwipeEvents(this) { @Override public void onSwipeRight() { @@ -131,6 +137,7 @@ public class ActivitySummaryDetail extends AbstractGBActivity { currentItem = newItem; makeSummaryHeader(newItem); makeSummaryContent(newItem); + activitySummariesChartFragment.setDateAndGetData(gbDevice, currentItem.getStartTime().getTime()/1000, currentItem.getEndTime().getTime()/1000); layout.startAnimation(animFadeRight); } else { @@ -145,6 +152,7 @@ public class ActivitySummaryDetail extends AbstractGBActivity { currentItem = newItem; makeSummaryHeader(newItem); makeSummaryContent(newItem); + activitySummariesChartFragment.setDateAndGetData(gbDevice, currentItem.getStartTime().getTime()/1000, currentItem.getEndTime().getTime()/1000); layout.startAnimation(animFadeLeft); } else { layout.startAnimation(animBounceLeft); @@ -156,8 +164,10 @@ public class ActivitySummaryDetail extends AbstractGBActivity { if (currentItem != null) { makeSummaryHeader(currentItem); makeSummaryContent(currentItem); + activitySummariesChartFragment.setDateAndGetData(gbDevice, currentItem.getStartTime().getTime()/1000, currentItem.getEndTime().getTime()/1000); } + //allows long-press.switch of data being in raw form or recalculated ImageView activity_icon = findViewById(R.id.item_image); activity_icon.setOnLongClickListener(new View.OnLongClickListener() { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SimpleChartsHost.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SimpleChartsHost.java new file mode 100644 index 000000000..e69de29bb diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java index f49757829..392b90815 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java @@ -420,7 +420,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { */ protected abstract void renderCharts(); - protected DefaultChartsData refresh(GBDevice gbDevice, List samples) { + public DefaultChartsData refresh(GBDevice gbDevice, List samples) { // Calendar cal = GregorianCalendar.getInstance(); // cal.clear(); TimestampTranslation tsTranslation = new TimestampTranslation(); @@ -844,7 +844,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { * It does this so that the large timestamp values can be used * floating point values, where the mantissa is just 24 bits. */ - protected static class TimestampTranslation { + public static class TimestampTranslation { private int tsOffset = -1; public int shorten(int timestamp) { diff --git a/app/src/main/res/drawable/ic_activity_pingpong.xml b/app/src/main/res/drawable/ic_activity_pingpong.xml index 2f4684530..73f7879ed 100644 --- a/app/src/main/res/drawable/ic_activity_pingpong.xml +++ b/app/src/main/res/drawable/ic_activity_pingpong.xml @@ -4,17 +4,17 @@ android:viewportWidth="24" android:viewportHeight="24"> - diff --git a/app/src/main/res/layout/activity_summary_details.xml b/app/src/main/res/layout/activity_summary_details.xml index 0f324599f..d2fd8a22e 100644 --- a/app/src/main/res/layout/activity_summary_details.xml +++ b/app/src/main/res/layout/activity_summary_details.xml @@ -165,6 +165,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + + +