UI: new profile switch rendering

This commit is contained in:
Milos Kozak 2022-05-22 00:13:09 +02:00
parent 9259be46d7
commit 8b3c4c18c6
13 changed files with 100 additions and 96 deletions

View file

@ -339,9 +339,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
val graphData = GraphData(injector, binding.bgGraph, overviewData)
val menuChartSettings = overviewMenus.setting
graphData.addInRangeArea(overviewData.fromTime, overviewData.endTime, defaultValueHelper.determineLowLine(), defaultValueHelper.determineHighLine())
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal], context)
if (buildHelper.isDev()) graphData.addBucketedData()
graphData.addTreatments()
graphData.addTreatments(context)
if (menuChartSettings[0][OverviewMenus.CharType.TREAT.ordinal])
graphData.addTherapyEvents()
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])

View file

@ -68,7 +68,6 @@ import info.nightscout.androidaps.utils.TrendCalculator
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.androidaps.utils.ui.SingleClickButton
import info.nightscout.androidaps.utils.ui.UIRunnable
@ -971,9 +970,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
val menuChartSettings = overviewMenus.setting
graphData.addInRangeArea(overviewData.fromTime, overviewData.endTime, defaultValueHelper.determineLowLine(), defaultValueHelper.determineHighLine())
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal], context)
if (buildHelper.isDev()) graphData.addBucketedData()
graphData.addTreatments()
graphData.addTreatments(context)
if (menuChartSettings[0][OverviewMenus.CharType.TREAT.ordinal])
graphData.addTherapyEvents()
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.overview.graphData
import android.content.Context
import android.graphics.DashPathEffect
import android.graphics.Paint
import com.jjoe64.graphview.GraphView
@ -10,14 +11,13 @@ import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.general.overview.OverviewData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.AreaGraphSeries
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DoubleDataPoint
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TimeAsXAxisLabelFormatter
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.shared.logging.AAPSLogger
import java.util.*
import javax.inject.Inject
import kotlin.math.abs
@ -48,13 +48,16 @@ class GraphData(
addSeries(overviewData.bucketedGraphSeries)
}
fun addBgReadings(addPredictions: Boolean) {
fun addBgReadings(addPredictions: Boolean, context: Context?) {
maxY = if (overviewData.bgReadingsArray.isEmpty()) {
if (units == GlucoseUnit.MGDL) 180.0 else 10.0
} else overviewData.maxBgValue
minY = 0.0
addSeries(overviewData.bgReadingGraphSeries)
if (addPredictions) addSeries(overviewData.predictionsGraphSeries)
overviewData.bgReadingGraphSeries.setOnDataPointTapListener { _, dataPoint ->
if (dataPoint is GlucoseValueDataPoint) ToastUtils.showToastInUiThread(context, dataPoint.label)
}
}
fun addInRangeArea(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double) {
@ -65,7 +68,7 @@ class GraphData(
addSeries(AreaGraphSeries(inRangeAreaDataPoints).also {
it.color = 0
it.isDrawBackground = true
it.backgroundColor = rh.gac(graph.context,R.attr.inRangeBackground)
it.backgroundColor = rh.gac(graph.context, R.attr.inRangeBackground)
})
}
@ -82,9 +85,13 @@ class GraphData(
addSeries(overviewData.temporaryTargetSeries)
}
fun addTreatments() {
fun addTreatments(context: Context?) {
maxY = maxOf(maxY, overviewData.maxTreatmentsValue)
addSeries(overviewData.treatmentsSeries)
overviewData.treatmentsSeries.setOnDataPointTapListener { _, dataPoint ->
if (dataPoint is EffectiveProfileSwitchDataPoint) ToastUtils.showToastInUiThread(context, dataPoint.data.originalCustomizedName)
if (dataPoint is BolusDataPoint) ToastUtils.showToastInUiThread(context, dataPoint.label)
}
}
fun addTherapyEvents() {

View file

@ -1,16 +1,14 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.content.Context
import android.graphics.Color
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import javax.inject.Inject
class BolusDataPoint @Inject constructor(
class BolusDataPoint(
val data: Bolus,
private val rh: ResourceHelper,
private val activePlugin: ActivePlugin,
@ -31,8 +29,8 @@ class BolusDataPoint @Inject constructor(
override fun color(context: Context?): Int =
if (data.type == Bolus.Type.SMB) rh.gac(context, R.attr.smbColor)
else if (data.isValid) rh.gac(context, R.attr.bolusDataPointColor)
else rh.gac(context, R.attr.alarmColor)
else if (data.isValid) rh.gac(context, R.attr.bolusDataPointColor)
else rh.gac(context, R.attr.alarmColor)
override fun setY(y: Double) {
yValue = y

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.content.Context
import android.graphics.Color
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
import info.nightscout.androidaps.interfaces.ResourceHelper
@ -9,11 +8,10 @@ import javax.inject.Inject
class EffectiveProfileSwitchDataPoint @Inject constructor(
val data: EffectiveProfileSwitch,
private val rh: ResourceHelper
private val rh: ResourceHelper,
private var yValue: Double
) : DataPointWithLabelInterface {
private var yValue = 0.0
override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = yValue
@ -21,10 +19,10 @@ class EffectiveProfileSwitchDataPoint @Inject constructor(
yValue = y
}
override val label get() = data.originalCustomizedName
override val label get() = if (data.originalPercentage != 100) data.originalPercentage.toString() + "%" else ""
override val duration = 0L
override val shape = PointsWithLabelGraphSeries.Shape.PROFILE
override val size = 10f
override val size = 2f
override fun color(context: Context?): Int {
return rh.gac(context, R.attr.profileSwitchColor)
}

View file

@ -5,9 +5,10 @@ import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.utils.DefaultValueHelper
import javax.inject.Inject
class GlucoseValueDataPoint @Inject constructor(
@ -24,7 +25,7 @@ class GlucoseValueDataPoint @Inject constructor(
override fun getY(): Double = valueToUnits(profileFunction.getUnits())
override fun setY(y: Double) {}
override val label: String? = null
override val label: String = Profile.toCurrentUnitsString(profileFunction, data.value)
override val duration = 0L
override val shape get() = if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION else PointsWithLabelGraphSeries.Shape.BG
override val size = 1f
@ -40,15 +41,15 @@ class GlucoseValueDataPoint @Inject constructor(
}
}
private fun predictionColor (context: Context?): Int {
return when (data.sourceSensor) {
GlucoseValue.SourceSensor.IOB_PREDICTION -> rh.gac(context, R.attr.iobColor)
GlucoseValue.SourceSensor.COB_PREDICTION -> rh.gac(context, R.attr.cobColor)
GlucoseValue.SourceSensor.A_COB_PREDICTION -> -0x7f000001 and rh.gac(context, R.attr.cobColor)
GlucoseValue.SourceSensor.UAM_PREDICTION -> rh.gac(context, R.attr.uamColor)
GlucoseValue.SourceSensor.ZT_PREDICTION -> rh.gac(context, R.attr.ztColor)
else -> rh.gac( context,R.attr.defaultTextColor)
}
private fun predictionColor(context: Context?): Int {
return when (data.sourceSensor) {
GlucoseValue.SourceSensor.IOB_PREDICTION -> rh.gac(context, R.attr.iobColor)
GlucoseValue.SourceSensor.COB_PREDICTION -> rh.gac(context, R.attr.cobColor)
GlucoseValue.SourceSensor.A_COB_PREDICTION -> -0x7f000001 and rh.gac(context, R.attr.cobColor)
GlucoseValue.SourceSensor.UAM_PREDICTION -> rh.gac(context, R.attr.uamColor)
GlucoseValue.SourceSensor.ZT_PREDICTION -> rh.gac(context, R.attr.ztColor)
else -> rh.gac(context, R.attr.defaultTextColor)
}
}
private val isPrediction: Boolean

View file

@ -1,52 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions;
import com.jjoe64.graphview.series.DataPointInterface;
import java.io.Serializable;
import java.util.Date;
/**
* Created by mike on 18.10.2017.
*/
public class ScaledDataPoint implements DataPointInterface, Serializable {
private static final long serialVersionUID=1428263342645L;
private final double x;
private final double y;
private final Scale scale;
public ScaledDataPoint(double x, double y, Scale scale) {
this.x=x;
this.y=y;
this.scale = scale;
}
public ScaledDataPoint(long x, double y, Scale scale) {
this.x=x;
this.y=y;
this.scale = scale;
}
public ScaledDataPoint(Date x, double y, Scale scale) {
this.x = x.getTime();
this.y = y;
this.scale = scale;
}
@Override
public double getX() {
return x;
}
@Override
public double getY() {
return scale.transform(y);
}
@Override
public String toString() {
return "["+x+"/"+y+"]";
}
}

View file

@ -0,0 +1,26 @@
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import com.jjoe64.graphview.series.DataPointInterface
open class ScaledDataPoint : DataPointInterface {
private val x: Double
private val y: Double
private val scale: Scale
constructor(x: Double, y: Double, scale: Scale) {
this.x = x
this.y = y
this.scale = scale
}
constructor(x: Long, y: Double, scale: Scale) {
this.x = x.toDouble()
this.y = y
this.scale = scale
}
override fun getX(): Double = x
override fun getY(): Double = scale.transform(y)
override fun toString(): String = "[$x/$y]"
}

View file

@ -12,6 +12,7 @@ import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.GlucoseUnit
import info.nightscout.androidaps.interfaces.Profile
import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.OverviewData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
@ -21,7 +22,6 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.interfaces.ResourceHelper
import javax.inject.Inject
class PrepareTreatmentsDataWorker(
@ -72,7 +72,7 @@ class PrepareTreatmentsDataWorker(
// ProfileSwitch
repository.getEffectiveProfileSwitchDataFromTimeToTime(data.overviewData.fromTime, data.overviewData.endTime, true).blockingGet()
.map { EffectiveProfileSwitchDataPoint(it, rh) }
.map { EffectiveProfileSwitchDataPoint(it, rh, data.overviewData.maxBgValue) }
.forEach(filteredTreatments::add)
// OfflineEvent

View file

@ -25,17 +25,24 @@ package info.nightscout.androidaps.plugins.general.overview.graphExtensions;
*/
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import androidx.core.content.ContextCompat;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.BaseSeries;
import java.util.Iterator;
import info.nightscout.androidaps.core.R;
/**
* Series that plots the data as points.
* The points can be different shapes or a
@ -108,8 +115,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
/**
* plot the data to the viewport
*
* @param graphView graphview
* @param canvas canvas to draw on
* @param graphView graphview
* @param canvas canvas to draw on
* @param isSecondScale whether it is the second scale
*/
@Override
@ -264,6 +271,24 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
canvas.drawText(value.getLabel(), endX, endY, mPaint);
}
} else if (value.getShape() == Shape.PROFILE) {
Drawable drawable = ContextCompat.getDrawable(graphView.getContext(), R.drawable.ic_ribbon_profile);
drawable.setColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY);
drawable.setBounds((int) endX - drawable.getIntrinsicWidth() / 2, 0,
(int) (endX + drawable.getIntrinsicWidth() / 2),
drawable.getIntrinsicHeight());
drawable.draw(canvas);
mPaint.setTextSize(scaledTextSize * 0.8f);
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setColor(value.color(graphView.getContext()));
Rect bounds = new Rect();
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
float px = endX - bounds.width() / 2.0f;
float py = (float) (drawable.getIntrinsicHeight() + 30);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(value.getLabel(), px, py, mPaint);
/*
mPaint.setStrokeWidth(0);
if (value.getLabel() != null) {
//mPaint.setTextSize((int) (scaledPxSize * 3));
@ -280,7 +305,9 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint);
canvas.restore();
}
*/
} else if (value.getShape() == Shape.MBG) {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
@ -364,9 +391,9 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
/**
* helper to render triangle
*
* @param point array with 3 coordinates
* @param point array with 3 coordinates
* @param canvas canvas to draw on
* @param paint paint object
* @param paint paint object
*/
private void drawArrows(Point[] point, Canvas canvas, Paint paint) {
canvas.save();

View file

@ -90,7 +90,7 @@
<color name="zt">#00d2d2</color>
<color name="calibration">#E83258</color>
<color name="bolusDataPointColor">#00FFFF</color>
<color name="profileSwitch">#00FFFF</color>
<color name="profileSwitch">#FFFFFF</color>
<color name="sens">#008585</color>
<color name="ribbonDefault">#5a595b</color>

View file

@ -90,7 +90,7 @@
<color name="zt">#00d2d2</color>
<color name="calibration">#E83258</color>
<color name="bolusDataPointColor">#00FFFF</color>
<color name="profileSwitch">#00FFFF</color>
<color name="profileSwitch">#000000</color>
<color name="red">#FF0000</color>
<color name="blue">#0000FF</color>
<color name="sens">#008585</color>