From daa8fa62be3500c77adb1632e3d8181c5c41ac87 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 24 Apr 2020 15:55:06 +0200 Subject: [PATCH] HistoryBrowser refactor --- .../historyBrowser/HistoryBrowseActivity.java | 378 ------------------ .../historyBrowser/HistoryBrowseActivity.kt | 330 +++++++++++++++ .../res/layout/activity_historybrowse.xml | 75 ++-- 3 files changed, 356 insertions(+), 427 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.java create mode 100644 app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.java deleted file mode 100644 index 4ed1c3b8b7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.java +++ /dev/null @@ -1,378 +0,0 @@ -package info.nightscout.androidaps.historyBrowser; - -import android.os.Bundle; -import android.os.SystemClock; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.SeekBar; -import android.widget.TextView; - -import androidx.appcompat.widget.PopupMenu; -import androidx.core.content.res.ResourcesCompat; - -import com.jjoe64.graphview.GraphView; -import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; - -import java.util.Calendar; -import java.util.Date; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.events.EventCustomCalculationFinished; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction; -import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; -import info.nightscout.androidaps.plugins.general.overview.OverviewMenus; -import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.DefaultValueHelper; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.T; -import info.nightscout.androidaps.utils.buildHelper.BuildHelper; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.sharedPreferences.SP; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.CompositeDisposable; - -public class HistoryBrowseActivity extends NoSplashAppCompatActivity { - @Inject HasAndroidInjector injector; - @Inject AAPSLogger aapsLogger; - @Inject RxBusWrapper rxBus; - @Inject SP sp; - @Inject ResourceHelper resourceHelper; - @Inject ProfileFunction profileFunction; - @Inject DefaultValueHelper defaultValueHelper; - @Inject IobCobStaticCalculatorPlugin iobCobStaticCalculatorPlugin; - @Inject ActivePluginProvider activePlugin; - @Inject BuildHelper buildHelper; - @Inject FabricPrivacy fabricPrivacy; - @Inject OverviewMenus overviewMenus; - - private CompositeDisposable disposable = new CompositeDisposable(); - - ImageButton chartButton; - - boolean showBasal = true; - boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope; - - - Button buttonDate; - Button buttonZoom; - GraphView bgGraph; - GraphView iobGraph; - SeekBar seekBar; - TextView noProfile; - TextView iobCalculationProgressView; - - private int rangeToDisplay = 24; // for graph - private long start = 0; - - - EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished(); - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_historybrowse); - - buttonDate = findViewById(R.id.historybrowse_date); - buttonZoom = findViewById(R.id.historybrowse_zoom); - bgGraph = findViewById(R.id.historyybrowse_bggraph); - iobGraph = findViewById(R.id.historybrowse_iobgraph); - seekBar = findViewById(R.id.historybrowse_seekBar); - noProfile = findViewById(R.id.historybrowse_noprofile); - iobCalculationProgressView = findViewById(R.id.overview_iobcalculationprogess); - - findViewById(R.id.historybrowse_left).setOnClickListener(v -> { - start -= T.hours(rangeToDisplay).msecs(); - updateGUI("onClickLeft"); - runCalculation("onClickLeft"); - }); - - findViewById(R.id.historybrowse_right).setOnClickListener(v -> { - start += T.hours(rangeToDisplay).msecs(); - updateGUI("onClickRight"); - runCalculation("onClickRight"); - }); - - findViewById(R.id.historybrowse_end).setOnClickListener(v -> { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.HOUR_OF_DAY, 0); - start = calendar.getTimeInMillis(); - updateGUI("onClickEnd"); - runCalculation("onClickEnd"); - }); - - findViewById(R.id.historybrowse_zoom).setOnClickListener(v -> { - rangeToDisplay += 6; - rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; - updateGUI("rangeChange"); - }); - - findViewById(R.id.historybrowse_zoom).setOnLongClickListener(v -> { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(start); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.HOUR_OF_DAY, 0); - start = calendar.getTimeInMillis(); - updateGUI("resetToMidnight"); - runCalculation("onLongClickZoom"); - return true; - }); - - findViewById(R.id.historybrowse_date).setOnClickListener(v -> { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(new Date(start)); - DatePickerDialog dpd = DatePickerDialog.newInstance( - (view, year, monthOfYear, dayOfMonth) -> { - Date date = new Date(0); - date.setYear(year - 1900); - date.setMonth(monthOfYear); - date.setDate(dayOfMonth); - date.setHours(0); - start = date.getTime(); - updateGUI("onClickDate"); - runCalculation("onClickDate"); - }, - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH) - ); - dpd.setThemeDark(true); - dpd.dismissOnPause(true); - dpd.show(getSupportFragmentManager(), "Datepickerdialog"); - }); - - bgGraph.getGridLabelRenderer().setGridColor(resourceHelper.gc(R.color.graphgrid)); - bgGraph.getGridLabelRenderer().reloadStyles(); - iobGraph.getGridLabelRenderer().setGridColor(resourceHelper.gc(R.color.graphgrid)); - iobGraph.getGridLabelRenderer().reloadStyles(); - iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false); - bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50); - iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50); - iobGraph.getGridLabelRenderer().setNumVerticalLabels(5); - - overviewMenus.setupChartMenu(findViewById(R.id.overview_chartMenuButton)); - } - - @Override - public void onPause() { - super.onPause(); - disposable.clear(); - iobCobStaticCalculatorPlugin.stopCalculation("onPause"); - } - - @Override - public void onResume() { - super.onResume(); - disposable.add(rxBus - .toObservable(EventAutosensCalculationFinished.class) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(event -> { - if (event.getCause() == eventCustomCalculationFinished) { - aapsLogger.debug(LTag.AUTOSENS, "EventAutosensCalculationFinished"); - synchronized (HistoryBrowseActivity.this) { - updateGUI("EventAutosensCalculationFinished"); - } - } - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventIobCalculationProgress.class) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(event -> { - if (iobCalculationProgressView != null) - iobCalculationProgressView.setText(event.getProgress()); - }, exception -> fabricPrivacy.logException(exception)) - ); - disposable.add(rxBus - .toObservable(EventRefreshOverview.class) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(event -> updateGUI("EventRefreshOverview") , fabricPrivacy::logException) - ); - // set start of current day - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.HOUR_OF_DAY, 0); - start = calendar.getTimeInMillis(); - runCalculation("onResume"); - SystemClock.sleep(1000); - updateGUI("onResume"); - } - - private void runCalculation(String from) { - long end = start + T.hours(rangeToDisplay).msecs(); - iobCobStaticCalculatorPlugin.stopCalculation(from); - iobCobStaticCalculatorPlugin.clearCache(); - iobCobStaticCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished); - } - - void updateGUI(String from) { - aapsLogger.debug(LTag.UI, "updateGUI from: " + from); - - if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null) - return; - - final PumpInterface pump = activePlugin.getActivePump(); - final Profile profile = profileFunction.getProfile(); - - if (profile == null) { - noProfile.setVisibility(View.VISIBLE); - return; - } else { - noProfile.setVisibility(View.GONE); - } - - final double lowLine = defaultValueHelper.determineLowLine(); - final double highLine = defaultValueHelper.determineHighLine(); - - buttonDate.setText(DateUtil.dateAndTimeString(start)); - buttonZoom.setText(String.valueOf(rangeToDisplay)); - - final boolean showPrediction = false; - - showBasal = sp.getBoolean("hist_showbasals", true); - showIob = sp.getBoolean("hist_showiob", true); - showCob = sp.getBoolean("hist_showcob", true); - showDev = sp.getBoolean("hist_showdeviations", false); - showRat = sp.getBoolean("hist_showratios", false); - showActPrim = sp.getBoolean("hist_showactivityprimary", false); - showActSec = sp.getBoolean("hist_showactivitysecondary", false); - showDevslope = sp.getBoolean("hist_showdevslope", false); - - //int hoursToFetch; - final long toTime; - final long fromTime; - //if (showPrediction) { - //int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000)); - //predHours = Math.min(2, predHours); - //predHours = Math.max(0, predHours); - //hoursToFetch = rangeToDisplay - predHours; - //toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific - //fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; - //endTime = toTime + predHours * 60 * 60 * 1000L; - //} else { - fromTime = start + T.secs(100).msecs(); - toTime = start + T.hours(rangeToDisplay).msecs(); - //} - - aapsLogger.debug(LTag.UI, "Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime)); - - final long pointer = System.currentTimeMillis(); - - // ------------------ 1st graph - - final GraphData graphData = new GraphData(injector, bgGraph, iobCobStaticCalculatorPlugin); - - // **** In range Area **** - graphData.addInRangeArea(fromTime, toTime, lowLine, highLine); - - // **** BG **** - if (showPrediction) -//graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed); - ; - else - graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null); - - // set manual x bounds to have nice steps - graphData.formatAxis(fromTime, toTime); - - if (showActPrim) { - graphData.addActivity(fromTime, toTime, false, 1d); - } - - // Treatments - graphData.addTreatments(fromTime, toTime); - - // add basal data - if (pump.getPumpDescription().isTempBasalCapable && showBasal) { - graphData.addBasals(fromTime, toTime, lowLine / graphData.getMaxY() / 1.2d); - } - - // **** NOW line **** - graphData.addNowLine(pointer); - - // ------------------ 2nd graph - - new Thread(() -> { - final GraphData secondGraphData = new GraphData(injector, iobGraph, iobCobStaticCalculatorPlugin); - - boolean useIobForScale = false; - boolean useCobForScale = false; - boolean useDevForScale = false; - boolean useRatioForScale = false; - boolean useIAForScale = false; - boolean useDSForScale = false; - - if (showIob) { - useIobForScale = true; - } else if (showCob) { - useCobForScale = true; - } else if (showDev) { - useDevForScale = true; - } else if (showRat) { - useRatioForScale = true; - } else if (showActSec) { - useIAForScale = true; - } else if (showDevslope) { - useDSForScale = true; - } - - if (showIob) - secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d, showPrediction); - if (showCob) - secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d); - if (showDev) - secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d); - if (showRat) - secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d); - if (showActSec) - secondGraphData.addActivity(fromTime, toTime, useIAForScale, useIAForScale ? 2d : 1d); - if (showDevslope) - secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d); - - // **** NOW line **** - // set manual x bounds to have nice steps - secondGraphData.formatAxis(fromTime, toTime); - secondGraphData.addNowLine(pointer); - - // do GUI update - runOnUiThread(() -> { - if (showIob || showCob || showDev || showRat || showActSec || showDevslope) { - iobGraph.setVisibility(View.VISIBLE); - } else { - iobGraph.setVisibility(View.GONE); - } - // finally enforce drawing of graphs - graphData.performUpdate(); - if (showIob || showCob || showDev || showRat || showActSec || showDevslope) - secondGraphData.performUpdate(); - }); - }).start(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt new file mode 100644 index 0000000000..0b260e9470 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/HistoryBrowseActivity.kt @@ -0,0 +1,330 @@ +package info.nightscout.androidaps.historyBrowser + +import android.app.DatePickerDialog +import android.graphics.Color +import android.os.Bundle +import android.os.SystemClock +import android.util.DisplayMetrics +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import com.jjoe64.graphview.GraphView +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.events.EventCustomCalculationFinished +import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction +import info.nightscout.androidaps.plugins.general.overview.OverviewMenus +import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DefaultValueHelper +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.buildHelper.BuildHelper +import info.nightscout.androidaps.utils.extensions.toVisibility +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.activity_historybrowse.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.util.* +import javax.inject.Inject + +class HistoryBrowseActivity : NoSplashAppCompatActivity() { + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var sp: SP + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var defaultValueHelper: DefaultValueHelper + @Inject lateinit var iobCobStaticCalculatorPlugin: IobCobStaticCalculatorPlugin + @Inject lateinit var activePlugin: ActivePluginProvider + @Inject lateinit var buildHelper: BuildHelper + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var overviewMenus: OverviewMenus + + private val disposable = CompositeDisposable() + + private val secondaryGraphs = ArrayList() + private val secondaryGraphsLabel = ArrayList() + + private var axisWidth: Int = 0 + private var rangeToDisplay = 24 // for graph + private var start: Long = 0 + + private var eventCustomCalculationFinished = EventCustomCalculationFinished() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_historybrowse) + + historybrowse_left.setOnClickListener { + start -= T.hours(rangeToDisplay.toLong()).msecs() + updateGUI("onClickLeft") + runCalculation("onClickLeft") + } + historybrowse_right.setOnClickListener { + start += T.hours(rangeToDisplay.toLong()).msecs() + updateGUI("onClickRight") + runCalculation("onClickRight") + } + historybrowse_end.setOnClickListener { + val calendar = Calendar.getInstance() + calendar.timeInMillis = System.currentTimeMillis() + calendar[Calendar.MILLISECOND] = 0 + calendar[Calendar.SECOND] = 0 + calendar[Calendar.MINUTE] = 0 + calendar[Calendar.HOUR_OF_DAY] = 0 + start = calendar.timeInMillis + updateGUI("onClickEnd") + runCalculation("onClickEnd") + } + historybrowse_zoom.setOnClickListener { + rangeToDisplay += 6 + rangeToDisplay = if (rangeToDisplay > 24) 6 else rangeToDisplay + updateGUI("rangeChange") + } + historybrowse_zoom.setOnLongClickListener { + val calendar = Calendar.getInstance() + calendar.timeInMillis = start + calendar[Calendar.MILLISECOND] = 0 + calendar[Calendar.SECOND] = 0 + calendar[Calendar.MINUTE] = 0 + calendar[Calendar.HOUR_OF_DAY] = 0 + start = calendar.timeInMillis + updateGUI("resetToMidnight") + runCalculation("onLongClickZoom") + true + } + + // create an OnDateSetListener + val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth -> + val cal = Calendar.getInstance() + cal.timeInMillis = start + cal.set(Calendar.YEAR, year) + cal.set(Calendar.MONTH, monthOfYear) + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth) + start = cal.timeInMillis + historybrowse_date?.text = DateUtil.dateAndTimeString(start) + updateGUI("onClickDate") + runCalculation("onClickDate") + } + + historybrowse_date.setOnClickListener { + val cal = Calendar.getInstance() + cal.timeInMillis = start + DatePickerDialog(this, dateSetListener, + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH) + ).show() + } + + val dm = DisplayMetrics() + windowManager?.defaultDisplay?.getMetrics(dm) + + axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80 + historybrowse_bggraph?.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid) + historybrowse_bggraph?.gridLabelRenderer?.reloadStyles() + historybrowse_bggraph?.gridLabelRenderer?.labelVerticalWidth = axisWidth + + overviewMenus.setupChartMenu(overview_chartMenuButton) + prepareGraphs() + } + + public override fun onPause() { + super.onPause() + disposable.clear() + iobCobStaticCalculatorPlugin.stopCalculation("onPause") + } + + public override fun onResume() { + super.onResume() + disposable.add(rxBus + .toObservable(EventAutosensCalculationFinished::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ event: EventAutosensCalculationFinished -> + // catch only events from iobCobStaticCalculatorPlugin + if (event.cause === eventCustomCalculationFinished) { + aapsLogger.debug(LTag.AUTOSENS, "EventAutosensCalculationFinished") + updateGUI("EventAutosensCalculationFinished") + } + }) { fabricPrivacy::logException } + ) + disposable.add(rxBus + .toObservable(EventIobCalculationProgress::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ overview_iobcalculationprogess?.text = it.progress }) { fabricPrivacy::logException } + ) + disposable.add(rxBus + .toObservable(EventRefreshOverview::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + prepareGraphs() + updateGUI("EventRefreshOverview") + }) { fabricPrivacy::logException } + ) + // set start of current day + val calendar = Calendar.getInstance() + calendar.timeInMillis = System.currentTimeMillis() + calendar[Calendar.MILLISECOND] = 0 + calendar[Calendar.SECOND] = 0 + calendar[Calendar.MINUTE] = 0 + calendar[Calendar.HOUR_OF_DAY] = 0 + start = calendar.timeInMillis + runCalculation("onResume") + SystemClock.sleep(1000) + updateGUI("onResume") + } + + private fun prepareGraphs() { + val numOfGraphs = overviewMenus.setting.size + + if (numOfGraphs != secondaryGraphs.size - 1) { + //aapsLogger.debug("New secondary graph count ${numOfGraphs-1}") + // rebuild needed + secondaryGraphs.clear() + secondaryGraphsLabel.clear() + history_iobgraph.removeAllViews() + for (i in 1 until numOfGraphs) { + val label = TextView(this) + label.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(100, 0, 0, -50) } + history_iobgraph.addView(label) + secondaryGraphsLabel.add(label) + val graph = GraphView(this) + graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, 0, 0, resourceHelper.dpToPx(10)) } + graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid) + graph.gridLabelRenderer?.reloadStyles() + graph.gridLabelRenderer?.isHorizontalLabelsVisible = false + graph.gridLabelRenderer?.labelVerticalWidth = axisWidth + graph.gridLabelRenderer?.numVerticalLabels = 3 + graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray + history_iobgraph.addView(graph) + secondaryGraphs.add(graph) + } + } + + } + + private fun runCalculation(from: String) { + val end = start + T.hours(rangeToDisplay.toLong()).msecs() + iobCobStaticCalculatorPlugin.stopCalculation(from) + iobCobStaticCalculatorPlugin.clearCache() + iobCobStaticCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished) + } + + @Synchronized + fun updateGUI(from: String) { + aapsLogger.debug(LTag.UI, "updateGUI from: $from") + val pump = activePlugin.activePump + val profile = profileFunction.getProfile() + + historybrowse_noprofile?.visibility = (profile == null).toVisibility() + profile ?: return + + val lowLine = defaultValueHelper.determineLowLine() + val highLine = defaultValueHelper.determineHighLine() + historybrowse_date?.text = DateUtil.dateAndTimeString(start) + historybrowse_zoom?.text = rangeToDisplay.toString() + + GlobalScope.launch(Dispatchers.Main) { + historybrowse_bggraph ?: return@launch + val graphData = GraphData(injector, historybrowse_bggraph, iobCobStaticCalculatorPlugin) + val secondaryGraphsData: ArrayList = ArrayList() + + // do preparation in different thread + withContext(Dispatchers.Default) { + val fromTime: Long = start + T.secs(100).msecs() + val toTime: Long = start + T.hours(rangeToDisplay.toLong()).msecs() + aapsLogger.debug(LTag.UI, "Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime)) + val pointer = System.currentTimeMillis() + + // **** In range Area **** + graphData.addInRangeArea(fromTime, toTime, lowLine, highLine) + + // **** BG **** + graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null) + + // set manual x bounds to have nice steps + graphData.formatAxis(fromTime, toTime) + + // Treatments + graphData.addTreatments(fromTime, toTime) + if (overviewMenus.setting[0][OverviewMenus.CharType.ACT.ordinal]) + graphData.addActivity(fromTime, toTime, false, 0.8) + + // add basal data + if (pump.pumpDescription.isTempBasalCapable && overviewMenus.setting[0][OverviewMenus.CharType.BAS.ordinal]) { + graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2) + } + + // add target line + graphData.addTargetLine(fromTime, toTime, profile, null) + + // **** NOW line **** + graphData.addNowLine(pointer) + + // ------------------ 2nd graph + for (g in 0 until secondaryGraphs.size) { + val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobStaticCalculatorPlugin) + var useIobForScale = false + var useCobForScale = false + var useDevForScale = false + var useRatioForScale = false + var useDSForScale = false + var useIAForScale = false + var useABSForScale = false + when { + overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true + overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true + } + + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, overviewMenus.setting[g + 1][OverviewMenus.CharType.PRE.ordinal]) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0) + if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0) + + // set manual x bounds to have nice steps + secondGraphData.formatAxis(fromTime, toTime) + secondGraphData.addNowLine(pointer) + secondaryGraphsData.add(secondGraphData) + } + } + // finally enforce drawing of graphs in UI thread + graphData.performUpdate() + for (g in 0 until secondaryGraphs.size) { + secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1) + secondaryGraphs[g].visibility = ( + overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] || + overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] + ).toVisibility() + secondaryGraphsData[g].performUpdate() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_historybrowse.xml b/app/src/main/res/layout/activity_historybrowse.xml index 2c2c5b8cd2..86f4f88711 100644 --- a/app/src/main/res/layout/activity_historybrowse.xml +++ b/app/src/main/res/layout/activity_historybrowse.xml @@ -64,65 +64,42 @@ + android:orientation="vertical"> - - - - - - - - - - - + + android:layout_height="match_parent" /> - + android:layout_alignParentTop="true" + android:layout_alignParentEnd="true" + android:paddingTop="5dp" + app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" /> - + - + + + android:layout_height="wrap_content" + android:orientation="vertical" /> - - - - -