Implement temp target dialog for automation action

This commit is contained in:
Nico Schmitz 2019-03-20 00:39:00 +01:00
parent 91e4b01f10
commit c074ec36c4
11 changed files with 359 additions and 12 deletions

View file

@ -27,6 +27,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.general.automation.actions.Action; import info.nightscout.androidaps.plugins.general.automation.actions.Action;
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog; import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog;
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditActionDialog;
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog; import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog;
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger; import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
@ -134,7 +135,10 @@ public class AutomationFragment extends SubscriberFragment {
public void onBindViewHolder(@NonNull ViewHolder holder, int position) { public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final Action action = mActionList.get(position); final Action action = mActionList.get(position);
holder.actionTitle.setText(action.friendlyName()); holder.actionTitle.setText(action.friendlyName());
holder.itemRoot.setOnClickListener(v -> action.openConfigurationDialog(mFragmentManager)); holder.itemRoot.setOnClickListener(v -> {
EditActionDialog dialog = EditActionDialog.newInstance(action);
dialog.show(mFragmentManager, "EditActionDialog");
});
} }
@Override @Override

View file

@ -1,6 +1,9 @@
package info.nightscout.androidaps.plugins.general.automation.actions; package info.nightscout.androidaps.plugins.general.automation.actions;
import android.content.Context;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.view.View;
import android.widget.LinearLayout;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -13,7 +16,9 @@ public abstract class Action {
abstract void doAction(Callback callback); abstract void doAction(Callback callback);
public void openConfigurationDialog(FragmentManager manager) { } public void generateDialog(LinearLayout root) { }
public void saveFromDialog() { }
public String toJSON() { public String toJSON() {
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();

View file

@ -1,23 +1,38 @@
package info.nightscout.androidaps.plugins.general.automation.actions; package info.nightscout.androidaps.plugins.general.automation.actions;
import android.support.v4.app.FragmentManager; import android.support.annotation.StringRes;
import android.widget.LinearLayout;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
import info.nightscout.androidaps.plugins.general.automation.elements.Label;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
public class ActionStartTempTarget extends Action { public class ActionStartTempTarget extends Action {
private double value;
private int durationInMinutes;
private String reason; private String reason;
private String units = Constants.MGDL; private double valueInMgdl;
private String units;
private int durationInMinutes;
private InputBg inputBg;
private InputDuration inputDuration;
public ActionStartTempTarget() {
units = Constants.MGDL;
}
public ActionStartTempTarget(String units) {
this.units = Constants.MGDL;
}
@Override @Override
public int friendlyName() { public int friendlyName() {
@ -26,15 +41,29 @@ public class ActionStartTempTarget extends Action {
@Override @Override
void doAction(Callback callback) { void doAction(Callback callback) {
double converted = Profile.toMgdl(value, units); TempTarget tempTarget = new TempTarget().date(DateUtil.now()).duration(durationInMinutes).reason(reason).source(Source.USER).low(valueInMgdl).high(valueInMgdl);
TempTarget tempTarget = new TempTarget().date(DateUtil.now()).duration(durationInMinutes).reason(reason).source(Source.USER).low(converted).high(converted);
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
if (callback != null) if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run(); callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
} }
@Override @Override
public void openConfigurationDialog(FragmentManager manager) { public void generateDialog(LinearLayout root) {
inputBg = new InputBg(units);
if (valueInMgdl != 0d) inputBg.setMgdl(valueInMgdl);
inputDuration = new InputDuration(durationInMinutes, InputDuration.TimeUnit.MINUTES);
int unitResId = units.equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol;
Label labelBg = new Label(MainApp.gs(R.string.careportal_newnstreatment_percentage_label), MainApp.gs(unitResId), inputBg);
labelBg.generateDialog(root);
Label labelDuration = new Label(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "min", inputDuration);
labelDuration.generateDialog(root);
}
@Override
public void saveFromDialog() {
valueInMgdl = inputBg.getMgdl();
durationInMinutes = inputDuration.getMinutes();
} }
} }

View file

@ -0,0 +1,66 @@
package info.nightscout.androidaps.plugins.general.automation.dialogs;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
public class EditActionDialog extends DialogFragment {
private Unbinder mUnbinder;
private Action mAction;
@BindView(R.id.layout_root)
LinearLayout mRootLayout;
@BindView(R.id.viewActionTitle)
TextView mViewActionTitle;
public static EditActionDialog newInstance(Action action) {
Bundle args = new Bundle();
EditActionDialog fragment = new EditActionDialog();
fragment.setArguments(args);
fragment.mAction = action;
return fragment;
}
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.automation_dialog_action, container, false);
mUnbinder = ButterKnife.bind(this, view);
mViewActionTitle.setText(mAction.friendlyName());
mRootLayout.removeAllViews();
mAction.generateDialog(mRootLayout);
return view;
}
@Override
public void onDestroyView() {
mUnbinder.unbind();
super.onDestroyView();
}
@OnClick(R.id.ok)
public void onButtonOk(View view) {
mAction.saveFromDialog();
dismiss();
}
@OnClick(R.id.cancel)
public void onButtonCancel(View view) {
dismiss();
}
}

View file

@ -22,7 +22,6 @@ import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
public class EditEventDialog extends DialogFragment { public class EditEventDialog extends DialogFragment {
private static AutomationEvent mEvent; private static AutomationEvent mEvent;
@BindView(R.id.inputEventTitle) @BindView(R.id.inputEventTitle)

View file

@ -0,0 +1,9 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
public class Element {
public void generateDialog(LinearLayout root) { }
}

View file

@ -0,0 +1,81 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.LinearLayout;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.utils.NumberPicker;
public class InputBg extends Element {
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
// TODO: validate inputs
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private String units;
private double value;
private final double minValue, maxValue, step;
private final DecimalFormat decimalFormat;
public InputBg(String units) {
this.units = units;
// set default initial value
if (units.equals(Constants.MMOL)) {
// mmol
value = 5.5;
minValue = 2;
maxValue = 30;
step = 0.1;
decimalFormat = new DecimalFormat("0.0");
} else {
// mg/dL
value = 100;
minValue = 36;
maxValue = 540;
step = 1;
decimalFormat = new DecimalFormat("0");
}
}
@Override
public void generateDialog(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(0d, minValue, maxValue, step, decimalFormat, false, textWatcher);
numberPicker.setValue(value);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
public String getUnits() {
return units;
}
public double getValue() {
return value;
}
public double getMgdl() {
return Profile.toMgdl(value, units);
}
public void setMgdl(double value) {
this.value = Profile.fromMgdlToUnits(value, units);
}
}

View file

@ -0,0 +1,56 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import java.text.DecimalFormat;
import info.nightscout.utils.NumberPicker;
public class InputDuration extends Element {
public enum TimeUnit {
MINUTES,
HOURS
}
private TimeUnit unit;
private double value;
public InputDuration(double value, TimeUnit unit) {
this.unit = unit;
this.value = value;
}
@Override
public void generateDialog(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
if (unit.equals(TimeUnit.MINUTES)) {
// Minutes
numberPicker.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false);
} else {
// Hours
numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false);
}
numberPicker.setValue(value);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
public TimeUnit getUnit() {
return unit;
}
public double getValue() {
return value;
}
public int getMinutes() {
if (unit.equals(TimeUnit.MINUTES)) {
return (int)value;
} else {
return (int)(value * 60d);
}
}
}

View file

@ -0,0 +1,59 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.graphics.Typeface;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import info.nightscout.androidaps.MainApp;
public class Label extends Element {
private final Element element;
private final String textPre;
private final String textPost;
public Label(String textPre, String textPost, Element element) {
this.element = element;
this.textPre = textPre;
this.textPost = textPost;
}
@Override
public void generateDialog(LinearLayout root) {
// container layout
LinearLayout layout = new LinearLayout(root.getContext());
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
// text view pre element
int px = MainApp.dpToPx(10);
TextView textViewPre = new TextView(root.getContext());
textViewPre.setText(textPre);
textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
textViewPre.setWidth(MainApp.dpToPx(120));
textViewPre.setPadding(px, px, px, px);
textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD);
layout.addView(textViewPre);
// add element to layout
element.generateDialog(layout);
// text view post element
if (textPost != null) {
px = MainApp.dpToPx(5);
TextView textViewPost = new TextView(root.getContext());
textViewPost.setText(textPost);
textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
textViewPost.setWidth(MainApp.dpToPx(45));
textViewPost.setPadding(px, px, px, px);
textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD);
layout.addView(textViewPost);
}
// add layout to root layout
root.addView(layout);
}
}

View file

@ -177,7 +177,7 @@ public class TriggerBg extends Trigger {
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(layout); root.addView(layout);
// input filed for threshold // input field for threshold
NumberPicker numberPicker = new NumberPicker(context, null); NumberPicker numberPicker = new NumberPicker(context, null);
numberPicker.setParams(0d, 0d, (double) 500, 1d, new DecimalFormat("0"), false, textWatcher); numberPicker.setParams(0d, 0d, (double) 500, 1d, new DecimalFormat("0"), false, textWatcher);
numberPicker.setValue(threshold); numberPicker.setValue(threshold);

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="300dp"
android:padding="10dp">
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/viewActionTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingBottom="10dp"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="10dp"
android:id="@+id/layout_root" />
<include layout="@layout/mdtp_done_button" />
</LinearLayout>
</ScrollView>
</LinearLayout>