From ddb1868018055c80a8e4f1bd32010955e1aee93a Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 15 Jun 2016 21:47:26 +0200 Subject: [PATCH 1/3] Constrains interface --- .../interfaces/ConstrainsInterface.java | 7 + .../androidaps/interfaces/PluginBase.java | 1 + .../ConfigBuilder/ConfigBuilderFragment.java | 60 ++++-- .../Objectives/ObjectivesFragment.java | 150 ++++++++++++-- .../res/layout/configbuilder_fragment.xml | 190 ++++++++++-------- .../res/layout/configbuilder_simpleitem.xml | 73 ++++--- .../main/res/layout/objectives_fragment.xml | 18 +- app/src/main/res/layout/objectives_item.xml | 21 +- app/src/main/res/values/strings.xml | 3 + 9 files changed, 365 insertions(+), 158 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java 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/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index cfb1d08539..add2491614 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; @@ -52,6 +53,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI ListView tempsListView; ListView profileListView; ListView apsListView; + ListView constrainsListView; ListView generalListView; PluginCustomAdapter pumpDataAdapter = null; @@ -59,6 +61,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 +105,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 +115,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,10 +309,6 @@ 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()); onEnabledCategoryChanged(plugin); } @@ -320,10 +318,6 @@ 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(); @@ -350,6 +344,8 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI if (type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE) if (pluginList.size() < 2) holder.checkboxEnabled.setEnabled(false); + if (type == PluginBase.CONSTRAINS) + holder.checkboxEnabled.setEnabled(false); return convertView; @@ -378,6 +374,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: @@ -409,6 +406,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: @@ -480,5 +478,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/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/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">