Clean up code. Improve ux.

This commit is contained in:
Nico Schmitz 2018-10-25 21:12:26 +02:00
parent 80e3b57b8c
commit 7698923fe8
6 changed files with 163 additions and 106 deletions

View file

@ -12,11 +12,11 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import butterknife.BindView; import butterknife.BindView;
@ -25,6 +25,7 @@ import butterknife.OnClick;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; 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.dialogs.ChooseTriggerDialog;
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;
@ -126,20 +127,12 @@ public class AutomationFragment extends SubscriberFragment {
public static class TriggerListAdapter { public static class TriggerListAdapter {
private final LinearLayout mRootLayout; private final LinearLayout mRootLayout;
private final Context mContext; private final Context mContext;
private final List<Trigger> mTriggerList; private final TriggerConnector mRootConnector;
public TriggerListAdapter(Context context, LinearLayout rootLayout, List<Trigger> triggers) { public TriggerListAdapter(Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
mRootLayout = rootLayout; mRootLayout = rootLayout;
mContext = context; mContext = context;
mTriggerList = triggers; mRootConnector = rootTrigger;
build();
}
public TriggerListAdapter(Context context, LinearLayout rootLayout, Trigger trigger) {
mRootLayout = rootLayout;
mContext = context;
mTriggerList = new ArrayList<>();
mTriggerList.add(trigger);
build(); build();
} }
@ -148,6 +141,38 @@ public class AutomationFragment extends SubscriberFragment {
mRootLayout.removeAllViews(); mRootLayout.removeAllViews();
} }
private void build() {
for(int i = 0; i < mRootConnector.size(); ++i) {
final Trigger trigger = mRootConnector.get(i);
// spinner
if (i > 0) {
createSpinner(trigger);
}
// trigger layout
mRootLayout.addView(trigger.createView(mContext));
// buttons
createButtons(trigger);
}
if (mRootConnector.size() == 0) {
Button buttonAdd = new Button(mContext);
buttonAdd.setText("Add New");
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = ChooseTriggerDialog.newInstance();
FragmentManager manager = AutomationFragment.fragmentManager();
dialog.show(manager, "ChooseTriggerDialog");
dialog.setOnClickListener(newTriggerObject -> {
mRootConnector.add(newTriggerObject);
rebuild();
});
});
mRootLayout.addView(buttonAdd);
}
}
private Spinner createSpinner() { private Spinner createSpinner() {
Spinner spinner = new Spinner(mContext); Spinner spinner = new Spinner(mContext);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels()); ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels());
@ -156,42 +181,79 @@ public class AutomationFragment extends SubscriberFragment {
return spinner; return spinner;
} }
private void build() { private void createSpinner(Trigger trigger) {
boolean isFirstItem = true; final TriggerConnector connector = trigger.getConnector();
for(Trigger trigger : mTriggerList) { final int initialPosition = connector.getConnectorType().ordinal();
if (!isFirstItem) { Spinner spinner = createSpinner();
final TriggerConnector connector = trigger.getConnector(); spinner.setSelection(initialPosition);
final int initialPosition = connector.getConnectorType().ordinal(); spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
Spinner spinner = createSpinner(); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
spinner.setSelection(initialPosition); LinearLayout.LayoutParams.MATCH_PARENT,
spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay)); LinearLayout.LayoutParams.WRAP_CONTENT
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( );
LinearLayout.LayoutParams.MATCH_PARENT, params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
LinearLayout.LayoutParams.WRAP_CONTENT spinner.setLayoutParams(params);
); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8)); @Override
spinner.setLayoutParams(params); public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { if (position != initialPosition) {
@Override // conector type changed
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { changeConnector(trigger, connector, TriggerConnector.Type.values()[position]);
if (position != initialPosition) { }
// conector type changed
changeConnector(trigger, connector, TriggerConnector.Type.values()[position]);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mRootLayout.addView(spinner);
} else {
isFirstItem = false;
} }
mRootLayout.addView(trigger.createView(mContext)); @Override
public void onNothingSelected(AdapterView<?> parent) { }
});
mRootLayout.addView(spinner);
}
private void createButtons(Trigger trigger) {
// do not create buttons for TriggerConnector
if (trigger instanceof TriggerConnector) {
return;
} }
// Button Layout
LinearLayout buttonLayout = new LinearLayout(mContext);
buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mRootLayout.addView(buttonLayout);
// Button [-]
Button buttonRemove = new Button(mContext);
buttonRemove.setText("del");
buttonRemove.setOnClickListener(v -> {
final TriggerConnector connector = trigger.getConnector();
connector.remove(trigger);
connector.simplify().rebuildView();
});
buttonLayout.addView(buttonRemove);
// Button [+]
Button buttonAdd = new Button(mContext);
buttonAdd.setText("add");
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = ChooseTriggerDialog.newInstance();
FragmentManager manager = AutomationFragment.fragmentManager();
dialog.show(manager, "ChooseTriggerDialog");
dialog.setOnClickListener(newTriggerObject -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger)+1, newTriggerObject);
connector.simplify().rebuildView();
});
});
buttonLayout.addView(buttonAdd);
// Button [*]
Button buttonCopy = new Button(mContext);
buttonCopy.setText("copy");
buttonCopy.setOnClickListener(v -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger)+1, trigger.duplicate());
connector.simplify().rebuildView();
});
buttonLayout.addView(buttonCopy);
} }
public static void changeConnector(final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) { public static void changeConnector(final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {

View file

@ -17,9 +17,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent; import info.nightscout.androidaps.plugins.general.automation.AutomationEvent;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment; import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime;
public class EditEventDialog extends DialogFragment { public class EditEventDialog extends DialogFragment {
@ -49,14 +47,12 @@ public class EditEventDialog extends DialogFragment {
View view = inflater.inflate(R.layout.automation_dialog_event, container, false); View view = inflater.inflate(R.layout.automation_dialog_event, container, false);
mUnbinder = ButterKnife.bind(this, view); mUnbinder = ButterKnife.bind(this, view);
// dummy initialization // initialization
TriggerConnector to = new TriggerConnector(TriggerConnector.Type.OR); TriggerConnector rootTrigger = new TriggerConnector(TriggerConnector.Type.OR);
to.add(new TriggerBg()); mEvent.setTrigger(rootTrigger);
to.add(new TriggerTime());
mEvent.setTrigger(to);
// display triggers // display root trigger
mTriggerListAdapter = new AutomationFragment.TriggerListAdapter(getContext(), mLayoutTrigger, mEvent.getTrigger()); mLayoutTrigger.addView(rootTrigger.createView(getContext()));
return view; return view;
} }

View file

@ -97,6 +97,8 @@ public abstract class Trigger {
void notifyAboutRun(long time) { void notifyAboutRun(long time) {
} }
public abstract Trigger duplicate();
static Trigger instantiate(JSONObject object) { static Trigger instantiate(JSONObject object) {
try { try {
String type = object.getString("type"); String type = object.getString("type");

View file

@ -45,6 +45,17 @@ public class TriggerBg extends Trigger {
} }
}; };
public TriggerBg() {
super();
}
private TriggerBg(TriggerBg triggerBg) {
super();
comparator = triggerBg.comparator;
units = triggerBg.units;
threshold = triggerBg.threshold;
}
@Override @Override
public synchronized boolean shouldRun() { public synchronized boolean shouldRun() {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
@ -99,6 +110,11 @@ public class TriggerBg extends Trigger {
return MainApp.gs(R.string.glucosecompared, comparator.getStringRes(), threshold, units); return MainApp.gs(R.string.glucosecompared, comparator.getStringRes(), threshold, units);
} }
@Override
public Trigger duplicate() {
return new TriggerBg(this);
}
TriggerBg threshold(double threshold) { TriggerBg threshold(double threshold) {
this.threshold = threshold; this.threshold = threshold;
return this; return this;

View file

@ -2,10 +2,8 @@ package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.content.Context; import android.content.Context;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.json.JSONArray; import org.json.JSONArray;
@ -18,7 +16,6 @@ import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment; import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog;
import info.nightscout.utils.JsonHelper; import info.nightscout.utils.JsonHelper;
public class TriggerConnector extends Trigger { public class TriggerConnector extends Trigger {
@ -172,6 +169,11 @@ public class TriggerConnector extends Trigger {
return result.toString(); return result.toString();
} }
@Override
public Trigger duplicate() {
return null;
}
private AutomationFragment.TriggerListAdapter adapter; private AutomationFragment.TriggerListAdapter adapter;
public void rebuildView() { public void rebuildView() {
@ -194,53 +196,11 @@ public class TriggerConnector extends Trigger {
triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(triggerListLayout); root.addView(triggerListLayout);
adapter = new AutomationFragment.TriggerListAdapter(context, triggerListLayout, list); adapter = new AutomationFragment.TriggerListAdapter(context, triggerListLayout, this);
LinearLayout buttonLayout = new LinearLayout(context);
buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(buttonLayout);
Button buttonRemove = new Button(context);
buttonRemove.setText("-");
buttonRemove.setOnClickListener(v -> {
if (connector != null) {
connector.remove(TriggerConnector.this);
connector.simplify();
connector.adapter.rebuild();
} else {
// no parent
list.clear();
simplify();
adapter.rebuild();
}
});
buttonLayout.addView(buttonRemove);
Button buttonAdd = new Button(context);
buttonAdd.setText("+");
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = ChooseTriggerDialog.newInstance();
FragmentManager manager = AutomationFragment.fragmentManager();
dialog.show(manager, "ChooseTriggerDialog");
dialog.setOnClickListener(newTriggerObject -> addNewTrigger(adapter, newTriggerObject, getConnectorType()));
});
buttonLayout.addView(buttonAdd);
return root; return root;
} }
private void addNewTrigger(AutomationFragment.TriggerListAdapter adapter, Trigger trigger, Type connection) {
if (getConnectorType().equals(connection)) {
add(trigger);
} else {
TriggerConnector t = new TriggerConnector(connection);
t.add(trigger);
add(t);
}
adapter.rebuild();
}
public TriggerConnector simplify() { public TriggerConnector simplify() {
// simplify children // simplify children
for(int i = 0; i < size(); ++i) { for(int i = 0; i < size(); ++i) {

View file

@ -85,22 +85,37 @@ public class TriggerTime extends Trigger {
private final boolean[] weekdays = new boolean[DayOfWeek.values().length]; private final boolean[] weekdays = new boolean[DayOfWeek.values().length];
long lastRun; private long lastRun;
// Single execution // Single execution
long runAt; private long runAt;
// Recurring // Recurring
boolean recurring; private boolean recurring;
int hour; private int hour;
int minute; private int minute;
long validTo; private long validTo;
public TriggerTime() { public TriggerTime() {
super();
setAll(false); setAll(false);
} }
private TriggerTime(TriggerTime triggerTime) {
super();
lastRun = triggerTime.lastRun;
runAt = triggerTime.runAt;
recurring = triggerTime.recurring;
hour = triggerTime.hour;
minute = triggerTime.minute;
validTo = triggerTime.validTo;
for(int i = 0; i < weekdays.length; ++i) {
weekdays[i] = triggerTime.weekdays[i];
}
}
public void setAll(boolean value) { public void setAll(boolean value) {
for(DayOfWeek day : DayOfWeek.values()) { for(DayOfWeek day : DayOfWeek.values()) {
set(day, value); set(day, value);
@ -207,6 +222,11 @@ public class TriggerTime extends Trigger {
lastRun = time; lastRun = time;
} }
@Override
public Trigger duplicate() {
return new TriggerTime(this);
}
TriggerTime lastRun(long lastRun) { TriggerTime lastRun(long lastRun) {
this.lastRun = lastRun; this.lastRun = lastRun;
return this; return this;
@ -251,6 +271,7 @@ public class TriggerTime extends Trigger {
public View createView(Context context) { public View createView(Context context) {
LinearLayout root = (LinearLayout) super.createView(context); LinearLayout root = (LinearLayout) super.createView(context);
// TODO: Replace external tool WeekdaysPicker with a self-made GUI element
WeekdaysPicker weekdaysPicker = new WeekdaysPicker(context); WeekdaysPicker weekdaysPicker = new WeekdaysPicker(context);
weekdaysPicker.setEditable(true); weekdaysPicker.setEditable(true);
weekdaysPicker.setSelectedDays(getSelectedDays()); weekdaysPicker.setSelectedDays(getSelectedDays());