simplify graph series
This commit is contained in:
parent
8934d2d6b9
commit
dd7e777a24
9 changed files with 282 additions and 555 deletions
|
@ -2,20 +2,24 @@ package info.nightscout.androidaps.db;
|
|||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import com.jjoe64.graphview.series.DataPointInterface;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS)
|
||||
public class BgReading implements DataPointInterface {
|
||||
public class BgReading implements DataPointWithLabelInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(BgReading.class);
|
||||
|
||||
@DatabaseField(id = true)
|
||||
|
@ -39,6 +43,8 @@ public class BgReading implements DataPointInterface {
|
|||
|
||||
public static String units = Constants.MGDL;
|
||||
|
||||
public boolean isPrediction = false; // true when drawing predictions as bg points
|
||||
|
||||
public BgReading() {}
|
||||
|
||||
public BgReading(NSSgv sgv) {
|
||||
|
@ -106,6 +112,7 @@ public class BgReading implements DataPointInterface {
|
|||
'}';
|
||||
}
|
||||
|
||||
// ------------------ DataPointWithLabelInterface ------------------
|
||||
@Override
|
||||
public double getX() {
|
||||
return date;
|
||||
|
@ -116,4 +123,51 @@ public class BgReading implements DataPointInterface {
|
|||
return valueToUnits(units);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.POINT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet);
|
||||
return isTablet ? 8 : 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
Double lowLine = SP.getDouble("low_mark", 0d);
|
||||
Double highLine = SP.getDouble("high_mark", 0d);
|
||||
if (lowLine < 1) {
|
||||
lowLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units);
|
||||
}
|
||||
if (highLine < 1) {
|
||||
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
||||
}
|
||||
String units = MainApp.getConfigBuilder().getProfile().getUnits();
|
||||
int color = MainApp.sResources.getColor(R.color.inrange);
|
||||
if (isPrediction)
|
||||
color = MainApp.sResources.getColor(R.color.prediction);
|
||||
else if (valueToUnits(units) < lowLine)
|
||||
color = MainApp.sResources.getColor(R.color.low);
|
||||
else if (valueToUnits(units) > highLine)
|
||||
color = MainApp.sResources.getColor(R.color.high);
|
||||
return color;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ package info.nightscout.androidaps.db;
|
|||
* Created by mike on 21.05.2017.
|
||||
*/
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
|
@ -20,6 +22,8 @@ import info.nightscout.androidaps.interfaces.InsulinInterface;
|
|||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
@ -29,7 +33,7 @@ import info.nightscout.utils.Round;
|
|||
*/
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_EXTENDEDBOLUSES)
|
||||
public class ExtendedBolus implements Interval {
|
||||
public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(ExtendedBolus.class);
|
||||
|
||||
@DatabaseField(id = true)
|
||||
|
@ -196,4 +200,49 @@ public class ExtendedBolus implements Interval {
|
|||
return "E " + DecimalFormatter.to2Decimal(absoluteRate()) + "U/h ("
|
||||
+ getRealDuration() + "/" + durationInMinutes + ") ";
|
||||
}
|
||||
|
||||
// -------- DataPointWithLabelInterface --------
|
||||
@Override
|
||||
public double getX() {
|
||||
return date;
|
||||
}
|
||||
|
||||
// default when no sgv around available
|
||||
private double yValue = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return yValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
yValue = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return toStringMedium();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return durationInMinutes * 60 * 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
return Color.CYAN;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
|
@ -10,6 +12,7 @@ import java.util.Date;
|
|||
|
||||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
|
||||
|
@ -118,11 +121,36 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
|||
return yValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
yValue = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return profileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
public String log() {
|
||||
return "ProfileSwitch{" +
|
||||
"date=" + date +
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
|
@ -16,6 +18,7 @@ import info.nightscout.androidaps.interfaces.InsulinInterface;
|
|||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
|
@ -103,14 +106,29 @@ public class Treatment implements DataPointWithLabelInterface {
|
|||
return label;
|
||||
}
|
||||
|
||||
public void setYValue(List<BgReading> bgReadingsArray) {
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
||||
BgReading reading = bgReadingsArray.get(r);
|
||||
if (reading.date > date) continue;
|
||||
yValue = Profile.fromMgdlToUnits(reading.value, profile.getUnits());
|
||||
break;
|
||||
}
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.BOLUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
yValue = y;
|
||||
}
|
||||
|
||||
// ----------------- DataPointInterface end --------------------
|
||||
|
|
|
@ -100,6 +100,7 @@ public class DetermineBasalResultAMA extends APSResult {
|
|||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +110,7 @@ public class DetermineBasalResultAMA extends APSResult {
|
|||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +120,7 @@ public class DetermineBasalResultAMA extends APSResult {
|
|||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ import com.jjoe64.graphview.Viewport;
|
|||
import com.jjoe64.graphview.series.BarGraphSeries;
|
||||
import com.jjoe64.graphview.series.DataPoint;
|
||||
import com.jjoe64.graphview.series.LineGraphSeries;
|
||||
import com.jjoe64.graphview.series.PointsGraphSeries;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
@ -61,7 +60,6 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
|
@ -109,11 +107,11 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
|
|||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.VerticalTextsGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.utils.BolusWizard;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
@ -189,8 +187,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledUpdate = null;
|
||||
|
||||
final Handler timeHandler = new Handler();
|
||||
|
||||
public OverviewFragment() {
|
||||
super();
|
||||
if (sHandlerThread == null) {
|
||||
|
@ -337,7 +333,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
|
||||
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
|
||||
if (activeloop == null)
|
||||
return;
|
||||
menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop));
|
||||
|
@ -620,8 +616,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
NSUpload.uploadDeviceStatus();
|
||||
ObjectivesPlugin objectivesPlugin = (ObjectivesPlugin) MainApp.getSpecificPlugin(ObjectivesPlugin.class);
|
||||
if (objectivesPlugin != null) {
|
||||
objectivesPlugin.manualEnacts++;
|
||||
objectivesPlugin.saveProgress();
|
||||
ObjectivesPlugin.manualEnacts++;
|
||||
ObjectivesPlugin.saveProgress();
|
||||
}
|
||||
}
|
||||
scheduleUpdateGUI("onClickAcceptTemp");
|
||||
|
@ -643,7 +639,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive();
|
||||
if (quickWizardEntry != null && actualBg != null) {
|
||||
quickWizardButton.setVisibility(View.VISIBLE);
|
||||
String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText();
|
||||
BolusWizard wizard = new BolusWizard();
|
||||
wizard.doCalc(profile, quickWizardEntry.carbs(), 0d, actualBg.valueToUnits(profile.getUnits()), 0d, true, true, false, false);
|
||||
|
||||
|
@ -679,7 +674,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U";
|
||||
confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g";
|
||||
|
||||
if (insulinAfterConstraints - wizard.calculatedTotalInsulin != 0 || carbsAfterConstraints != quickWizardEntry.carbs()) {
|
||||
if (!insulinAfterConstraints.equals(wizard.calculatedTotalInsulin) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror));
|
||||
builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput));
|
||||
|
@ -921,7 +916,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
apsModeView.setVisibility(View.VISIBLE);
|
||||
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled));
|
||||
apsModeView.setTextColor(Color.BLACK);
|
||||
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
|
||||
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
|
||||
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) {
|
||||
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended));
|
||||
apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend()));
|
||||
|
@ -959,7 +954,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
tempTargetView.setText(Profile.toUnitsString(tempTarget.low, Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()));
|
||||
else
|
||||
tempTargetView.setText(Profile.toUnitsString(tempTarget.low, Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + Profile.toUnitsString(tempTarget.high, Profile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits()));
|
||||
} if (Config.NSCLIENT) {
|
||||
}
|
||||
if (Config.NSCLIENT) {
|
||||
tempTargetView.setVisibility(View.GONE);
|
||||
} else {
|
||||
|
||||
|
@ -1173,7 +1169,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - new Date().getTime()) / (60 * 60 * 1000));
|
||||
predHours = Math.min(2, predHours);
|
||||
predHours = Math.max(0, predHours);
|
||||
hoursToFetch = (int) (rangeToDisplay - predHours);
|
||||
hoursToFetch = rangeToDisplay - predHours;
|
||||
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding
|
||||
fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
endTime = toTime + predHours * 60 * 60 * 1000L;
|
||||
|
@ -1189,12 +1185,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
LineGraphSeries<DataPoint> tempBasalsSeries = null;
|
||||
AreaGraphSeries<DoubleDataPoint> areaSeries;
|
||||
LineGraphSeries<DataPoint> seriesNow, seriesNow2;
|
||||
PointsGraphSeries<BgReading> seriesInRage;
|
||||
PointsGraphSeries<BgReading> seriesLow;
|
||||
PointsGraphSeries<BgReading> seriesHigh;
|
||||
PointsGraphSeries<BgReading> predSeries;
|
||||
PointsWithLabelGraphSeries<Treatment> seriesTreatments;
|
||||
VerticalTextsGraphSeries<ProfileSwitch> seriesProfileSwitch;
|
||||
|
||||
// **** TEMP BASALS graph ****
|
||||
Double maxBasalValueFound = 0d;
|
||||
|
@ -1406,9 +1396,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
|
||||
// **** BG graph ****
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
||||
List<BgReading> inRangeArray = new ArrayList<>();
|
||||
List<BgReading> lowArray = new ArrayList<>();
|
||||
List<BgReading> highArray = new ArrayList<>();
|
||||
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
|
||||
|
||||
if (bgReadingsArray.size() == 0)
|
||||
return;
|
||||
|
@ -1418,59 +1406,28 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
while (it.hasNext()) {
|
||||
BgReading bg = it.next();
|
||||
if (bg.value > maxBgValue) maxBgValue = bg.value;
|
||||
if (bg.valueToUnits(units) < lowLine)
|
||||
lowArray.add(bg);
|
||||
else if (bg.valueToUnits(units) > highLine)
|
||||
highArray.add(bg);
|
||||
else
|
||||
inRangeArray.add(bg);
|
||||
bgListArray.add(bg);
|
||||
}
|
||||
if (showPrediction) {
|
||||
DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed;
|
||||
List<BgReading> predArray = amaResult.getPredictions();
|
||||
Iterator<BgReading> itPred = predArray.iterator();
|
||||
while (itPred.hasNext()) {
|
||||
BgReading bg = it.next();
|
||||
bgListArray.add(bg);
|
||||
}
|
||||
}
|
||||
|
||||
maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units);
|
||||
maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4;
|
||||
if (highLine > maxBgValue) maxBgValue = highLine;
|
||||
Integer numOfHorizLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1);
|
||||
|
||||
BgReading[] inRange = new BgReading[inRangeArray.size()];
|
||||
BgReading[] low = new BgReading[lowArray.size()];
|
||||
BgReading[] high = new BgReading[highArray.size()];
|
||||
inRange = inRangeArray.toArray(inRange);
|
||||
low = lowArray.toArray(low);
|
||||
high = highArray.toArray(high);
|
||||
DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()];
|
||||
bg = bgListArray.toArray(bg);
|
||||
|
||||
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet);
|
||||
|
||||
if (inRange.length > 0) {
|
||||
bgGraph.addSeries(seriesInRage = new PointsGraphSeries<>(inRange));
|
||||
seriesInRage.setShape(PointsGraphSeries.Shape.POINT);
|
||||
seriesInRage.setSize(isTablet ? 8 : 5);
|
||||
seriesInRage.setColor(MainApp.sResources.getColor(R.color.inrange));
|
||||
}
|
||||
|
||||
if (low.length > 0) {
|
||||
bgGraph.addSeries(seriesLow = new PointsGraphSeries<>(low));
|
||||
seriesLow.setShape(PointsGraphSeries.Shape.POINT);
|
||||
seriesLow.setSize(isTablet ? 8 : 5);
|
||||
seriesLow.setColor(MainApp.sResources.getColor(R.color.low));
|
||||
}
|
||||
|
||||
if (high.length > 0) {
|
||||
bgGraph.addSeries(seriesHigh = new PointsGraphSeries<>(high));
|
||||
seriesHigh.setShape(PointsGraphSeries.Shape.POINT);
|
||||
seriesHigh.setSize(isTablet ? 8 : 5);
|
||||
seriesHigh.setColor(MainApp.sResources.getColor(R.color.high));
|
||||
}
|
||||
|
||||
if (showPrediction) {
|
||||
DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed;
|
||||
List<BgReading> predArray = amaResult.getPredictions();
|
||||
BgReading[] pred = new BgReading[predArray.size()];
|
||||
pred = predArray.toArray(pred);
|
||||
if (pred.length > 0) {
|
||||
bgGraph.addSeries(predSeries = new PointsGraphSeries<BgReading>(pred));
|
||||
predSeries.setShape(PointsGraphSeries.Shape.POINT);
|
||||
predSeries.setSize(4);
|
||||
predSeries.setColor(MainApp.sResources.getColor(R.color.prediction));
|
||||
}
|
||||
if (bg.length > 0) {
|
||||
bgGraph.addSeries(new PointsWithLabelGraphSeries<>(bg));
|
||||
}
|
||||
|
||||
// **** NOW line ****
|
||||
|
@ -1498,40 +1455,30 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
|
||||
|
||||
// Treatments
|
||||
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
|
||||
|
||||
List<Treatment> treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory();
|
||||
List<Treatment> filteredTreatments = new ArrayList<Treatment>();
|
||||
|
||||
for (int tx = 0; tx < treatments.size(); tx++) {
|
||||
Treatment t = treatments.get(tx);
|
||||
if (t.date < fromTime || t.date > endTime) continue;
|
||||
t.setYValue(bgReadingsArray);
|
||||
DataPointWithLabelInterface t = treatments.get(tx);
|
||||
if (t.getX() < fromTime || t.getX() > endTime) continue;
|
||||
t.setY(getNearestBg((long) t.getX(), bgReadingsArray));
|
||||
filteredTreatments.add(t);
|
||||
}
|
||||
Treatment[] treatmentsArray = new Treatment[filteredTreatments.size()];
|
||||
treatmentsArray = filteredTreatments.toArray(treatmentsArray);
|
||||
if (treatmentsArray.length > 0) {
|
||||
bgGraph.addSeries(seriesTreatments = new PointsWithLabelGraphSeries<Treatment>(treatmentsArray));
|
||||
seriesTreatments.setShape(PointsWithLabelGraphSeries.Shape.TRIANGLE);
|
||||
seriesTreatments.setSize(10);
|
||||
seriesTreatments.setColor(Color.CYAN);
|
||||
}
|
||||
|
||||
// ProfileSwitch
|
||||
List<ProfileSwitch> profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList();
|
||||
List<ProfileSwitch> filteredProfileSwitches = new ArrayList<ProfileSwitch>();
|
||||
|
||||
for (int tx = 0; tx < profileSwitches.size(); tx++) {
|
||||
ProfileSwitch t = profileSwitches.get(tx);
|
||||
if (t.date < fromTime || t.date > endTime) continue;
|
||||
filteredProfileSwitches.add(t);
|
||||
DataPointWithLabelInterface t = profileSwitches.get(tx);
|
||||
if (t.getX() < fromTime || t.getX() > endTime) continue;
|
||||
filteredTreatments.add(t);
|
||||
}
|
||||
ProfileSwitch[] profileSwitchArray = new ProfileSwitch[filteredProfileSwitches.size()];
|
||||
profileSwitchArray = filteredProfileSwitches.toArray(profileSwitchArray);
|
||||
if (profileSwitchArray.length > 0) {
|
||||
bgGraph.addSeries(seriesProfileSwitch = new VerticalTextsGraphSeries<ProfileSwitch>(profileSwitchArray));
|
||||
//seriesProfileSwitch.setShape(PointsWithLabelGraphSeries.Shape.TRIANGLE);
|
||||
seriesProfileSwitch.setSize(10);
|
||||
seriesProfileSwitch.setColor(Color.CYAN);
|
||||
|
||||
DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()];
|
||||
treatmentsArray = filteredTreatments.toArray(treatmentsArray);
|
||||
if (treatmentsArray.length > 0) {
|
||||
bgGraph.addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
|
||||
}
|
||||
|
||||
// set manual y bounds to have nice steps
|
||||
|
@ -1560,9 +1507,21 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public double getNearestBg(long date, List<BgReading> bgReadingsArray) {
|
||||
double bg = 0;
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
||||
BgReading reading = bgReadingsArray.get(r);
|
||||
if (reading.date > date) continue;
|
||||
bg = Profile.fromMgdlToUnits(reading.value, profile.getUnits());
|
||||
break;
|
||||
}
|
||||
return bg;
|
||||
}
|
||||
|
||||
|
||||
//Notifications
|
||||
public static class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.NotificationsViewHolder> {
|
||||
|
||||
|
|
|
@ -38,15 +38,21 @@ public interface DataPointWithLabelInterface extends DataPointInterface{
|
|||
/**
|
||||
* @return the x value
|
||||
*/
|
||||
public double getX();
|
||||
double getX();
|
||||
|
||||
/**
|
||||
* @return the y value
|
||||
*/
|
||||
public double getY();
|
||||
double getY();
|
||||
void setY(double y);
|
||||
|
||||
/**
|
||||
* @return the label value
|
||||
*/
|
||||
public String getLabel();
|
||||
String getLabel();
|
||||
|
||||
long getDuration();
|
||||
PointsWithLabelGraphSeries.Shape getShape();
|
||||
float getSize();
|
||||
int getColor();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.jjoe64.graphview.series.BaseSeries;
|
||||
|
@ -42,26 +44,6 @@ import java.util.Iterator;
|
|||
* @author jjoe64
|
||||
*/
|
||||
public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> extends BaseSeries<E> {
|
||||
/**
|
||||
* interface to implement a custom
|
||||
* drawing for the data points.
|
||||
*/
|
||||
public static interface CustomShape {
|
||||
/**
|
||||
* called when drawing a single data point.
|
||||
* use the x and y coordinates to render your
|
||||
* drawing at this point.
|
||||
*
|
||||
* @param canvas canvas to draw on
|
||||
* @param paint internal paint object. this has the correct color.
|
||||
* But you can use your own paint.
|
||||
* @param x x-coordinate the point has to be drawn to
|
||||
* @param y y-coordinate the point has to be drawn to
|
||||
* @param dataPoint the related data point
|
||||
*/
|
||||
void draw(Canvas canvas, Paint paint, float x, float y, DataPointWithLabelInterface dataPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* choose a predefined shape to render for
|
||||
* each data point.
|
||||
|
@ -77,45 +59,17 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
* draws a triangle
|
||||
*/
|
||||
TRIANGLE,
|
||||
|
||||
/**
|
||||
* draws a rectangle
|
||||
*/
|
||||
RECTANGLE
|
||||
RECTANGLE,
|
||||
BOLUS,
|
||||
EXTENDEDBOLUS,
|
||||
PROFILE
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapped styles for this series
|
||||
*/
|
||||
private final class Styles {
|
||||
/**
|
||||
* this is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*/
|
||||
float size;
|
||||
|
||||
/**
|
||||
* the shape that will be drawn for each point.
|
||||
*/
|
||||
Shape shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapped styles
|
||||
*/
|
||||
private Styles mStyles;
|
||||
|
||||
/**
|
||||
* internal paint object
|
||||
*/
|
||||
private Paint mPaint;
|
||||
|
||||
/**
|
||||
* handler to use a custom drawing
|
||||
*/
|
||||
private CustomShape mCustomShape;
|
||||
|
||||
/**
|
||||
* creates the series without data
|
||||
*/
|
||||
|
@ -138,11 +92,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
* set the defaults
|
||||
*/
|
||||
protected void init() {
|
||||
mStyles = new Styles();
|
||||
mStyles.size = 20f;
|
||||
mPaint = new Paint();
|
||||
mPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
setShape(Shape.POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,7 +128,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
double lastEndX = 0;
|
||||
|
||||
// draw data
|
||||
mPaint.setColor(getColor());
|
||||
|
||||
double diffY = maxY - minY;
|
||||
double diffX = maxX - minX;
|
||||
|
@ -194,6 +144,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
while (values.hasNext()) {
|
||||
E value = values.next();
|
||||
|
||||
mPaint.setColor(value.getColor());
|
||||
|
||||
double valY = value.getY() - minY;
|
||||
double ratY = valY / diffY;
|
||||
double y = graphHeight * ratY;
|
||||
|
@ -227,30 +179,57 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
|
||||
// draw data point
|
||||
if (!overdraw) {
|
||||
if (mCustomShape != null) {
|
||||
mCustomShape.draw(canvas, mPaint, endX, endY, value);
|
||||
} else if (mStyles.shape == Shape.POINT) {
|
||||
canvas.drawCircle(endX, endY, mStyles.size, mPaint);
|
||||
} else if (mStyles.shape == Shape.RECTANGLE) {
|
||||
canvas.drawRect(endX-mStyles.size, endY-mStyles.size, endX+mStyles.size, endY+mStyles.size, mPaint);
|
||||
} else if (mStyles.shape == Shape.TRIANGLE) {
|
||||
if (value.getShape() == Shape.POINT) {
|
||||
canvas.drawCircle(endX, endY, value.getSize(), mPaint);
|
||||
} else if (value.getShape() == Shape.RECTANGLE) {
|
||||
canvas.drawRect(endX-value.getSize(), endY-value.getSize(), endX+value.getSize(), endY+value.getSize(), mPaint);
|
||||
} else if (value.getShape() == Shape.TRIANGLE) {
|
||||
Point[] points = new Point[3];
|
||||
points[0] = new Point((int)endX, (int)(endY-getSize()));
|
||||
points[1] = new Point((int)(endX+getSize()), (int)(endY+getSize()*0.67));
|
||||
points[2] = new Point((int)(endX-getSize()), (int)(endY+getSize()*0.67));
|
||||
points[0] = new Point((int)endX, (int)(endY-value.getSize()));
|
||||
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
drawArrows(points, canvas, mPaint);
|
||||
} else if (value.getShape() == Shape.BOLUS) {
|
||||
Point[] points = new Point[3];
|
||||
points[0] = new Point((int)endX, (int)(endY-value.getSize()));
|
||||
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
drawArrows(points, canvas, mPaint);
|
||||
if (value.getLabel() != null) {
|
||||
float px = endX;
|
||||
float py = endY - (int) (value.getSize());
|
||||
canvas.save();
|
||||
canvas.rotate(-45, px, py);
|
||||
mPaint.setTextSize((int) (value.getSize() * 2.5));
|
||||
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
|
||||
mPaint.setFakeBoldText(true);
|
||||
canvas.drawText(value.getLabel(), px + value.getSize(), py, mPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
} else if (value.getShape() == Shape.EXTENDEDBOLUS) {
|
||||
Point[] points = new Point[3];
|
||||
points[0] = new Point((int)endX, (int)(endY-value.getSize()));
|
||||
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||
drawArrows(points, canvas, mPaint);
|
||||
} else if (value.getShape() == Shape.PROFILE) {
|
||||
if (value.getLabel() != null) {
|
||||
mPaint.setTextSize((int) (value.getSize() * 3));
|
||||
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||
Rect bounds = new Rect();
|
||||
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
float px = endX + bounds.height() / 2;
|
||||
float py = (float) (graphHeight * ratY + bounds.width() + 10);
|
||||
canvas.save();
|
||||
canvas.rotate(-90, px, py);
|
||||
canvas.drawText(value.getLabel(), px, py, mPaint);
|
||||
canvas.drawRect(px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
// set values above point
|
||||
if (value.getLabel() != null) {
|
||||
float px = endX;
|
||||
float py = endY - (int) (getSize());
|
||||
canvas.save();
|
||||
canvas.rotate(-45, px, py);
|
||||
mPaint.setTextSize((int) (getSize() * 2.5));
|
||||
mPaint.setFakeBoldText(true);
|
||||
canvas.drawText(value.getLabel(), px + getSize(), py, mPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
@ -276,57 +255,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
points[6] = point[0].x;
|
||||
points[7] = point[0].y;
|
||||
|
||||
canvas.save();
|
||||
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
|
||||
Path path = new Path();
|
||||
path.moveTo(point[0].x , point[0].y);
|
||||
path.lineTo(point[1].x,point[1].y);
|
||||
path.lineTo(point[2].x,point[2].y);
|
||||
canvas.drawPath(path,paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*
|
||||
* @return the size of the shape
|
||||
*/
|
||||
public float getSize() {
|
||||
return mStyles.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*
|
||||
* @param radius the size of the shape
|
||||
*/
|
||||
public void setSize(float radius) {
|
||||
mStyles.size = radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the shape that will be drawn for each point
|
||||
*/
|
||||
public Shape getShape() {
|
||||
return mStyles.shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the shape that will be drawn for each point
|
||||
*/
|
||||
public void setShape(Shape s) {
|
||||
mStyles.shape = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a custom handler to render your own
|
||||
* drawing for each data point.
|
||||
*
|
||||
* @param shape handler to use a custom drawing
|
||||
*/
|
||||
public void setCustomShape(CustomShape shape) {
|
||||
mCustomShape = shape;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,326 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.Overview.graphExtensions;
|
||||
|
||||
/**
|
||||
* GraphView
|
||||
* Copyright (C) 2014 Jonas Gehring
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License,
|
||||
* with the "Linking Exception", which can be found at the license.txt
|
||||
* file in this program.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* with the "Linking Exception" along with this program; if not,
|
||||
* write to the author Jonas Gehring <g.jjoe64@gmail.com>.
|
||||
* <p>
|
||||
* Added by mike
|
||||
*/
|
||||
|
||||
/**
|
||||
* Added by mike
|
||||
*/
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.jjoe64.graphview.series.BaseSeries;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Series that plots the data as points.
|
||||
* The points can be different shapes or a
|
||||
* complete custom drawing.
|
||||
*
|
||||
* @author jjoe64
|
||||
*/
|
||||
public class VerticalTextsGraphSeries<E extends DataPointWithLabelInterface> extends BaseSeries<E> {
|
||||
/**
|
||||
* interface to implement a custom
|
||||
* drawing for the data points.
|
||||
*/
|
||||
public static interface CustomShape {
|
||||
/**
|
||||
* called when drawing a single data point.
|
||||
* use the x and y coordinates to render your
|
||||
* drawing at this point.
|
||||
*
|
||||
* @param canvas canvas to draw on
|
||||
* @param paint internal paint object. this has the correct color.
|
||||
* But you can use your own paint.
|
||||
* @param x x-coordinate the point has to be drawn to
|
||||
* @param y y-coordinate the point has to be drawn to
|
||||
* @param dataPoint the related data point
|
||||
*/
|
||||
void draw(Canvas canvas, Paint paint, float x, float y, DataPointWithLabelInterface dataPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* choose a predefined shape to render for
|
||||
* each data point.
|
||||
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
||||
*/
|
||||
public enum Shape {
|
||||
/**
|
||||
* draws a point / circle
|
||||
*/
|
||||
POINT,
|
||||
|
||||
/**
|
||||
* draws a triangle
|
||||
*/
|
||||
TRIANGLE,
|
||||
|
||||
/**
|
||||
* draws a rectangle
|
||||
*/
|
||||
RECTANGLE
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapped styles for this series
|
||||
*/
|
||||
private final class Styles {
|
||||
/**
|
||||
* this is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*/
|
||||
float size;
|
||||
|
||||
/**
|
||||
* the shape that will be drawn for each point.
|
||||
*/
|
||||
Shape shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapped styles
|
||||
*/
|
||||
private Styles mStyles;
|
||||
|
||||
/**
|
||||
* internal paint object
|
||||
*/
|
||||
private Paint mPaint;
|
||||
|
||||
/**
|
||||
* handler to use a custom drawing
|
||||
*/
|
||||
private CustomShape mCustomShape;
|
||||
|
||||
/**
|
||||
* creates the series without data
|
||||
*/
|
||||
public VerticalTextsGraphSeries() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the series with data
|
||||
*
|
||||
* @param data datapoints
|
||||
*/
|
||||
public VerticalTextsGraphSeries(E[] data) {
|
||||
super(data);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* inits the internal objects
|
||||
* set the defaults
|
||||
*/
|
||||
protected void init() {
|
||||
mStyles = new Styles();
|
||||
mStyles.size = 20f;
|
||||
mPaint = new Paint();
|
||||
mPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
setShape(Shape.POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* plot the data to the viewport
|
||||
*
|
||||
* @param graphView graphview
|
||||
* @param canvas canvas to draw on
|
||||
* @param isSecondScale whether it is the second scale
|
||||
*/
|
||||
@Override
|
||||
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
|
||||
resetDataPoints();
|
||||
|
||||
// get data
|
||||
double maxX = graphView.getViewport().getMaxX(false);
|
||||
double minX = graphView.getViewport().getMinX(false);
|
||||
|
||||
double maxY;
|
||||
double minY;
|
||||
if (isSecondScale) {
|
||||
maxY = graphView.getSecondScale().getMaxY();
|
||||
minY = graphView.getSecondScale().getMinY();
|
||||
} else {
|
||||
maxY = graphView.getViewport().getMaxY(false);
|
||||
minY = graphView.getViewport().getMinY(false);
|
||||
}
|
||||
|
||||
Iterator<E> values = getValues(minX, maxX);
|
||||
|
||||
// draw background
|
||||
double lastEndY = 0;
|
||||
double lastEndX = 0;
|
||||
|
||||
// draw data
|
||||
mPaint.setColor(getColor());
|
||||
|
||||
double diffY = maxY - minY;
|
||||
double diffX = maxX - minX;
|
||||
|
||||
float graphHeight = graphView.getGraphContentHeight();
|
||||
float graphWidth = graphView.getGraphContentWidth();
|
||||
float graphLeft = graphView.getGraphContentLeft();
|
||||
float graphTop = graphView.getGraphContentTop();
|
||||
|
||||
lastEndY = 0;
|
||||
lastEndX = 0;
|
||||
float firstX = 0;
|
||||
int i = 0;
|
||||
while (values.hasNext()) {
|
||||
E value = values.next();
|
||||
|
||||
double valY = value.getY() - minY;
|
||||
double ratY = valY / diffY;
|
||||
double y = graphHeight * ratY;
|
||||
|
||||
double valX = value.getX() - minX;
|
||||
double ratX = valX / diffX;
|
||||
double x = graphWidth * ratX;
|
||||
|
||||
double orgX = x;
|
||||
double orgY = y;
|
||||
|
||||
// overdraw
|
||||
boolean overdraw = false;
|
||||
if (x > graphWidth) { // end right
|
||||
overdraw = true;
|
||||
}
|
||||
if (y < 0) { // end bottom
|
||||
overdraw = true;
|
||||
}
|
||||
if (y > graphHeight) { // end top
|
||||
overdraw = true;
|
||||
}
|
||||
/* Fix a bug that continue to show the DOT after Y axis */
|
||||
if (x < 0) {
|
||||
overdraw = true;
|
||||
}
|
||||
|
||||
float endX = (float) x + (graphLeft + 1);
|
||||
float endY = (float) (graphTop - y) + graphHeight;
|
||||
registerDataPoint(endX, endY, value);
|
||||
|
||||
// draw data point
|
||||
if (!overdraw) {
|
||||
if (value.getLabel() != null) {
|
||||
mPaint.setTextSize((int) (getSize() * 3));
|
||||
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
|
||||
Rect bounds = new Rect();
|
||||
mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
float px = endX + bounds.height() / 2;
|
||||
float py = (float) (graphHeight * ratY + bounds.width() + 10);
|
||||
canvas.save();
|
||||
canvas.rotate(-90, px, py);
|
||||
canvas.drawText(value.getLabel(), px, py, mPaint);
|
||||
canvas.drawRect(px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to render triangle
|
||||
*
|
||||
* @param point array with 3 coordinates
|
||||
* @param canvas canvas to draw on
|
||||
* @param paint paint object
|
||||
*/
|
||||
private void drawArrows(Point[] point, Canvas canvas, Paint paint) {
|
||||
float[] points = new float[8];
|
||||
points[0] = point[0].x;
|
||||
points[1] = point[0].y;
|
||||
points[2] = point[1].x;
|
||||
points[3] = point[1].y;
|
||||
points[4] = point[2].x;
|
||||
points[5] = point[2].y;
|
||||
points[6] = point[0].x;
|
||||
points[7] = point[0].y;
|
||||
|
||||
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
|
||||
Path path = new Path();
|
||||
path.moveTo(point[0].x, point[0].y);
|
||||
path.lineTo(point[1].x, point[1].y);
|
||||
path.lineTo(point[2].x, point[2].y);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*
|
||||
* @return the size of the shape
|
||||
*/
|
||||
public float getSize() {
|
||||
return mStyles.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for the size of the shape that
|
||||
* will be drawn.
|
||||
* This is useless if you are using a custom shape.
|
||||
*
|
||||
* @param radius the size of the shape
|
||||
*/
|
||||
public void setSize(float radius) {
|
||||
mStyles.size = radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the shape that will be drawn for each point
|
||||
*/
|
||||
public Shape getShape() {
|
||||
return mStyles.shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s the shape that will be drawn for each point
|
||||
*/
|
||||
public void setShape(Shape s) {
|
||||
mStyles.shape = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a custom handler to render your own
|
||||
* drawing for each data point.
|
||||
*
|
||||
* @param shape handler to use a custom drawing
|
||||
*/
|
||||
public void setCustomShape(CustomShape shape) {
|
||||
mCustomShape = shape;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue