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.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
@ -25,6 +25,7 @@ import butterknife.OnClick;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
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.triggers.Trigger;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
@ -126,20 +127,12 @@ public class AutomationFragment extends SubscriberFragment {
public static class TriggerListAdapter {
private final LinearLayout mRootLayout;
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;
mContext = context;
mTriggerList = triggers;
build();
}
public TriggerListAdapter(Context context, LinearLayout rootLayout, Trigger trigger) {
mRootLayout = rootLayout;
mContext = context;
mTriggerList = new ArrayList<>();
mTriggerList.add(trigger);
mRootConnector = rootTrigger;
build();
}
@ -148,6 +141,38 @@ public class AutomationFragment extends SubscriberFragment {
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() {
Spinner spinner = new Spinner(mContext);
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;
}
private void build() {
boolean isFirstItem = true;
for(Trigger trigger : mTriggerList) {
if (!isFirstItem) {
final TriggerConnector connector = trigger.getConnector();
final int initialPosition = connector.getConnectorType().ordinal();
Spinner spinner = createSpinner();
spinner.setSelection(initialPosition);
spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
spinner.setLayoutParams(params);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
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;
private void createSpinner(Trigger trigger) {
final TriggerConnector connector = trigger.getConnector();
final int initialPosition = connector.getConnectorType().ordinal();
Spinner spinner = createSpinner();
spinner.setSelection(initialPosition);
spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
spinner.setLayoutParams(params);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position != initialPosition) {
// conector type changed
changeConnector(trigger, connector, TriggerConnector.Type.values()[position]);
}
}
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) {

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.AutomationFragment;
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.TriggerTime;
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);
mUnbinder = ButterKnife.bind(this, view);
// dummy initialization
TriggerConnector to = new TriggerConnector(TriggerConnector.Type.OR);
to.add(new TriggerBg());
to.add(new TriggerTime());
mEvent.setTrigger(to);
// initialization
TriggerConnector rootTrigger = new TriggerConnector(TriggerConnector.Type.OR);
mEvent.setTrigger(rootTrigger);
// display triggers
mTriggerListAdapter = new AutomationFragment.TriggerListAdapter(getContext(), mLayoutTrigger, mEvent.getTrigger());
// display root trigger
mLayoutTrigger.addView(rootTrigger.createView(getContext()));
return view;
}

View file

@ -97,6 +97,8 @@ public abstract class Trigger {
void notifyAboutRun(long time) {
}
public abstract Trigger duplicate();
static Trigger instantiate(JSONObject object) {
try {
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
public synchronized boolean shouldRun() {
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
@ -99,6 +110,11 @@ public class TriggerBg extends Trigger {
return MainApp.gs(R.string.glucosecompared, comparator.getStringRes(), threshold, units);
}
@Override
public Trigger duplicate() {
return new TriggerBg(this);
}
TriggerBg threshold(double threshold) {
this.threshold = threshold;
return this;

View file

@ -2,10 +2,8 @@ package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.content.Context;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import org.json.JSONArray;
@ -18,7 +16,6 @@ import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment;
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog;
import info.nightscout.utils.JsonHelper;
public class TriggerConnector extends Trigger {
@ -172,6 +169,11 @@ public class TriggerConnector extends Trigger {
return result.toString();
}
@Override
public Trigger duplicate() {
return null;
}
private AutomationFragment.TriggerListAdapter adapter;
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));
root.addView(triggerListLayout);
adapter = new AutomationFragment.TriggerListAdapter(context, triggerListLayout, list);
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);
adapter = new AutomationFragment.TriggerListAdapter(context, triggerListLayout, this);
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() {
// simplify children
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];
long lastRun;
private long lastRun;
// Single execution
long runAt;
private long runAt;
// Recurring
boolean recurring;
int hour;
int minute;
private boolean recurring;
private int hour;
private int minute;
long validTo;
private long validTo;
public TriggerTime() {
super();
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) {
for(DayOfWeek day : DayOfWeek.values()) {
set(day, value);
@ -207,6 +222,11 @@ public class TriggerTime extends Trigger {
lastRun = time;
}
@Override
public Trigger duplicate() {
return new TriggerTime(this);
}
TriggerTime lastRun(long lastRun) {
this.lastRun = lastRun;
return this;
@ -251,6 +271,7 @@ public class TriggerTime extends Trigger {
public View createView(Context context) {
LinearLayout root = (LinearLayout) super.createView(context);
// TODO: Replace external tool WeekdaysPicker with a self-made GUI element
WeekdaysPicker weekdaysPicker = new WeekdaysPicker(context);
weekdaysPicker.setEditable(true);
weekdaysPicker.setSelectedDays(getSelectedDays());