HistoryBrowser refactor
This commit is contained in:
parent
55ecac882d
commit
daa8fa62be
3 changed files with 356 additions and 427 deletions
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<GraphView>()
|
||||||
|
private val secondaryGraphsLabel = ArrayList<TextView>()
|
||||||
|
|
||||||
|
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<GraphData> = 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,65 +64,42 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:orientation="vertical">
|
android:layout_weight="1">
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1">
|
|
||||||
|
|
||||||
<com.jjoe64.graphview.GraphView
|
|
||||||
android:id="@+id/historyybrowse_bggraph"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/overview_chartMenuButton"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/overview_iobcalculationprogess"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:textSize="15sp" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<com.jjoe64.graphview.GraphView
|
<com.jjoe64.graphview.GraphView
|
||||||
android:id="@+id/historybrowse_iobgraph"
|
android:id="@+id/historybrowse_bggraph"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="100dp" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<SeekBar
|
<ImageButton
|
||||||
android:id="@+id/historybrowse_seekBar"
|
android:id="@+id/overview_chartMenuButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:visibility="gone"/>
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
<TextView
|
||||||
|
android:id="@+id/overview_iobcalculationprogess"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
<ScrollView
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/history_iobgraph"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
Loading…
Reference in a new issue