diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index 98779179f6..4258eafa95 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -115,10 +115,6 @@ public class MainActivity extends AppCompatActivity { MainApp.bus().register(this); } - public static TabPageAdapter getPageAdapter() { - return pageAdapter; - } - public static ArrayList getPluginsList() { return pluginsList; } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index 558381b061..56b3db443d 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -168,7 +168,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { /* * Returns glucose_status for openAPS or null if no actual data available */ - public class GlucoseStatus { + public static class GlucoseStatus { public double glucose = 0d; public double delta = 0d; public double avgdelta = 0d; diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java new file mode 100644 index 0000000000..e7094b7aa2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.interfaces; + +/** + * Created by mike on 15.06.2016. + */ +public interface ConstrainsInterface { +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index 26f15883d3..36897d0f7d 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -12,6 +12,7 @@ public interface PluginBase { int PROFILE = 4; int APS = 5; int PUMP = 6; + int CONSTRAINS = 7; public int getType(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/APSResult.java index 27b4650f76..80f702883c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/APSResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/APSResult.java @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins; import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; import java.text.DecimalFormat; @@ -11,7 +13,7 @@ import info.nightscout.androidaps.R; /** * Created by mike on 09.06.2016. */ -public class APSResult { +public class APSResult implements Parcelable { public String reason; public double rate; public int duration; @@ -31,4 +33,37 @@ public class APSResult { else return MainApp.instance().getApplicationContext().getString(R.string.nochangerequested); } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(reason); + dest.writeDouble(rate); + dest.writeInt(duration); + dest.writeInt(changeRequested ? 1 : 0); + } + + public final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public APSResult createFromParcel(Parcel in) { + return new APSResult(in); + } + + public APSResult[] newArray(int size) { + return new APSResult[size]; + } + }; + + private APSResult(Parcel in) { + reason = in.readString(); + rate = in.readDouble(); + duration = in.readInt(); + changeRequested = in.readInt() == 1; + } + + public APSResult() {} + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index cfb1d08539..9c8ea0d4bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java @@ -12,6 +12,7 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; @@ -30,6 +31,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.interfaces.ConstrainsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; @@ -39,10 +41,7 @@ import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.client.data.NSProfile; -/** - * A simple {@link Fragment} subclass. - */ -public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface { +public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface, ConstrainsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderFragment.class); private static final String PREFS_NAME = "Settings"; @@ -52,6 +51,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI ListView tempsListView; ListView profileListView; ListView apsListView; + ListView constrainsListView; ListView generalListView; PluginCustomAdapter pumpDataAdapter = null; @@ -59,6 +59,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI PluginCustomAdapter tempsDataAdapter = null; PluginCustomAdapter profileDataAdapter = null; PluginCustomAdapter apsDataAdapter = null; + PluginCustomAdapter constrainsDataAdapter = null; PluginCustomAdapter generalDataAdapter = null; @@ -102,6 +103,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI tempsListView = (ListView) view.findViewById(R.id.configbuilder_tempslistview); profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview); apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview); + constrainsListView = (ListView) view.findViewById(R.id.configbuilder_constrainslistview); generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview); setViews(); @@ -111,28 +113,26 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI void setViews() { pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.PUMP)); pumpListView.setAdapter(pumpDataAdapter); + setListViewHeightBasedOnChildren(pumpListView); treatmentsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.TREATMENT)); treatmentsListView.setAdapter(treatmentsDataAdapter); + setListViewHeightBasedOnChildren(treatmentsListView); tempsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.TEMPBASAL)); tempsListView.setAdapter(tempsDataAdapter); + setListViewHeightBasedOnChildren(tempsListView); profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.PROFILE)); profileListView.setAdapter(profileDataAdapter); + setListViewHeightBasedOnChildren(profileListView); apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.APS)); apsListView.setAdapter(apsDataAdapter); + setListViewHeightBasedOnChildren(apsListView); + constrainsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS)); + constrainsListView.setAdapter(constrainsDataAdapter); + setListViewHeightBasedOnChildren(constrainsListView); generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.GENERAL)); generalListView.setAdapter(generalDataAdapter); + setListViewHeightBasedOnChildren(generalListView); - - apsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View view, - int position, long id) { - // When clicked, show a toast with the TextView text - PluginBase plugin = (PluginBase) parent.getItemAtPosition(position); - Toast.makeText(MainApp.instance().getApplicationContext(), - "Clicked on Row: " + plugin.getName(), - Toast.LENGTH_LONG).show(); - } - }); } /* @@ -307,12 +307,10 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI public void onClick(View v) { CheckBox cb = (CheckBox) v; PluginBase plugin = (PluginBase) cb.getTag(); - Toast.makeText(MainApp.instance().getApplicationContext(), - "Clicked on ENABLED: " + plugin.getName() + - " is " + cb.isChecked(), - Toast.LENGTH_LONG).show(); plugin.setFragmentEnabled(cb.isChecked()); + if (cb.isChecked()) plugin.setFragmentVisible(true); onEnabledCategoryChanged(plugin); + storeSettings(); } }); @@ -320,13 +318,9 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI public void onClick(View v) { CheckBox cb = (CheckBox) v; PluginBase plugin = (PluginBase) cb.getTag(); - Toast.makeText(MainApp.instance().getApplicationContext(), - "Clicked on VISIBLE: " + plugin.getName() + - " is " + cb.isChecked(), - Toast.LENGTH_LONG).show(); plugin.setFragmentVisible(cb.isChecked()); - MainApp.bus().post(new EventRefreshGui()); storeSettings(); + MainApp.bus().post(new EventRefreshGui()); } }); } else { @@ -347,10 +341,25 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } int type = plugin.getType(); + // Force enabled if there is only one plugin if (type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE) if (pluginList.size() < 2) holder.checkboxEnabled.setEnabled(false); + // Constrains cannot be disabled + if (type == PluginBase.CONSTRAINS) + holder.checkboxEnabled.setEnabled(false); + + // Hide disabled profiles by default + if (type == PluginBase.PROFILE) { + if (!plugin.isEnabled()) { + holder.checkboxVisible.setEnabled(false); + holder.checkboxVisible.setChecked(false); + } else { + holder.checkboxVisible.setEnabled(true); + } + } + return convertView; } @@ -378,6 +387,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: + case PluginBase.CONSTRAINS: break; // Single selection allowed case PluginBase.PROFILE: @@ -399,7 +409,6 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } break; } - storeSettings(); } private void verifySelectionInCategories() { @@ -409,27 +418,48 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: + case PluginBase.CONSTRAINS: break; // Single selection allowed case PluginBase.PROFILE: activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory); if (Config.logConfigBuilder) log.debug("Selected profile interface: " + ((PluginBase) activeProfile).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activeProfile).getName())) { + p.setFragmentVisible(false); + } + } break; case PluginBase.PUMP: activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory); if (Config.logConfigBuilder) log.debug("Selected pump interface: " + ((PluginBase) activePump).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activePump).getName())) { + p.setFragmentVisible(false); + } + } break; case PluginBase.TEMPBASAL: activeTempBasals = (TempBasalsInterface) getTheOneEnabledInArray(pluginsInCategory); if (Config.logConfigBuilder) log.debug("Selected tempbasal interface: " + ((PluginBase) activeTempBasals).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activeTempBasals).getName())) { + p.setFragmentVisible(false); + } + } break; case PluginBase.TREATMENT: activeTreatments = (TreatmentsInterface) getTheOneEnabledInArray(pluginsInCategory); if (Config.logConfigBuilder) log.debug("Selected treatment interface: " + ((PluginBase) activeTreatments).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activeTreatments).getName())) { + p.setFragmentVisible(false); + } + } break; } @@ -480,5 +510,29 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI verifySelectionInCategories(); } + /**** + * Method for Setting the Height of the ListView dynamically. + * *** Hack to fix the issue of not showing all the items of the ListView + * *** when placed inside a ScrollView + ****/ + public static void setListViewHeightBasedOnChildren(ListView listView) { + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter == null) + return; + int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED); + int totalHeight = 0; + View view = null; + for (int i = 0; i < listAdapter.getCount(); i++) { + view = listAdapter.getView(i, view, listView); + if (i == 0) + view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT)); + + view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); + totalHeight += view.getMeasuredHeight(); + } + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); + listView.setLayoutParams(params); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LowSuspend/LowSuspendFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/LowSuspend/LowSuspendFragment.java index 5d8adecc35..bfc2ec127c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/LowSuspend/LowSuspendFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/LowSuspend/LowSuspendFragment.java @@ -3,6 +3,8 @@ package info.nightscout.androidaps.plugins.LowSuspend; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -42,11 +44,64 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener TextView resultView; TextView requestView; - Date lastAPSRun = null; - APSResult lastAPSResult = null; + // last values + class LastRun implements Parcelable { + public Boolean lastLow = null; + public Boolean lastLowProjected = null; + public Double lastMinBg = null; + public String lastUnits = null; + public DatabaseHelper.GlucoseStatus lastGlucoseStatus = null; + public Date lastAPSRun = null; + public APSResult lastAPSResult = null; - boolean fragmentEnabled = false; - boolean fragmentVisible = true; + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(lastLow ? 1 : 0); + dest.writeInt(lastLowProjected ? 1 : 0); + dest.writeDouble(lastMinBg); + dest.writeString(lastUnits); + dest.writeDouble(lastGlucoseStatus.avgdelta); + dest.writeDouble(lastGlucoseStatus.delta); + dest.writeDouble(lastGlucoseStatus.glucose); + dest.writeLong(lastAPSRun.getTime()); + dest.writeParcelable(lastAPSResult, 0); + } + + public final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public LastRun createFromParcel(Parcel in) { + return new LastRun(in); + } + + public LastRun[] newArray(int size) { + return new LastRun[size]; + } + }; + + private LastRun(Parcel in) { + lastLow = in.readInt() == 1; + lastLowProjected = in.readInt() == 1; + lastMinBg = in.readDouble(); + lastUnits = in.readString(); + lastGlucoseStatus = new DatabaseHelper.GlucoseStatus(); + lastGlucoseStatus.avgdelta = in.readDouble(); + lastGlucoseStatus.delta = in.readDouble(); + lastGlucoseStatus.glucose = in.readDouble(); + lastAPSRun = new Date(in.readLong()); + lastAPSResult = in.readParcelable(APSResult.class.getClassLoader()); + } + + public LastRun() {} + } + + static LastRun lastRun = null; + + private boolean fragmentEnabled = false; + private boolean fragmentVisible = true; public LowSuspendFragment() { super(); @@ -90,12 +145,16 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener @Override public APSResult getLastAPSResult() { - return lastAPSResult; + if (lastRun != null) + return lastRun.lastAPSResult; + else return null; } @Override public Date getLastAPSRun() { - return lastAPSRun; + if (lastRun != null) + return lastRun.lastAPSRun; + else return null; } public static LowSuspendFragment newInstance() { @@ -121,9 +180,19 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener resultView = (TextView) view.findViewById(R.id.lowsuspend_result); requestView = (TextView) view.findViewById(R.id.lowsuspend_request); + if (savedInstanceState != null) { + lastRun = savedInstanceState.getParcelable("lastrun"); + } + updateGUI(); return view; } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable("lastrun", lastRun); + } + private void registerBus() { try { MainApp.bus().unregister(this); @@ -161,7 +230,6 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener public void invoke() { SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData(); - DecimalFormat formatNumber1decimalplaces = new DecimalFormat("0.0"); NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); @@ -197,6 +265,7 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener Double baseBasalRate = pump.getBaseBasalRate(); boolean isTempBasalInProgress = pump.isTempBasalInProgress(); Double tempBasalRate = pump.getTempBasalAbsoluteRate(); + Date now = new Date(); if (low && !lowProjected) { if (!isTempBasalInProgress || tempBasalRate != 0d) { @@ -227,13 +296,26 @@ public class LowSuspendFragment extends Fragment implements View.OnClickListener request.changeRequested = false; request.reason = getString(R.string.nochangerequested); } - glucoseStatusView.setText(glucoseStatus.toString()); - minBgView.setText(formatNumber1decimalplaces.format(minBg) + " " + profile.getUnits()); - resultView.setText(getString(R.string.lowsuspend_low) + " " + low + "\n" + getString(R.string.lowsuspend_lowprojected) + " " + lowProjected); - requestView.setText(request.toString()); - lastRunView.setText(new Date().toLocaleString()); - lastAPSResult = request; - lastAPSRun = new Date(); + lastRun = new LastRun(); + lastRun.lastMinBg = minBg; + lastRun.lastLow = low; + lastRun.lastLowProjected = lowProjected; + lastRun.lastGlucoseStatus = glucoseStatus; + lastRun.lastUnits = profile.getUnits(); + lastRun.lastAPSResult = request; + lastRun.lastAPSRun = now; + updateGUI(); + } + + void updateGUI() { + if (lastRun != null) { + DecimalFormat formatNumber1decimalplaces = new DecimalFormat("0.0"); + glucoseStatusView.setText(lastRun.lastGlucoseStatus.toString()); + minBgView.setText(formatNumber1decimalplaces.format(lastRun.lastMinBg) + " " + lastRun.lastUnits); + resultView.setText(getString(R.string.lowsuspend_low) + " " + lastRun.lastLow + "\n" + getString(R.string.lowsuspend_lowprojected) + " " + lastRun.lastLowProjected); + requestView.setText(lastRun.lastAPSResult.toString()); + lastRunView.setText(lastRun.lastAPSRun.toLocaleString()); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java index 29ee7bfb13..a85b111486 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.Objectives; +import android.content.Context; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.widget.CardView; @@ -8,25 +10,38 @@ import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.LinearLayout; import android.widget.TextView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Date; import java.util.List; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.ConstrainsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -public class ObjectivesFragment extends Fragment implements PluginBase { +public class ObjectivesFragment extends Fragment implements View.OnClickListener, PluginBase, ConstrainsInterface { + private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); + RecyclerView recyclerView; LinearLayoutManager llm; + CheckBox enableFakeTime; boolean fragmentVisible = true; + String PREFS_NAME = "Objectives"; + @Override public int getType() { - return PluginBase.GENERAL; + return PluginBase.CONSTRAINS; } @Override @@ -58,6 +73,15 @@ public class ObjectivesFragment extends Fragment implements PluginBase { this.fragmentVisible = fragmentVisible; } + @Override + public void onClick(View v) { + int id = v.getId(); + switch (id) { + default: + break; + } + } + class Objective { String objective; String gate; @@ -95,13 +119,41 @@ public class ObjectivesFragment extends Fragment implements PluginBase { new Date(0, 0, 0), 1, new Date(0, 0, 0))); objectives.add(new Objective("Adjust basals and ratios if needed, and then enable auto-sens", "1 week successful daytime looping with regular carb entry", - new Date(0, 0, 0), 1, new Date(0, 0, 0))); + new Date(0, 0, 0), 7, new Date(0, 0, 0))); objectives.add(new Objective("Enabling additional features for daytime use, such as advanced meal assist", "", new Date(0, 0, 0), 1, new Date(0, 0, 0))); } - public static class RecyclerViewAdapter extends RecyclerView.Adapter { + void saveProgress() { + SharedPreferences settings = MainApp.instance().getApplicationContext().getSharedPreferences(PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + for (int num = 0; num < objectives.size(); num++) { + Objective o = objectives.get(num); + editor.putLong(num + "started", o.started.getTime()); + editor.putLong(num + "accomplished", o.accomplished.getTime()); + } + editor.commit(); + if (Config.logPrefsChange) + log.debug("Objectives stored"); + } + + void loadProgress() { + SharedPreferences settings = MainApp.instance().getApplicationContext().getSharedPreferences(PREFS_NAME, 0); + for (int num = 0; num < objectives.size(); num++) { + Objective o = objectives.get(num); + o.started = new Date(settings.getLong(num + "started", 0)); + o.accomplished = new Date(settings.getLong(num + "accomplished", 0)); + } + if (Config.logPrefsChange) + log.debug("Objectives loaded"); + } + + boolean isAPSEnabledAtAll() { + return true; + } + + public class RecyclerViewAdapter extends RecyclerView.Adapter { List objectives; @@ -118,11 +170,61 @@ public class ObjectivesFragment extends Fragment implements PluginBase { @Override public void onBindViewHolder(ObjectiveViewHolder holder, int position) { + Objective o = objectives.get(position); + Context context = MainApp.instance().getApplicationContext(); holder.position.setText(String.valueOf(position + 1)); - holder.objective.setText(objectives.get(position).objective); - holder.gate.setText(objectives.get(position).gate); - holder.started.setText(objectives.get(position).started.toString()); - holder.accomplished.setText(objectives.get(position).accomplished.toString()); + holder.objective.setText(o.objective); + holder.gate.setText(o.gate); + holder.duration.setText(context.getString(R.string.minimalduration) + " " + o.durationInDays + " " + context.getString(R.string.days)); + holder.started.setText(o.started.toLocaleString()); + holder.accomplished.setText(o.accomplished.toLocaleString()); + + holder.startButton.setTag(o); + holder.verifyButton.setTag(o); + + holder.startButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + Objective o = (Objective) v.getTag(); + o.started = new Date(); + updateView(); + //saveProgress(); + } + }); + holder.verifyButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + Objective o = (Objective) v.getTag(); + o.accomplished = new Date(); + updateView(); + //saveProgress(); + } + }); + + Long now = new Date().getTime(); + if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 0) { + // Phase 0: previous not completed + holder.startedLayout.setVisibility(View.GONE); + holder.durationLayout.setVisibility(View.GONE); + holder.verifyLayout.setVisibility(View.GONE); + } else if (o.started.getTime() == 0) { + // Phase 1: not started + holder.durationLayout.setVisibility(View.GONE); + holder.verifyLayout.setVisibility(View.GONE); + holder.started.setVisibility(View.GONE); + } else if (o.started.getTime() > 0 && !enableFakeTime.isChecked() && o.accomplished.getTime() == 0 && o.started.getTime() + o.durationInDays * 24 * 60 * 60 * 1000 > now) { + // Phase 2: started, waiting for duration + holder.startButton.setEnabled(false); + holder.verifyLayout.setVisibility(View.GONE); + } else if (o.accomplished.getTime() == 0 ) { + // Phase 3: started, after duration + holder.startButton.setEnabled(false); + holder.accomplished.setVisibility(View.INVISIBLE); + } else { + // Phase 4: verified + holder.gateLayout.setVisibility(View.GONE); + holder.startedLayout.setVisibility(View.GONE); + holder.durationLayout.setVisibility(View.GONE); + holder.verifyButton.setVisibility(View.INVISIBLE); + } } @Override @@ -135,22 +237,36 @@ public class ObjectivesFragment extends Fragment implements PluginBase { super.onAttachedToRecyclerView(recyclerView); } - public static class ObjectiveViewHolder extends RecyclerView.ViewHolder { + public class ObjectiveViewHolder extends RecyclerView.ViewHolder { CardView cv; TextView position; TextView objective; + LinearLayout gateLayout; TextView gate; + TextView duration; + LinearLayout durationLayout; TextView started; + Button startButton; + LinearLayout startedLayout; TextView accomplished; + Button verifyButton; + LinearLayout verifyLayout; ObjectiveViewHolder(View itemView) { super(itemView); cv = (CardView) itemView.findViewById(R.id.objectives_cardview); position = (TextView) itemView.findViewById(R.id.objectives_position); objective = (TextView) itemView.findViewById(R.id.objectives_objective); + durationLayout = (LinearLayout) itemView.findViewById(R.id.objectives_duration_linearlayout); + duration = (TextView) itemView.findViewById(R.id.objectives_duration); + gateLayout = (LinearLayout) itemView.findViewById(R.id.objectives_gate_linearlayout); gate = (TextView) itemView.findViewById(R.id.objectives_gate); + startedLayout = (LinearLayout) itemView.findViewById(R.id.objectives_start_linearlayout); started = (TextView) itemView.findViewById(R.id.objectives_started); + startButton = (Button) itemView.findViewById(R.id.objectives_start); + verifyLayout = (LinearLayout) itemView.findViewById(R.id.objectives_verify_linearlayout); accomplished = (TextView) itemView.findViewById(R.id.objectives_accomplished); + verifyButton = (Button) itemView.findViewById(R.id.objectives_verify); } } } @@ -158,6 +274,7 @@ public class ObjectivesFragment extends Fragment implements PluginBase { public ObjectivesFragment() { super(); initializeData(); + loadProgress(); } public static ObjectivesFragment newInstance() { @@ -179,11 +296,20 @@ public class ObjectivesFragment extends Fragment implements PluginBase { recyclerView.setHasFixedSize(true); llm = new LinearLayoutManager(view.getContext()); recyclerView.setLayoutManager(llm); - - RecyclerViewAdapter adapter = new RecyclerViewAdapter(objectives); - recyclerView.setAdapter(adapter); + enableFakeTime = (CheckBox) view.findViewById(R.id.objectives_faketime); + enableFakeTime.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + updateView(); + } + }); + updateView(); return view; } + void updateView() { + RecyclerViewAdapter adapter = new RecyclerViewAdapter(objectives); + recyclerView.setAdapter(adapter); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java index e26a588d5d..20b852b904 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java @@ -1,15 +1,26 @@ package info.nightscout.androidaps.plugins.SimpleProfile; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.TextView; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; @@ -19,12 +30,37 @@ import info.nightscout.client.data.NSProfile; public class SimpleProfileFragment extends Fragment implements PluginBase, ProfileInterface { private static Logger log = LoggerFactory.getLogger(SimpleProfileFragment.class); + private static final String PREFS_NAME = "SimpleProfile"; + boolean fragmentEnabled = true; boolean fragmentVisible = true; + EditText diaView; + RadioButton mgdlView; + RadioButton mmolView; + EditText icView; + EditText isfView; + EditText carView; + EditText basalView; + EditText targetlowView; + EditText targethighView; + + boolean mgdl; + boolean mmol; + Double dia; + Double ic; + Double isf; + Double car; + Double basal; + Double targetLow; + Double targetHigh; + + NSProfile convertedProfile = null; + public SimpleProfileFragment() { super(); registerBus(); + loadSettings(); } @Override @@ -71,7 +107,75 @@ public class SimpleProfileFragment extends Fragment implements PluginBase, Profi public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.simpleprofile_fragment, container, false); + diaView = (EditText) layout.findViewById(R.id.simpleprofile_dia); + mgdlView = (RadioButton) layout.findViewById(R.id.simpleprofile_mgdl); + mmolView = (RadioButton) layout.findViewById(R.id.simpleprofile_mmol); + icView = (EditText) layout.findViewById(R.id.simpleprofile_ic); + isfView = (EditText) layout.findViewById(R.id.simpleprofile_isf); + carView = (EditText) layout.findViewById(R.id.simpleprofile_car); + basalView = (EditText) layout.findViewById(R.id.simpleprofile_basalrate); + targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow); + targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh); + mgdlView.setChecked(mgdl); + mmolView.setChecked(mmol); + diaView.setText(dia.toString()); + icView.setText(ic.toString()); + isfView.setText(isf.toString()); + carView.setText(car.toString()); + basalView.setText(basal.toString()); + targetlowView.setText(targetLow.toString()); + targethighView.setText(targetHigh.toString()); + + mgdlView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mgdl = mgdlView.isChecked(); + mmol = !mgdl; + mmolView.setChecked(mmol); + storeSettings(); + } + }); + mmolView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mmol = mmolView.isChecked(); + mgdl = !mmol; + mgdlView.setChecked(mgdl); + storeSettings(); + } + }); + + TextWatcher textWatch = new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + dia = Double.parseDouble(diaView.getText().toString().replace(",", ".")); + ic = Double.parseDouble(icView.getText().toString().replace(",", ".")); + isf = Double.parseDouble(isfView.getText().toString().replace(",", ".")); + car = Double.parseDouble(carView.getText().toString().replace(",", ".")); + basal = Double.parseDouble(basalView.getText().toString().replace(",", ".")); + targetLow = Double.parseDouble(targetlowView.getText().toString().replace(",", ".")); + targetHigh = Double.parseDouble(targethighView.getText().toString().replace(",", ".")); + } + }; + diaView.addTextChangedListener(textWatch); + icView.addTextChangedListener(textWatch); + isfView.addTextChangedListener(textWatch); + carView.addTextChangedListener(textWatch); + basalView.addTextChangedListener(textWatch); + targetlowView.addTextChangedListener(textWatch); + targethighView.addTextChangedListener(textWatch); return layout; } @@ -89,8 +193,107 @@ public class SimpleProfileFragment extends Fragment implements PluginBase, Profi MainApp.bus().register(this); } + private void storeSettings() { + if (Config.logPrefsChange) + log.debug("Storing settings"); + SharedPreferences settings = MainApp.instance().getApplicationContext().getSharedPreferences(PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putBoolean("mmol", mmol); + editor.putBoolean("mgdl", mgdl); + editor.putFloat("dia", new Float(dia)); + editor.putFloat("ic", new Float(ic)); + editor.putFloat("isf", new Float(isf)); + editor.putFloat("car", new Float(car)); + editor.putFloat("basal", new Float(basal)); + editor.putFloat("targetlow", new Float(targetLow)); + editor.putFloat("targethigh", new Float(targetHigh)); + + editor.commit(); + createConvertedProfile(); + } + + private void loadSettings() { + if (Config.logPrefsChange) + log.debug("Loading stored settings"); + SharedPreferences settings = MainApp.instance().getApplicationContext().getSharedPreferences(PREFS_NAME, 0); + + if (settings.contains("mgdl")) mgdl = settings.getBoolean("mgdl", true); else mgdl = true; + if (settings.contains("mmol")) mmol = settings.getBoolean("mmol", false); else mmol = false; + if (settings.contains("dia")) dia = (double) settings.getFloat("dia", 3); else dia = 3d; + if (settings.contains("ic")) ic = (double) settings.getFloat("ic", 20); else ic = 20d; + if (settings.contains("isf")) isf = (double) settings.getFloat("isf", 200); else isf = 200d; + if (settings.contains("car")) car = (double) settings.getFloat("car", 20); else car = 20d; + if (settings.contains("basal")) basal = (double) settings.getFloat("basal", 1); else basal = 1d; + if (settings.contains("targetlow")) targetLow = (double) settings.getFloat("targetlow", 80); else targetLow = 80d; + if (settings.contains("targethigh")) + targetHigh = (double) settings.getFloat("targethigh", 120); else targetHigh = 120d; + createConvertedProfile(); + } + + + /* + { + "_id": "576264a12771b7500d7ad184", + "startDate": "2016-06-16T08:35:00.000Z", + "defaultProfile": "Default", + "store": { + "Default": { + "dia": "3", + "carbratio": [{ + "time": "00:00", + "value": "30" + }], + "carbs_hr": "20", + "delay": "20", + "sens": [{ + "time": "00:00", + "value": "100" + }], + "timezone": "UTC", + "basal": [{ + "time": "00:00", + "value": "0.1" + }], + "target_low": [{ + "time": "00:00", + "value": "0" + }], + "target_high": [{ + "time": "00:00", + "value": "0" + }], + "startDate": "1970-01-01T00:00:00.000Z", + "units": "mmol" + } + }, + "created_at": "2016-06-16T08:34:41.256Z" + } + */ + void createConvertedProfile() { + JSONObject json = new JSONObject(); + JSONObject store = new JSONObject(); + JSONObject profile = new JSONObject(); + + try { + json.put("defaultProfile", "Profile"); + json.put("store", store); + profile.put("dia", dia); + profile.put("carbratio", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", ic))); + profile.put("carbs_hr", car); + profile.put("sens", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", isf))); + profile.put("basal", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", basal))); + profile.put("target_low", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetLow))); + profile.put("target_high", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetHigh))); + profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL); + store.put("Profile", profile); + } catch (JSONException e) { + e.printStackTrace(); + } + convertedProfile = new NSProfile(json, null); + } + @Override public NSProfile getProfile() { - return null; + return convertedProfile; } } diff --git a/app/src/main/res/layout/configbuilder_fragment.xml b/app/src/main/res/layout/configbuilder_fragment.xml index e5dd0b4b7f..6a603ab526 100644 --- a/app/src/main/res/layout/configbuilder_fragment.xml +++ b/app/src/main/res/layout/configbuilder_fragment.xml @@ -4,100 +4,126 @@ android:layout_height="match_parent" tools:context="info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment"> - + android:layout_height="match_parent"> - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + diff --git a/app/src/main/res/layout/configbuilder_simpleitem.xml b/app/src/main/res/layout/configbuilder_simpleitem.xml index 3d8894ed94..af5d7e531b 100644 --- a/app/src/main/res/layout/configbuilder_simpleitem.xml +++ b/app/src/main/res/layout/configbuilder_simpleitem.xml @@ -1,49 +1,44 @@ - + android:layout_height="wrap_content" + android:orientation="horizontal"> - + android:layout_alignParentLeft="true" + android:layout_gravity="center" + android:focusable="false" + android:focusableInTouchMode="false" + android:text="Enabled" /> - + - + - - - + - - \ No newline at end of file + diff --git a/app/src/main/res/layout/objectives_fragment.xml b/app/src/main/res/layout/objectives_fragment.xml index 062d9931cb..ec5cbd771c 100644 --- a/app/src/main/res/layout/objectives_fragment.xml +++ b/app/src/main/res/layout/objectives_fragment.xml @@ -4,12 +4,24 @@ android:layout_height="match_parent" tools:context=".plugins.Objectives.ObjectivesFragment"> - - + + + + + + diff --git a/app/src/main/res/layout/objectives_item.xml b/app/src/main/res/layout/objectives_item.xml index 2dea4f5fd0..948ebb37f0 100644 --- a/app/src/main/res/layout/objectives_item.xml +++ b/app/src/main/res/layout/objectives_item.xml @@ -68,7 +68,8 @@ + android:orientation="horizontal" + android:id="@+id/objectives_gate_linearlayout"> + android:orientation="horizontal" + android:id="@+id/objectives_start_linearlayout">