Skip to content
Snippets Groups Projects
Commit d4474df5 authored by Volker Richert's avatar Volker Richert
Browse files

- change to scatter chat

- enable touch an chat
- implement long click to zoom out (fit to screen)
parent 53ea2ac4
No related branches found
No related tags found
No related merge requests found
...@@ -33,28 +33,28 @@ import android.util.Log; ...@@ -33,28 +33,28 @@ import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TextView.BufferType; import android.widget.TextView.BufferType;
import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.ScatterChart;
import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData;
import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.data.ScatterDataSet;
import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.ViewPortHandler; import com.github.mikephil.charting.utils.ViewPortHandler;
import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing; import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;
import com.mikepenz.google_material_typeface_library.GoogleMaterial; import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.materialdrawer.AccountHeaderBuilder; import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer; import com.mikepenz.materialdrawer.Drawer;
...@@ -64,9 +64,9 @@ import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; ...@@ -64,9 +64,9 @@ import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
...@@ -96,7 +96,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -96,7 +96,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
SharedPreferences prefs = null; SharedPreferences prefs = null;
private PumpInfo mActivePump; private PumpInfo mActivePump;
private TextView mTextViewLog; // This will eventually move to a status page. private TextView mTextViewLog; // This will eventually move to a status page.
private LineChart mChart; private ScatterChart mChart;
private Intent mNightscoutUploadService; private Intent mNightscoutUploadService;
private Handler mUiRefreshHandler = new Handler(); private Handler mUiRefreshHandler = new Handler();
private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable(); private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable();
...@@ -252,10 +252,43 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -252,10 +252,43 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
.build(); .build();
mTextViewLog = (TextView) findViewById(R.id.textview_log); mTextViewLog = (TextView) findViewById(R.id.textview_log);
mChart = (LineChart) findViewById(R.id.chart); mChart = (ScatterChart) findViewById(R.id.chart);
mChart.setDescription(null); // Hide the description mChart.setDescription(null); // Hide the description
mChart.setTouchEnabled(true);
mChart.setPinchZoom(true);
mChart.setHighlightPerDragEnabled(false);
mChart.setHighlightPerTapEnabled(false);
mChart.setOnChartGestureListener(new OnChartGestureListener() {
@Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
@Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
@Override
public void onChartLongPressed(MotionEvent me) {
mChart.fitScreen();
}
@Override
public void onChartDoubleTapped(MotionEvent me) {}
@Override
public void onChartSingleTapped(MotionEvent me) {}
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {}
@Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {}
@Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {}
});
XAxis xAxis = mChart.getXAxis(); XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(10f); xAxis.setTextSize(10f);
...@@ -622,113 +655,138 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -622,113 +655,138 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
// FIXME - grab the last item from the activePump's getPumpHistory // FIXME - grab the last item from the activePump's getPumpHistory
RealmResults<PumpStatusEvent> results = updateChart(mRealm.where(PumpStatusEvent.class)
mRealm.where(PumpStatusEvent.class) .greaterThan("eventDate", new Date(System.currentTimeMillis() - 1000*60*60*24))
.greaterThan("eventDate", new Date(System.currentTimeMillis() - 1000*60*60*24)) .findAllSorted("eventDate", Sort.ASCENDING));
.findAllSorted("eventDate", Sort.ASCENDING);
updateChart(results); if (pumpStatusData != null) {
if (pumpStatusData == null) {
return;
}
String sgvString, units; String sgvString, units;
if (prefs.getBoolean("mmolxl", false)) { if (prefs.getBoolean("mmolxl", false)) {
DecimalFormat df; DecimalFormat df;
if (prefs.getBoolean("mmolDecimals", false)) if (prefs.getBoolean("mmolDecimals", false))
df = new DecimalFormat("0.00"); df = new DecimalFormat("0.00");
else else
df = new DecimalFormat("0.0"); df = new DecimalFormat("0.0");
float fBgValue = (float) pumpStatusData.getSgv(); float fBgValue = (float) pumpStatusData.getSgv();
sgvString = df.format(fBgValue / 18.016f); sgvString = df.format(fBgValue / 18.016f);
units = "mmol/L"; units = "mmol/L";
Log.d(TAG, "mmolxl true --> " + sgvString); Log.d(TAG, "mmolxl true --> " + sgvString);
} else { } else {
sgvString = String.valueOf(pumpStatusData.getSgv()); sgvString = String.valueOf(pumpStatusData.getSgv());
units = "mg/dL"; units = "mg/dL";
Log.d(TAG, "mmolxl false --> " + sgvString); Log.d(TAG, "mmolxl false --> " + sgvString);
} }
textViewBg.setText(sgvString); textViewBg.setText(sgvString);
textViewUnits.setText(units); textViewUnits.setText(units);
textViewBgTime.setText(DateUtils.getRelativeTimeSpanString(pumpStatusData.getEventDate().getTime())); textViewBgTime.setText(DateUtils.getRelativeTimeSpanString(pumpStatusData.getEventDate().getTime()));
textViewTrend.setText(Html.fromHtml(renderTrendHtml(pumpStatusData.getCgmTrend()))); textViewTrend.setText(Html.fromHtml(renderTrendHtml(pumpStatusData.getCgmTrend())));
textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusData.getActiveInsulin())); textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusData.getActiveInsulin()));
ActionMenuItemView batIcon = ((ActionMenuItemView) findViewById(R.id.status_battery)); ActionMenuItemView batIcon = ((ActionMenuItemView) findViewById(R.id.status_battery));
if (batIcon != null) { if (batIcon != null) {
switch (pumpStatusData.getBatteryPercentage()) { switch (pumpStatusData.getBatteryPercentage()) {
case 0: case 0:
batIcon.setTitle("0%"); batIcon.setTitle("0%");
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_0)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_0));
break; break;
case 25: case 25:
batIcon.setTitle("25%"); batIcon.setTitle("25%");
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_25)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_25));
break; break;
case 50: case 50:
batIcon.setTitle("50%"); batIcon.setTitle("50%");
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_50)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_50));
break; break;
case 75: case 75:
batIcon.setTitle("75%"); batIcon.setTitle("75%");
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_75)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_75));
break; break;
case 100: case 100:
batIcon.setTitle("100%"); batIcon.setTitle("100%");
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_100)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_100));
break; break;
default: default:
batIcon.setTitle(getResources().getString(R.string.menu_name_status)); batIcon.setTitle(getResources().getString(R.string.menu_name_status));
batIcon.setIcon(getResources().getDrawable(R.drawable.battery_unknown)); batIcon.setIcon(getResources().getDrawable(R.drawable.battery_unknown));
}
} }
}
}
// Run myself again in 60 seconds; // Run myself again in 60 seconds;
mUiRefreshHandler.postDelayed(this, 60000L); mUiRefreshHandler.postDelayed(this, 60000L);
} }
private void updateChart(RealmResults<PumpStatusEvent> results) { private void updateChart(RealmResults<PumpStatusEvent> results) {
if (results.size() == 0) return; int size = results.size();
PumsStatusLineDataSet lineDataSet = new PumsStatusLineDataSet(results, "eventDate", "sgv"); if (size == 0) return;
lineDataSet.setDrawCircleHole(false); List<Entry> entries = new ArrayList<Entry>(size);
lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); int[] colors = new int[size * 2]; // getColor is called with (i/2)
lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722"));
lineDataSet.setLineWidth(1.8f); for (PumpStatusEvent pumpStatus: results) {
lineDataSet.setCircleRadius(3.6f); // turn your data into Entry objects
lineDataSet.setValueTextColor(Color.WHITE); int sgv = pumpStatus.getSgv(),
lineDataSet.setValueFormatter(new IValueFormatter() { pos = entries.size() * 2;
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { entries.add(new Entry(pumpStatus.getEventDate().getTime(), pumpStatus.getSgv()));
DecimalFormat df; if (sgv < 80)
colors[pos] = colors[pos+1] = Color.RED;
else if (sgv <= 180)
colors[pos] = colors[pos+1] = Color.GREEN;
else if (sgv <= 260)
colors[pos] = colors[pos+1] = Color.YELLOW;
else
colors[pos] = colors[pos+1] = Color.RED;
}
if (prefs.getBoolean("mmolxl", false)) { if (mChart.getData() == null) {
if (prefs.getBoolean("mmolDecimals", false)) mChart.setMinimumHeight(200);
df = new DecimalFormat("0.00");
else
df = new DecimalFormat("0.0");
return df.format(value / 18.016f); ScatterDataSet dataSet = new ScatterDataSet(entries, null);
} else {
return new DecimalFormat("0").format(value); dataSet.setColors(colors);
dataSet.setValueTextColor(Color.WHITE);
dataSet.setScatterShape(ScatterChart.ScatterShape.CIRCLE);
dataSet.setScatterShapeSize(7.2f);
dataSet.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
DecimalFormat df;
if (prefs.getBoolean("mmolxl", false)) {
if (prefs.getBoolean("mmolDecimals", false))
df = new DecimalFormat("0.00");
else
df = new DecimalFormat("0.0");
return df.format(value / 18.016f);
} else {
return new DecimalFormat("0").format(value);
}
} }
} });
});
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>(); ArrayList<IScatterDataSet> dataSets = new ArrayList<IScatterDataSet>();
dataSets.add(lineDataSet); dataSets.add(dataSet);
LineData lineData = new LineData(dataSets); ScatterData lineData = new ScatterData(dataSets);
mChart.setData(lineData);
} else {
((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setValues(entries);
((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setColors(colors);
//dataSet.notifyDataSetChanged();
}
// set data //TODO: make the display timespan configurable
mChart.setMinimumHeight(200);
mChart.setData(lineData);
mChart.getXAxis().setAxisMaximum(System.currentTimeMillis()); mChart.getXAxis().setAxisMaximum(System.currentTimeMillis());
mChart.getXAxis().setAxisMinimum(mChart.getXAxis().getAxisMaximum() - 24 * 60 * 60 * 1000);
mChart.postInvalidate();
} }
} }
...@@ -841,13 +899,13 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc ...@@ -841,13 +899,13 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
} }
} }
private class PumsStatusLineDataSet extends RealmLineDataSet<PumpStatusEvent> { private class PumsStatusDataSet extends RealmScatterDataSet<PumpStatusEvent> {
public PumsStatusLineDataSet(RealmResults<PumpStatusEvent> result, String yValuesField) { public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String yValuesField) {
super(result, yValuesField); super(result, yValuesField);
} }
public PumsStatusLineDataSet(RealmResults<PumpStatusEvent> result, String xValuesField, String yValuesField) { public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String xValuesField, String yValuesField) {
super(result, xValuesField, yValuesField); super(result, xValuesField, yValuesField);
} }
......
package info.nightscout.android.model.medtronicNg; package info.nightscout.android.model.medtronicNg;
import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import java.util.Date; import java.util.Date;
import io.realm.RealmObject; import io.realm.RealmObject;
...@@ -9,7 +11,7 @@ import io.realm.annotations.Index; ...@@ -9,7 +11,7 @@ import io.realm.annotations.Index;
/** /**
* Created by lgoedhart on 4/06/2016. * Created by lgoedhart on 4/06/2016.
*/ */
public class PumpStatusEvent extends RealmObject { public class PumpStatusEvent extends RealmObject {
@Index @Index
private Date eventDate; // The actual time of the event (assume the capture device eventDate/time is accurate) private Date eventDate; // The actual time of the event (assume the capture device eventDate/time is accurate)
private Date pumpDate; // The eventDate/time on the pump at the time of the event private Date pumpDate; // The eventDate/time on the pump at the time of the event
......
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
</LinearLayout> </LinearLayout>
<com.github.mikephil.charting.charts.LineChart <com.github.mikephil.charting.charts.ScatterChart
android:id="@+id/chart" android:id="@+id/chart"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment