ObjectivesFragment to kotlin

This commit is contained in:
Milos Kozak 2019-09-03 18:11:28 +02:00
parent a75312eea0
commit 702ca21459
3 changed files with 228 additions and 263 deletions

View file

@ -1,255 +0,0 @@
package info.nightscout.androidaps.plugins.constraints.objectives;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.common.SubscriberFragment;
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.FabricPrivacy;
public class ObjectivesFragment extends SubscriberFragment {
private RecyclerView recyclerView;
private CheckBox enableFake;
private TextView reset;
private ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter();
private Handler handler = new Handler(Looper.getMainLooper());
private Runnable objectiveUpdater = new Runnable() {
@Override
public void run() {
handler.postDelayed(this, 60 * 1000);
updateGUI();
}
};
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
recyclerView = view.findViewById(R.id.objectives_recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
recyclerView.setAdapter(objectivesAdapter);
enableFake = view.findViewById(R.id.objectives_fake);
reset = view.findViewById(R.id.objectives_reset);
enableFake.setOnClickListener(v -> updateGUI());
reset.setOnClickListener(v -> {
ObjectivesPlugin.INSTANCE.reset();
recyclerView.getAdapter().notifyDataSetChanged();
scrollToCurrentObjective();
});
scrollToCurrentObjective();
startUpdateTimer();
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
}
return null;
}
@Override
public synchronized void onDestroyView() {
super.onDestroyView();
handler.removeCallbacks(objectiveUpdater);
}
private void startUpdateTimer() {
handler.removeCallbacks(objectiveUpdater);
for (Objective objective : ObjectivesPlugin.INSTANCE.getObjectives()) {
if (objective.isStarted() && !objective.isAccomplished()) {
long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn()) % (60 * 1000);
handler.postDelayed(objectiveUpdater, timeTillNextMinute);
break;
}
}
}
private void scrollToCurrentObjective() {
for (int i = 0; i < ObjectivesPlugin.INSTANCE.getObjectives().size(); i++) {
Objective objective = ObjectivesPlugin.INSTANCE.getObjectives().get(i);
if (!objective.isStarted() || !objective.isAccomplished()) {
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
@Override
protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
@Override
protected int calculateTimeForScrolling(int dx) {
return super.calculateTimeForScrolling(dx) * 4;
}
};
smoothScroller.setTargetPosition(i);
recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
break;
}
}
}
private class ObjectivesAdapter extends RecyclerView.Adapter<ObjectivesAdapter.ViewHolder> {
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Objective objective = ObjectivesPlugin.INSTANCE.getObjectives().get(position);
holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1));
holder.revert.setVisibility(View.INVISIBLE);
if (objective.getObjective() != 0) {
holder.objective.setVisibility(View.VISIBLE);
holder.objective.setText(MainApp.gs(objective.getObjective()));
} else holder.objective.setVisibility(View.GONE);
if (objective.getGate() != 0) {
holder.gate.setVisibility(View.VISIBLE);
holder.gate.setText(MainApp.gs(objective.getGate()));
} else holder.gate.setVisibility(View.GONE);
if (!objective.isStarted()) {
holder.gate.setTextColor(0xFFFFFFFF);
holder.verify.setVisibility(View.GONE);
holder.progress.setVisibility(View.GONE);
holder.accomplished.setVisibility(View.GONE);
if (position == 0 || ObjectivesPlugin.INSTANCE.getObjectives().get(position - 1).isAccomplished())
holder.start.setVisibility(View.VISIBLE);
else holder.start.setVisibility(View.GONE);
} else if (objective.isAccomplished()) {
holder.gate.setTextColor(0xFF4CAF50);
holder.verify.setVisibility(View.GONE);
holder.progress.setVisibility(View.GONE);
holder.start.setVisibility(View.GONE);
holder.accomplished.setVisibility(View.VISIBLE);
} else if (objective.isStarted()) {
holder.gate.setTextColor(0xFFFFFFFF);
holder.verify.setVisibility(View.VISIBLE);
holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked());
holder.start.setVisibility(View.GONE);
holder.accomplished.setVisibility(View.GONE);
if (objective.isRevertable()) {
holder.revert.setVisibility(View.VISIBLE);
}
holder.progress.setVisibility(View.VISIBLE);
holder.progress.removeAllViews();
for (Objective.Task task : objective.getTasks()) {
if (task.shouldBeIgnored()) continue;
TextView textView = new TextView(holder.progress.getContext());
textView.setTextColor(0xFFFFFFFF);
String basicHTML = "%2$s: <font color=\"%1$s\"><b>%3$s</b></font>";
String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress());
textView.setText(Html.fromHtml(formattedHTML));
holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
}
}
holder.accomplished.setText(MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.getAccomplishedOn())));
holder.accomplished.setTextColor(0xFFC1C1C1);
holder.verify.setOnClickListener((view) -> {
objective.setAccomplishedOn(DateUtil.now());
notifyDataSetChanged();
scrollToCurrentObjective();
startUpdateTimer();
});
holder.start.setOnClickListener((view) -> {
objective.setStartedOn(DateUtil.now());
notifyDataSetChanged();
scrollToCurrentObjective();
startUpdateTimer();
});
holder.revert.setOnClickListener((view) -> {
objective.setAccomplishedOn(0);
objective.setStartedOn(0);
if (position > 0) {
Objective prevObj = ObjectivesPlugin.INSTANCE.getObjectives().get(position - 1);
prevObj.setAccomplishedOn(0);
}
notifyDataSetChanged();
scrollToCurrentObjective();
});
if (objective.hasSpecialInput && !objective.isAccomplished()) {
holder.enterButton.setVisibility(View.VISIBLE);
holder.input.setVisibility(View.VISIBLE);
holder.inputHint.setVisibility(View.VISIBLE);
holder.enterButton.setOnClickListener((view) -> {
String input = holder.input.getText().toString();
objective.specialAction(getActivity(), input);
notifyDataSetChanged();
});
} else {
holder.enterButton.setVisibility(View.GONE);
holder.input.setVisibility(View.GONE);
holder.inputHint.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return ObjectivesPlugin.INSTANCE.getObjectives().size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
CardView cardView;
public TextView title;
public TextView objective;
TextView gate;
TextView accomplished;
public LinearLayout progress;
Button verify;
public Button start;
Button revert;
TextView inputHint;
EditText input;
Button enterButton;
ViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView;
title = itemView.findViewById(R.id.objective_title);
objective = itemView.findViewById(R.id.objective_objective);
gate = itemView.findViewById(R.id.objective_gate);
progress = itemView.findViewById(R.id.objective_progress);
verify = itemView.findViewById(R.id.objective_verify);
start = itemView.findViewById(R.id.objective_start);
revert = itemView.findViewById(R.id.objective_back);
accomplished = itemView.findViewById(R.id.objective_accomplished);
inputHint = itemView.findViewById(R.id.objective_inputhint);
input = itemView.findViewById(R.id.objective_input);
enterButton = itemView.findViewById(R.id.objective_enterbutton);
}
}
}
@Override
public void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
objectivesAdapter.notifyDataSetChanged();
});
}
}

View file

@ -0,0 +1,220 @@
package info.nightscout.androidaps.plugins.constraints.objectives
import android.graphics.Color
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import kotlinx.android.synthetic.main.objectives_fragment.*
class ObjectivesFragment : Fragment() {
private val objectivesAdapter = ObjectivesAdapter()
private val handler = Handler(Looper.getMainLooper())
private val objectiveUpdater = object : Runnable {
override fun run() {
handler.postDelayed(this, (60 * 1000).toLong())
updateGUI()
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.objectives_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
objectives_recyclerview.layoutManager = LinearLayoutManager(view.context)
objectives_recyclerview.adapter = objectivesAdapter
objectives_fake.setOnClickListener { updateGUI() }
objectives_reset.setOnClickListener {
ObjectivesPlugin.reset()
objectives_recyclerview.adapter?.notifyDataSetChanged()
scrollToCurrentObjective()
}
scrollToCurrentObjective()
startUpdateTimer()
}
@Synchronized
override fun onDestroyView() {
super.onDestroyView()
handler.removeCallbacks(objectiveUpdater)
}
private fun startUpdateTimer() {
handler.removeCallbacks(objectiveUpdater)
for (objective in ObjectivesPlugin.objectives) {
if (objective.isStarted && !objective.isAccomplished) {
val timeTillNextMinute = (System.currentTimeMillis() - objective.startedOn) % (60 * 1000)
handler.postDelayed(objectiveUpdater, timeTillNextMinute)
break
}
}
}
private fun scrollToCurrentObjective() {
for (i in 0 until ObjectivesPlugin.objectives.size) {
val objective = ObjectivesPlugin.objectives[i]
if (!objective.isStarted || !objective.isAccomplished) {
val smoothScroller = object : LinearSmoothScroller(context!!) {
override fun getVerticalSnapPreference(): Int {
return SNAP_TO_START
}
override fun calculateTimeForScrolling(dx: Int): Int {
return super.calculateTimeForScrolling(dx) * 4
}
}
smoothScroller.targetPosition = i
objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
break
}
}
}
private inner class ObjectivesAdapter : RecyclerView.Adapter<ObjectivesAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.objectives_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val objective = ObjectivesPlugin.objectives[position]
holder.title.text = MainApp.gs(R.string.nth_objective, position + 1)
holder.revert.visibility = View.GONE
if (objective.objective != 0) {
holder.objective.visibility = View.VISIBLE
holder.objective.text = MainApp.gs(objective.objective)
} else
holder.objective.visibility = View.GONE
if (objective.gate != 0) {
holder.gate.visibility = View.VISIBLE
holder.gate.text = MainApp.gs(objective.gate)
} else
holder.gate.visibility = View.GONE
if (!objective.isStarted) {
holder.gate.setTextColor(-0x1)
holder.verify.visibility = View.GONE
holder.progress.visibility = View.GONE
holder.accomplished.visibility = View.GONE
if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished)
holder.start.visibility = View.VISIBLE
else
holder.start.visibility = View.GONE
} else if (objective.isAccomplished) {
holder.gate.setTextColor(-0xb350b0)
holder.verify.visibility = View.GONE
holder.progress.visibility = View.GONE
holder.start.visibility = View.GONE
holder.accomplished.visibility = View.VISIBLE
} else if (objective.isStarted) {
holder.gate.setTextColor(-0x1)
holder.verify.visibility = View.VISIBLE
holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked
holder.start.visibility = View.GONE
holder.accomplished.visibility = View.GONE
if (objective.isRevertable) {
holder.revert.visibility = View.VISIBLE
}
holder.progress.visibility = View.VISIBLE
holder.progress.removeAllViews()
for (task in objective.tasks) {
if (task.shouldBeIgnored()) continue
val name = TextView(holder.progress.context)
name.text = MainApp.gs(task.task) + ":"
name.setTextColor(-0x1)
holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val state = TextView(holder.progress.context)
state.setTextColor(-0x1)
val basicHTML = "<font color=\"%1\$s\"><b>%2\$s</b></font>"
val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress)
state.text = HtmlHelper.fromHtml(formattedHTML)
state.gravity = Gravity.END
holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
val separator = View(holder.progress.context)
separator.setBackgroundColor(Color.DKGRAY)
holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2)
}
}
holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn))
holder.accomplished.setTextColor(-0x3e3e3f)
holder.verify.setOnClickListener {
objective.accomplishedOn = DateUtil.now()
notifyDataSetChanged()
scrollToCurrentObjective()
startUpdateTimer()
}
holder.start.setOnClickListener {
objective.startedOn = DateUtil.now()
notifyDataSetChanged()
scrollToCurrentObjective()
startUpdateTimer()
}
holder.revert.setOnClickListener {
objective.accomplishedOn = 0
objective.startedOn = 0
if (position > 0) {
val prevObj = ObjectivesPlugin.objectives[position - 1]
prevObj.accomplishedOn = 0
}
notifyDataSetChanged()
scrollToCurrentObjective()
}
if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) {
holder.enterButton.visibility = View.VISIBLE
holder.input.visibility = View.VISIBLE
holder.inputHint.visibility = View.VISIBLE
holder.enterButton.setOnClickListener {
val input = holder.input.text.toString()
objective.specialAction(activity, input)
notifyDataSetChanged()
}
} else {
holder.enterButton.visibility = View.GONE
holder.input.visibility = View.GONE
holder.inputHint.visibility = View.GONE
}
}
override fun getItemCount(): Int {
return ObjectivesPlugin.objectives.size
}
inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title: TextView = itemView.findViewById(R.id.objective_title)
val objective: TextView = itemView.findViewById(R.id.objective_objective)
val gate: TextView = itemView.findViewById(R.id.objective_gate)
val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished)
val progress: LinearLayout = itemView.findViewById(R.id.objective_progress)
val verify: Button = itemView.findViewById(R.id.objective_verify)
val start: Button = itemView.findViewById(R.id.objective_start)
val revert: Button = itemView.findViewById(R.id.objective_back)
val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint)
val input: EditText = itemView.findViewById(R.id.objective_input)
val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton)
}
}
fun updateGUI() {
activity?.runOnUiThread { objectivesAdapter.notifyDataSetChanged() }
}
}

View file

@ -20,7 +20,7 @@ import java.util.*
*/
object ObjectivesPlugin : PluginBase(PluginDescription()
.mainType(PluginType.CONSTRAINTS)
.fragmentClass(ObjectivesFragment::class.java.name)
.fragmentClass(ObjectivesFragment::class.qualifiedName)
.alwaysEnabled(!Config.NSCLIENT)
.showInList(!Config.NSCLIENT)
.pluginName(R.string.objectives)
@ -90,13 +90,13 @@ object ObjectivesPlugin : PluginBase(PluginDescription()
SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false)
SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false)
SP.putInt(R.string.key_ObjectivesmanualEnacts, 0)
SP.putBoolean(R.string.key_objectiveuseprofileswitch, false);
SP.putBoolean(R.string.key_objectiveusedisconnect, false);
SP.putBoolean(R.string.key_objectiveusereconnect, false);
SP.putBoolean(R.string.key_objectiveusetemptarget, false);
SP.putBoolean(R.string.key_objectiveuseactions, false);
SP.putBoolean(R.string.key_objectiveuseloop, false);
SP.putBoolean(R.string.key_objectiveusescale, false);
SP.putBoolean(R.string.key_objectiveuseprofileswitch, false)
SP.putBoolean(R.string.key_objectiveusedisconnect, false)
SP.putBoolean(R.string.key_objectiveusereconnect, false)
SP.putBoolean(R.string.key_objectiveusetemptarget, false)
SP.putBoolean(R.string.key_objectiveuseactions, false)
SP.putBoolean(R.string.key_objectiveuseloop, false)
SP.putBoolean(R.string.key_objectiveusescale, false)
}
fun completeObjectives(activity: Activity, request: String) {