TimeListEdit -> kt
This commit is contained in:
parent
3bc62e9a01
commit
971bf87cac
|
@ -1,34 +1,31 @@
|
|||
package info.nightscout.interfaces.profile
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import info.nightscout.interfaces.Constants
|
||||
import org.json.JSONArray
|
||||
|
||||
interface ProfileSource {
|
||||
|
||||
class SingleProfile {
|
||||
|
||||
var name: String? = null
|
||||
var mgdl: Boolean = false
|
||||
var dia: Double = Constants.defaultDIA
|
||||
var ic: JSONArray? = null
|
||||
var isf: JSONArray? = null
|
||||
var basal: JSONArray? = null
|
||||
var targetLow: JSONArray? = null
|
||||
var targetHigh: JSONArray? = null
|
||||
|
||||
fun deepClone(): SingleProfile {
|
||||
val sp = SingleProfile()
|
||||
sp.name = name
|
||||
sp.mgdl = mgdl
|
||||
sp.dia = dia
|
||||
sp.ic = JSONArray(ic.toString())
|
||||
sp.isf = JSONArray(isf.toString())
|
||||
sp.basal = JSONArray(basal.toString())
|
||||
sp.targetLow = JSONArray(targetLow.toString())
|
||||
sp.targetHigh = JSONArray(targetHigh.toString())
|
||||
return sp
|
||||
}
|
||||
class SingleProfile(
|
||||
var name: String,
|
||||
var mgdl: Boolean,
|
||||
var dia: Double,
|
||||
var ic: JSONArray,
|
||||
var isf: JSONArray,
|
||||
var basal: JSONArray,
|
||||
var targetLow: JSONArray,
|
||||
var targetHigh: JSONArray,
|
||||
) {
|
||||
fun deepClone(): SingleProfile =
|
||||
SingleProfile(
|
||||
name = name,
|
||||
mgdl = mgdl,
|
||||
dia = dia,
|
||||
ic = JSONArray(ic.toString()),
|
||||
isf = JSONArray(isf.toString()),
|
||||
basal = JSONArray(basal.toString()),
|
||||
targetLow = JSONArray(targetLow.toString()),
|
||||
targetHigh = JSONArray(targetHigh.toString())
|
||||
)
|
||||
}
|
||||
|
||||
val profile: ProfileStore?
|
||||
|
|
|
@ -33,8 +33,8 @@ import info.nightscout.interfaces.queue.CommandQueue
|
|||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.databinding.ActionsFragmentBinding
|
||||
import info.nightscout.plugins.general.overview.ui.StatusLightHandler
|
||||
import info.nightscout.plugins.skins.SkinProvider
|
||||
import info.nightscout.plugins.ui.StatusLightHandler
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventCustomActionsChanged
|
||||
|
|
|
@ -74,8 +74,8 @@ import info.nightscout.plugins.databinding.OverviewFragmentBinding
|
|||
import info.nightscout.plugins.general.overview.graphData.GraphData
|
||||
import info.nightscout.plugins.general.overview.notifications.NotificationStore
|
||||
import info.nightscout.plugins.general.overview.notifications.events.EventUpdateOverviewNotification
|
||||
import info.nightscout.plugins.general.overview.ui.StatusLightHandler
|
||||
import info.nightscout.plugins.skins.SkinProvider
|
||||
import info.nightscout.plugins.ui.StatusLightHandler
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventAcceptOpenLoopChange
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.plugins.ui
|
||||
package info.nightscout.plugins.general.overview.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Handler
|
|
@ -27,7 +27,7 @@ import info.nightscout.interfaces.utils.DecimalFormatter
|
|||
import info.nightscout.interfaces.utils.HardLimits
|
||||
import info.nightscout.plugins.R
|
||||
import info.nightscout.plugins.databinding.ProfileFragmentBinding
|
||||
import info.nightscout.plugins.ui.TimeListEdit
|
||||
import info.nightscout.plugins.profile.ui.TimeListEdit
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
import info.nightscout.rx.bus.RxBus
|
||||
import info.nightscout.rx.events.EventLocalProfileChanged
|
||||
|
@ -139,10 +139,10 @@ class ProfileFragment : DaggerFragment() {
|
|||
binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch)
|
||||
binding.dia.tag = "LP_DIA"
|
||||
TimeListEdit(
|
||||
context,
|
||||
requireContext(),
|
||||
aapsLogger,
|
||||
dateUtil,
|
||||
view,
|
||||
requireView(),
|
||||
R.id.ic_holder,
|
||||
"IC",
|
||||
rh.gs(info.nightscout.core.ui.R.string.ic_long_label),
|
||||
|
@ -156,10 +156,10 @@ class ProfileFragment : DaggerFragment() {
|
|||
)
|
||||
basalView =
|
||||
TimeListEdit(
|
||||
context,
|
||||
requireContext(),
|
||||
aapsLogger,
|
||||
dateUtil,
|
||||
view,
|
||||
requireView(),
|
||||
R.id.basal_holder,
|
||||
"BASAL",
|
||||
rh.gs(info.nightscout.core.ui.R.string.basal_long_label) + ": " + sumLabel(),
|
||||
|
@ -173,12 +173,27 @@ class ProfileFragment : DaggerFragment() {
|
|||
)
|
||||
if (units == Constants.MGDL) {
|
||||
val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(info.nightscout.core.ui.R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 1.0, DecimalFormat("0"), save)
|
||||
TimeListEdit(
|
||||
context,
|
||||
requireContext(),
|
||||
aapsLogger,
|
||||
dateUtil,
|
||||
view,
|
||||
requireView(),
|
||||
R.id.isf_holder,
|
||||
"ISF",
|
||||
rh.gs(info.nightscout.core.ui.R.string.isf_long_label),
|
||||
currentProfile.isf,
|
||||
null,
|
||||
isfRange,
|
||||
null,
|
||||
1.0,
|
||||
DecimalFormat("0"),
|
||||
save
|
||||
)
|
||||
TimeListEdit(
|
||||
requireContext(),
|
||||
aapsLogger,
|
||||
dateUtil,
|
||||
requireView(),
|
||||
R.id.target_holder,
|
||||
"TARGET",
|
||||
rh.gs(info.nightscout.core.ui.R.string.target_long_label),
|
||||
|
@ -195,7 +210,9 @@ class ProfileFragment : DaggerFragment() {
|
|||
roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
|
||||
roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL))
|
||||
)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(info.nightscout.core.ui.R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 0.1, DecimalFormat("0.0"), save)
|
||||
TimeListEdit(requireContext(), aapsLogger, dateUtil, requireView(), R.id.isf_holder, "ISF", rh.gs(info.nightscout.core.ui.R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 0.1,
|
||||
DecimalFormat
|
||||
("0.0"), save)
|
||||
val range1 = doubleArrayOf(
|
||||
roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)),
|
||||
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL))
|
||||
|
@ -206,10 +223,10 @@ class ProfileFragment : DaggerFragment() {
|
|||
)
|
||||
aapsLogger.info(LTag.CORE, "TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1])
|
||||
TimeListEdit(
|
||||
context,
|
||||
requireContext(),
|
||||
aapsLogger,
|
||||
dateUtil,
|
||||
view,
|
||||
requireView(),
|
||||
R.id.target_holder,
|
||||
"TARGET",
|
||||
rh.gs(info.nightscout.core.ui.R.string.target_long_label),
|
||||
|
|
|
@ -99,7 +99,7 @@ class ProfilePlugin @Inject constructor(
|
|||
ToastUtils.errorToast(activity, rh.gs(info.nightscout.core.ui.R.string.value_out_of_hard_limits, rh.gs(info.nightscout.core.ui.R.string.profile_dia), dia))
|
||||
return false
|
||||
}
|
||||
if (name.isNullOrEmpty()) {
|
||||
if (name.isEmpty()) {
|
||||
ToastUtils.errorToast(activity, rh.gs(R.string.missing_profile_name))
|
||||
return false
|
||||
}
|
||||
|
@ -177,7 +177,6 @@ class ProfilePlugin @Inject constructor(
|
|||
override fun storeSettings(activity: FragmentActivity?) {
|
||||
for (i in 0 until numOfProfiles) {
|
||||
profiles[i].run {
|
||||
name?.let { name ->
|
||||
val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_"
|
||||
sp.putString(localProfileNumbered + "name", name)
|
||||
sp.putBoolean(localProfileNumbered + "mgdl", mgdl)
|
||||
|
@ -187,7 +186,6 @@ class ProfilePlugin @Inject constructor(
|
|||
sp.putString(localProfileNumbered + "basal", basal.toString())
|
||||
sp.putString(localProfileNumbered + "targetlow", targetLow.toString())
|
||||
sp.putString(localProfileNumbered + "targethigh", targetHigh.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
sp.putInt(Constants.LOCAL_PROFILE + "_profiles", numOfProfiles)
|
||||
|
@ -198,10 +196,7 @@ class ProfilePlugin @Inject constructor(
|
|||
aapsLogger.debug(LTag.PROFILE, "Storing settings: " + rawProfile?.data.toString())
|
||||
rxBus.send(EventProfileStoreChanged())
|
||||
var namesOK = true
|
||||
profiles.forEach {
|
||||
val name = it.name ?: "."
|
||||
if (name.contains(".")) namesOK = false
|
||||
}
|
||||
profiles.forEach { if (it.name.contains(".")) namesOK = false }
|
||||
if (!namesOK) activity?.let {
|
||||
OKDialog.show(it, "", rh.gs(R.string.profile_name_contains_dot))
|
||||
}
|
||||
|
@ -214,20 +209,22 @@ class ProfilePlugin @Inject constructor(
|
|||
// numOfProfiles = max(numOfProfiles, 1) // create at least one default profile if none exists
|
||||
|
||||
for (i in 0 until numOfProfiles) {
|
||||
val p = ProfileSource.SingleProfile()
|
||||
val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_"
|
||||
|
||||
p.name = sp.getString(localProfileNumbered + "name", Constants.LOCAL_PROFILE + i)
|
||||
if (isExistingName(p.name)) continue
|
||||
p.mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false)
|
||||
p.dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA)
|
||||
val name = sp.getString(localProfileNumbered + "name", Constants.LOCAL_PROFILE + i)
|
||||
if (isExistingName(name)) continue
|
||||
try {
|
||||
p.ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray))
|
||||
p.isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray))
|
||||
p.basal = JSONArray(sp.getString(localProfileNumbered + "basal", defaultArray))
|
||||
p.targetLow = JSONArray(sp.getString(localProfileNumbered + "targetlow", defaultArray))
|
||||
p.targetHigh = JSONArray(sp.getString(localProfileNumbered + "targethigh", defaultArray))
|
||||
profiles.add(p)
|
||||
profiles.add(
|
||||
ProfileSource.SingleProfile(
|
||||
name = name,
|
||||
mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false),
|
||||
dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA),
|
||||
ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)),
|
||||
isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)),
|
||||
basal = JSONArray(sp.getString(localProfileNumbered + "basal", defaultArray)),
|
||||
targetLow = JSONArray(sp.getString(localProfileNumbered + "targetlow", defaultArray)),
|
||||
targetHigh = JSONArray(sp.getString(localProfileNumbered + "targethigh", defaultArray))
|
||||
)
|
||||
)
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Exception", e)
|
||||
}
|
||||
|
@ -279,16 +276,16 @@ class ProfilePlugin @Inject constructor(
|
|||
}
|
||||
val profile = ProfileSealed.Pure(pureProfile)
|
||||
val pureJson = pureProfile.jsonObject
|
||||
val sp = ProfileSource.SingleProfile()
|
||||
sp.name = verifiedName
|
||||
sp.mgdl = profile.units == GlucoseUnit.MGDL
|
||||
sp.dia = pureJson.getDouble("dia")
|
||||
sp.ic = pureJson.getJSONArray("carbratio")
|
||||
sp.isf = pureJson.getJSONArray("sens")
|
||||
sp.basal = pureJson.getJSONArray("basal")
|
||||
sp.targetLow = pureJson.getJSONArray("target_low")
|
||||
sp.targetHigh = pureJson.getJSONArray("target_high")
|
||||
return sp
|
||||
return ProfileSource.SingleProfile(
|
||||
name = verifiedName,
|
||||
mgdl = profile.units == GlucoseUnit.MGDL,
|
||||
dia = pureJson.getDouble("dia"),
|
||||
ic = pureJson.getJSONArray("carbratio"),
|
||||
isf = pureJson.getJSONArray("sens"),
|
||||
basal = pureJson.getJSONArray("basal"),
|
||||
targetLow = pureJson.getJSONArray("target_low"),
|
||||
targetHigh = pureJson.getJSONArray("target_high")
|
||||
)
|
||||
}
|
||||
|
||||
private fun isExistingName(name: String?): Boolean {
|
||||
|
@ -348,16 +345,18 @@ class ProfilePlugin @Inject constructor(
|
|||
break
|
||||
}
|
||||
}
|
||||
val p = ProfileSource.SingleProfile()
|
||||
p.name = Constants.LOCAL_PROFILE + free
|
||||
p.mgdl = profileFunction.getUnits() == GlucoseUnit.MGDL
|
||||
p.dia = Constants.defaultDIA
|
||||
p.ic = JSONArray(defaultArray)
|
||||
p.isf = JSONArray(defaultArray)
|
||||
p.basal = JSONArray(defaultArray)
|
||||
p.targetLow = JSONArray(defaultArray)
|
||||
p.targetHigh = JSONArray(defaultArray)
|
||||
profiles.add(p)
|
||||
profiles.add(
|
||||
ProfileSource.SingleProfile(
|
||||
name = Constants.LOCAL_PROFILE + free,
|
||||
mgdl = profileFunction.getUnits() == GlucoseUnit.MGDL,
|
||||
dia = Constants.defaultDIA,
|
||||
ic = JSONArray(defaultArray),
|
||||
isf = JSONArray(defaultArray),
|
||||
basal = JSONArray(defaultArray),
|
||||
targetLow = JSONArray(defaultArray),
|
||||
targetHigh = JSONArray(defaultArray)
|
||||
)
|
||||
)
|
||||
currentProfileIndex = profiles.size - 1
|
||||
createAndStoreConvertedProfile()
|
||||
storeSettings()
|
||||
|
@ -397,18 +396,16 @@ class ProfilePlugin @Inject constructor(
|
|||
try {
|
||||
for (i in 0 until numOfProfiles) {
|
||||
profiles[i].run {
|
||||
name?.let { name ->
|
||||
val profile = JSONObject()
|
||||
profile.put("dia", dia)
|
||||
profile.put("carbratio", ic)
|
||||
profile.put("sens", isf)
|
||||
profile.put("basal", basal)
|
||||
profile.put("target_low", targetLow)
|
||||
profile.put("target_high", targetHigh)
|
||||
profile.put("units", if (mgdl) Constants.MGDL else Constants.MMOL)
|
||||
profile.put("timezone", TimeZone.getDefault().id)
|
||||
store.put(name, profile)
|
||||
}
|
||||
val profile = JSONObject()
|
||||
profile.put("dia", dia)
|
||||
profile.put("carbratio", ic)
|
||||
profile.put("sens", isf)
|
||||
profile.put("basal", basal)
|
||||
profile.put("target_low", targetLow)
|
||||
profile.put("target_high", targetHigh)
|
||||
profile.put("units", if (mgdl) Constants.MGDL else Constants.MMOL)
|
||||
profile.put("timezone", TimeZone.getDefault().id)
|
||||
store.put(name, profile)
|
||||
}
|
||||
}
|
||||
if (numOfProfiles > 0) json.put("defaultProfile", currentProfile()?.name)
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
package info.nightscout.plugins.profile.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import info.nightscout.core.ui.elements.NumberPicker
|
||||
import info.nightscout.core.ui.elements.SpinnerHelper
|
||||
import info.nightscout.rx.logging.AAPSLogger
|
||||
import info.nightscout.shared.SafeParse.stringToDouble
|
||||
import info.nightscout.shared.utils.DateUtil
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.text.DecimalFormat
|
||||
import java.text.NumberFormat
|
||||
|
||||
class TimeListEdit(
|
||||
private val context: Context,
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val dateUtil: DateUtil,
|
||||
private val view: View,
|
||||
private val resLayoutId: Int,
|
||||
private val tagPrefix: String,
|
||||
private var label: String,
|
||||
private val data1: JSONArray,
|
||||
private val data2: JSONArray?,
|
||||
range1: DoubleArray,
|
||||
range2: DoubleArray?,
|
||||
private val step: Double,
|
||||
formatter: NumberFormat,
|
||||
save: Runnable?
|
||||
) {
|
||||
|
||||
private val intervals = arrayOfNulls<View>(24)
|
||||
private val spinners = arrayOfNulls<SpinnerHelper>(24)
|
||||
private val numberPickers1 = arrayOfNulls<NumberPicker>(24)
|
||||
private val numberPickers2 = arrayOfNulls<NumberPicker>(24)
|
||||
private val addButtons = arrayOfNulls<ImageView>(24)
|
||||
private val removeButtons = arrayOfNulls<ImageView>(24)
|
||||
private var finalAdd: ImageView? = null
|
||||
private val min: Double
|
||||
private val max: Double
|
||||
private val min2: Double
|
||||
private val max2: Double
|
||||
private val formatter: NumberFormat
|
||||
private val save: Runnable?
|
||||
private var layout: LinearLayout? = null
|
||||
private var textLabel: TextView? = null
|
||||
private var inflatedUntil = -1
|
||||
|
||||
init {
|
||||
min = range1[0]
|
||||
max = range1[1]
|
||||
min2 = range2?.get(0) ?: 0.0
|
||||
max2 = range2?.get(1) ?: 0.0
|
||||
this.formatter = formatter
|
||||
this.save = save
|
||||
buildView()
|
||||
}
|
||||
|
||||
private fun buildView() {
|
||||
val layout = view.findViewById<LinearLayout>(resLayoutId).also {
|
||||
this.layout = it
|
||||
it.removeAllViewsInLayout()
|
||||
} ?: return
|
||||
TextView(context).also {
|
||||
this.textLabel = it
|
||||
it.text = label
|
||||
it.gravity = Gravity.CENTER
|
||||
it.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also { llp ->
|
||||
llp.setMargins(0, 5, 0, 5)
|
||||
}
|
||||
TextViewCompat.setTextAppearance(it, android.R.style.TextAppearance_Medium)
|
||||
layout.addView(it)
|
||||
}
|
||||
var i = 0
|
||||
while (i < 24 && i < itemsCount()) {
|
||||
inflateRow(i)
|
||||
inflatedUntil = i
|
||||
i++
|
||||
}
|
||||
|
||||
// last "plus" to append new interval
|
||||
val factor = layout.context.resources.displayMetrics.density
|
||||
ImageView(context).also {
|
||||
this.finalAdd = it
|
||||
it.setImageResource(info.nightscout.core.main.R.drawable.ic_add)
|
||||
it.contentDescription = layout.context.resources.getString(info.nightscout.plugins.R.string.a11y_add_new_to_list)
|
||||
layout.addView(it)
|
||||
it.layoutParams = LinearLayout.LayoutParams((35.0 * factor).toInt(), (35 * factor).toInt()).also { llp ->
|
||||
llp.setMargins(0, 25, 0, 25) // llp.setMargins(left, top, right, bottom);
|
||||
llp.gravity = Gravity.CENTER
|
||||
}
|
||||
it.setOnClickListener {
|
||||
addItem(itemsCount(), if (itemsCount() > 0) secondFromMidnight(itemsCount() - 1) + ONE_HOUR_IN_SECONDS else 0)
|
||||
callSave()
|
||||
log()
|
||||
fillView()
|
||||
}
|
||||
}
|
||||
fillView()
|
||||
}
|
||||
|
||||
private fun inflateRow(position: Int) {
|
||||
val resource =
|
||||
if (data2 == null) info.nightscout.plugins.R.layout.timelistedit_element
|
||||
else info.nightscout.plugins.R.layout.timelistedit_element_vertical
|
||||
val childView = LayoutInflater.from(context).inflate(resource, layout, false).also {
|
||||
intervals[position] = it
|
||||
layout?.addView(it)
|
||||
}
|
||||
childView.findViewById<ImageView>(info.nightscout.plugins.R.id.timelistedit_add).also {
|
||||
addButtons[position] = it
|
||||
it.setOnClickListener {
|
||||
val seconds = secondFromMidnight(position)
|
||||
addItem(position, seconds)
|
||||
// for here for the rest of values
|
||||
for (i in position + 1 until itemsCount()) {
|
||||
if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) {
|
||||
editItem(i, secondFromMidnight(i - 1) + ONE_HOUR_IN_SECONDS, value1(i), value2(i))
|
||||
}
|
||||
}
|
||||
while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONE_HOUR_IN_SECONDS) removeItem(itemsCount() - 1)
|
||||
callSave()
|
||||
log()
|
||||
fillView()
|
||||
}
|
||||
}
|
||||
childView.findViewById<ImageView>(info.nightscout.plugins.R.id.timelistedit_remove).also {
|
||||
removeButtons[position] = it
|
||||
it.setOnClickListener {
|
||||
removeItem(position)
|
||||
callSave()
|
||||
log()
|
||||
fillView()
|
||||
}
|
||||
}
|
||||
SpinnerHelper(childView.findViewById(info.nightscout.plugins.R.id.timelistedit_time)).also {
|
||||
spinners[position] = it
|
||||
it.setOnItemSelectedListener(
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View, selected: Int, id: Long) {
|
||||
val seconds = (it.adapter as SpinnerAdapter).valueForPosition(selected)
|
||||
editItem(position, seconds, value1(position), value2(position))
|
||||
log()
|
||||
callSave()
|
||||
fillView()
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
)
|
||||
}
|
||||
childView.findViewById<NumberPicker>(info.nightscout.plugins.R.id.timelistedit_edit1).also {
|
||||
numberPickers1[position] = it
|
||||
it.setTextWatcher(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val value1 = stringToDouble(it.text, 0.0)
|
||||
var value2 = value2(position)
|
||||
if (data2 != null && value1 > value2) {
|
||||
value2 = value1
|
||||
numberPickers2[position]?.value = value2
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2)
|
||||
callSave()
|
||||
log()
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
})
|
||||
it.tag = "$tagPrefix-1-$position"
|
||||
}
|
||||
childView.findViewById<NumberPicker>(info.nightscout.plugins.R.id.timelistedit_edit2).also {
|
||||
numberPickers2[position] = it
|
||||
it.setTextWatcher(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
var value1 = value1(position)
|
||||
val value2 = stringToDouble(it.text, 0.0)
|
||||
if (data2 != null && value2 < value1) {
|
||||
value1 = value2
|
||||
numberPickers1[position]?.value = value1
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2)
|
||||
callSave()
|
||||
log()
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
})
|
||||
it.tag = "$tagPrefix-2-$position"
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillView() {
|
||||
for (i in 0..23) {
|
||||
if (i < itemsCount()) {
|
||||
intervals[i]?.visibility = View.VISIBLE
|
||||
buildInterval(i)
|
||||
} else if (i <= inflatedUntil) {
|
||||
intervals[i]?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
finalAdd?.visibility =
|
||||
if (!(itemsCount() > 0 && secondFromMidnight(itemsCount() - 1) == 23 * ONE_HOUR_IN_SECONDS)) View.VISIBLE
|
||||
else View.GONE
|
||||
}
|
||||
|
||||
private fun buildInterval(i: Int) {
|
||||
val timeSpinner = spinners[i] ?: return
|
||||
val editText1 = numberPickers1[i] ?: return
|
||||
val editText2 = numberPickers2[i] ?: return
|
||||
val previous = if (i == 0) -1 * ONE_HOUR_IN_SECONDS else secondFromMidnight(i - 1)
|
||||
var next = if (i == itemsCount() - 1) 24 * ONE_HOUR_IN_SECONDS else secondFromMidnight(i + 1)
|
||||
if (i == 0) next = ONE_HOUR_IN_SECONDS
|
||||
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next)
|
||||
editText1.setParams(value1(i), min, max, step, formatter, false, null)
|
||||
editText2.setParams(value2(i), min2, max2, step, formatter, false, null)
|
||||
if (data2 == null) {
|
||||
editText2.visibility = View.GONE
|
||||
}
|
||||
removeButtons[i]?.visibility =
|
||||
if (itemsCount() == 1 || i == 0) View.INVISIBLE
|
||||
else View.VISIBLE
|
||||
addButtons[i]?.visibility =
|
||||
if (itemsCount() >= 24 || secondFromMidnight(i) >= 82800) View.INVISIBLE
|
||||
else View.VISIBLE
|
||||
}
|
||||
|
||||
internal class SpinnerAdapter(context: Context, resource: Int, objects: List<CharSequence>, var values: List<Int>) : ArrayAdapter<CharSequence?>(context, resource, objects) {
|
||||
|
||||
fun valueForPosition(position: Int): Int = values[position]
|
||||
}
|
||||
|
||||
private fun fillSpinner(spinner: SpinnerHelper, secondsFromMidnight: Int, previous: Int, next: Int) {
|
||||
var posInList = 0
|
||||
val timeList = ArrayList<CharSequence>()
|
||||
val timeListValues = ArrayList<Int>()
|
||||
var pos = 0
|
||||
var t = previous + ONE_HOUR_IN_SECONDS
|
||||
while (t < next) {
|
||||
timeList.add(dateUtil.timeStringFromSeconds(t))
|
||||
timeListValues.add(t)
|
||||
if (secondsFromMidnight == t) posInList = pos
|
||||
pos++
|
||||
t += ONE_HOUR_IN_SECONDS
|
||||
}
|
||||
val adapter = SpinnerAdapter(
|
||||
context,
|
||||
info.nightscout.core.ui.R.layout.spinner_centered, timeList, timeListValues
|
||||
)
|
||||
spinner.adapter = adapter
|
||||
spinner.setSelection(posInList, false)
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun itemsCount(): Int {
|
||||
return data1.length()
|
||||
}
|
||||
|
||||
private fun secondFromMidnight(index: Int): Int {
|
||||
try {
|
||||
val item = data1[index] as JSONObject
|
||||
if (item.has("timeAsSeconds")) {
|
||||
var time = item.getInt("timeAsSeconds")
|
||||
if (index == 0 && time != 0) {
|
||||
// fix the bug, every array must start with 0
|
||||
item.put("timeAsSeconds", 0)
|
||||
time = 0
|
||||
}
|
||||
return time
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun value1(index: Int): Double {
|
||||
try {
|
||||
val item = data1[index] as JSONObject
|
||||
if (item.has("value")) {
|
||||
return item.getDouble("value")
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
private fun value2(index: Int): Double {
|
||||
if (data2 != null) {
|
||||
try {
|
||||
val item = data2[index] as JSONObject
|
||||
if (item.has("value")) {
|
||||
return item.getDouble("value")
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
private fun editItem(index: Int, timeAsSeconds: Int, value1: Double, value2: Double) {
|
||||
try {
|
||||
val time: String
|
||||
val hour = timeAsSeconds / 60 / 60
|
||||
val df = DecimalFormat("00")
|
||||
time = df.format(hour.toLong()) + ":00"
|
||||
val newObject1 = JSONObject()
|
||||
newObject1.put("time", time)
|
||||
newObject1.put("timeAsSeconds", timeAsSeconds)
|
||||
newObject1.put("value", value1)
|
||||
data1.put(index, newObject1)
|
||||
if (data2 != null) {
|
||||
val newObject2 = JSONObject()
|
||||
newObject2.put("time", time)
|
||||
newObject2.put("timeAsSeconds", timeAsSeconds)
|
||||
newObject2.put("value", value2)
|
||||
data2.put(index, newObject2)
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addItem(index: Int, timeAsSeconds: Int) {
|
||||
if (itemsCount() >= 24) return
|
||||
if (itemsCount() > inflatedUntil) {
|
||||
layout?.removeView(finalAdd)
|
||||
inflateRow(++inflatedUntil)
|
||||
layout?.addView(finalAdd)
|
||||
}
|
||||
try {
|
||||
// shift data
|
||||
for (i in data1.length() downTo index + 1) {
|
||||
data1.put(i, data1[i - 1])
|
||||
data2?.put(i, data2[i - 1])
|
||||
}
|
||||
// add new object
|
||||
editItem(index, timeAsSeconds, 0.0, 0.0)
|
||||
} catch (e: JSONException) {
|
||||
aapsLogger.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeItem(index: Int) {
|
||||
data1.remove(index)
|
||||
data2?.remove(index)
|
||||
}
|
||||
|
||||
private fun log() {
|
||||
for (i in 0 until data1.length()) {
|
||||
aapsLogger.debug(i.toString() + ": @" + dateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + if (data2 != null) " " + value2(i) else "")
|
||||
}
|
||||
}
|
||||
|
||||
private fun callSave() {
|
||||
save?.run()
|
||||
}
|
||||
|
||||
fun updateLabel(txt: String) {
|
||||
label = txt
|
||||
textLabel?.text = txt
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ONE_HOUR_IN_SECONDS = 60 * 60
|
||||
}
|
||||
}
|
|
@ -1,437 +0,0 @@
|
|||
package info.nightscout.plugins.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.widget.TextViewCompat;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.core.ui.elements.NumberPicker;
|
||||
import info.nightscout.core.ui.elements.SpinnerHelper;
|
||||
import info.nightscout.plugins.R;
|
||||
import info.nightscout.rx.logging.AAPSLogger;
|
||||
import info.nightscout.shared.SafeParse;
|
||||
import info.nightscout.shared.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 29.12.2016.
|
||||
*/
|
||||
|
||||
public class TimeListEdit {
|
||||
private final AAPSLogger aapsLogger;
|
||||
private final DateUtil dateUtil;
|
||||
|
||||
private final int ONEHOURINSECONDS = 60 * 60;
|
||||
|
||||
private final View[] intervals = new View[24];
|
||||
private final SpinnerHelper[] spinners = new SpinnerHelper[24];
|
||||
private final NumberPicker[] numberPickers1 = new NumberPicker[24];
|
||||
private final NumberPicker[] numberPickers2 = new NumberPicker[24];
|
||||
private final ImageView[] addButtons = new ImageView[24];
|
||||
private final ImageView[] removeButtons = new ImageView[24];
|
||||
private ImageView finalAdd;
|
||||
|
||||
private final Context context;
|
||||
private final View view;
|
||||
private final int resLayoutId;
|
||||
private final String tagPrefix;
|
||||
private String label;
|
||||
private final JSONArray data1;
|
||||
private final JSONArray data2;
|
||||
private final double step;
|
||||
private final double min;
|
||||
private final double max;
|
||||
private final double min2;
|
||||
private final double max2;
|
||||
private final NumberFormat formatter;
|
||||
private final Runnable save;
|
||||
private LinearLayout layout;
|
||||
private TextView textlabel;
|
||||
private int inflatedUntil = -1;
|
||||
|
||||
|
||||
public TimeListEdit(
|
||||
Context context,
|
||||
AAPSLogger aapsLogger,
|
||||
DateUtil dateUtil,
|
||||
View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double[] range1, double[] range2, double step, NumberFormat formatter, Runnable save) {
|
||||
this.context = context;
|
||||
this.aapsLogger = aapsLogger;
|
||||
this.dateUtil = dateUtil;
|
||||
this.view = view;
|
||||
this.resLayoutId = resLayoutId;
|
||||
this.tagPrefix = tagPrefix;
|
||||
this.label = label;
|
||||
this.data1 = data1;
|
||||
this.data2 = data2;
|
||||
this.step = step;
|
||||
this.min = range1[0];
|
||||
this.max = range1[1];
|
||||
this.min2 = range2 != null ? range2[0] : 0;
|
||||
this.max2 = range2 != null ? range2[1] : 0;
|
||||
this.formatter = formatter;
|
||||
this.save = save;
|
||||
buildView();
|
||||
}
|
||||
|
||||
private void buildView() {
|
||||
layout = view.findViewById(resLayoutId);
|
||||
layout.removeAllViewsInLayout();
|
||||
|
||||
textlabel = new TextView(context);
|
||||
textlabel.setText(label);
|
||||
textlabel.setGravity(Gravity.CENTER);
|
||||
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
llp.setMargins(0, 5, 0, 5);
|
||||
textlabel.setLayoutParams(llp);
|
||||
TextViewCompat.setTextAppearance(textlabel, android.R.style.TextAppearance_Medium);
|
||||
layout.addView(textlabel);
|
||||
|
||||
for (int i = 0; i < 24 && i < itemsCount(); i++) {
|
||||
inflateRow(i);
|
||||
inflatedUntil = i;
|
||||
}
|
||||
|
||||
// last "plus" to append new interval
|
||||
float factor = layout.getContext().getResources().getDisplayMetrics().density;
|
||||
finalAdd = new ImageView(context);
|
||||
finalAdd.setImageResource(info.nightscout.core.main.R.drawable.ic_add);
|
||||
finalAdd.setContentDescription(layout.getContext().getResources().getString(R.string.a11y_add_new_to_list));
|
||||
LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor));
|
||||
illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
|
||||
illp.gravity = Gravity.CENTER;
|
||||
layout.addView(finalAdd);
|
||||
finalAdd.setLayoutParams(illp);
|
||||
finalAdd.setOnClickListener(view -> {
|
||||
addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0);
|
||||
callSave();
|
||||
log();
|
||||
fillView();
|
||||
});
|
||||
|
||||
fillView();
|
||||
}
|
||||
|
||||
private void inflateRow(final int position) {
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
int resource = data2 == null ? R.layout.timelistedit_element : R.layout.timelistedit_element_vertical;
|
||||
View childView = intervals[position] = inflater.inflate(resource, layout, false);
|
||||
spinners[position] = new SpinnerHelper(childView.findViewById(R.id.timelistedit_time));
|
||||
numberPickers1[position] = childView.findViewById(R.id.timelistedit_edit1);
|
||||
numberPickers2[position] = childView.findViewById(R.id.timelistedit_edit2);
|
||||
addButtons[position] = childView.findViewById(R.id.timelistedit_add);
|
||||
removeButtons[position] = childView.findViewById(R.id.timelistedit_remove);
|
||||
|
||||
addButtons[position].setOnClickListener(view -> {
|
||||
int seconds = secondFromMidnight(position);
|
||||
addItem(position, seconds, 0, 0);
|
||||
// for here for the rest of values
|
||||
for (int i = position + 1; i < itemsCount(); i++) {
|
||||
if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) {
|
||||
editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i));
|
||||
}
|
||||
}
|
||||
while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS)
|
||||
removeItem(itemsCount() - 1);
|
||||
callSave();
|
||||
log();
|
||||
fillView();
|
||||
});
|
||||
|
||||
removeButtons[position].setOnClickListener(view -> {
|
||||
removeItem(position);
|
||||
callSave();
|
||||
log();
|
||||
fillView();
|
||||
});
|
||||
|
||||
spinners[position].setOnItemSelectedListener(
|
||||
new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int selected, long id) {
|
||||
int seconds = ((SpinnerAdapter) spinners[position].getAdapter()).valueForPosition(selected);
|
||||
editItem(position, seconds, value1(position), value2(position));
|
||||
log();
|
||||
callSave();
|
||||
fillView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
numberPickers1[position].setTextWatcher(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
Double value1 = SafeParse.INSTANCE.stringToDouble(numberPickers1[position].getText(), 0.0);
|
||||
Double value2 = value2(position);
|
||||
if (data2 != null && value1 > value2) {
|
||||
value2 = value1;
|
||||
numberPickers2[position].setValue(value2);
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2);
|
||||
callSave();
|
||||
log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start,
|
||||
int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start,
|
||||
int before, int count) {
|
||||
}
|
||||
});
|
||||
numberPickers1[position].setTag(tagPrefix + "-1-" + position);
|
||||
|
||||
numberPickers2[position].setTextWatcher(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
Double value1 = value1(position);
|
||||
Double value2 = SafeParse.INSTANCE.stringToDouble(numberPickers2[position].getText(), 0.0);
|
||||
if (data2 != null && value2 < value1) {
|
||||
value1 = value2;
|
||||
numberPickers1[position].setValue(value1);
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2);
|
||||
callSave();
|
||||
log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start,
|
||||
int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start,
|
||||
int before, int count) {
|
||||
}
|
||||
});
|
||||
numberPickers2[position].setTag(tagPrefix + "-2-" + position);
|
||||
|
||||
layout.addView(childView);
|
||||
}
|
||||
|
||||
private void fillView() {
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (i < itemsCount()) {
|
||||
intervals[i].setVisibility(View.VISIBLE);
|
||||
buildInterval(i);
|
||||
} else if (i <= inflatedUntil) {
|
||||
intervals[i].setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(itemsCount() > 0 && secondFromMidnight(itemsCount() - 1) == 23 * ONEHOURINSECONDS)) {
|
||||
finalAdd.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
finalAdd.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildInterval(int i) {
|
||||
SpinnerHelper timeSpinner = spinners[i];
|
||||
final NumberPicker editText1 = numberPickers1[i];
|
||||
final NumberPicker editText2 = numberPickers2[i];
|
||||
|
||||
|
||||
int previous = i == 0 ? -1 * ONEHOURINSECONDS : secondFromMidnight(i - 1);
|
||||
int next = i == itemsCount() - 1 ? 24 * ONEHOURINSECONDS : secondFromMidnight(i + 1);
|
||||
if (i == 0) next = ONEHOURINSECONDS;
|
||||
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
|
||||
|
||||
editText1.setParams(value1(i), min, max, step, formatter, false, null);
|
||||
editText2.setParams(value2(i), min2, max2, step, formatter, false, null);
|
||||
|
||||
if (data2 == null) {
|
||||
editText2.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
if (itemsCount() == 1 || i == 0) {
|
||||
removeButtons[i].setVisibility(View.INVISIBLE);
|
||||
} else
|
||||
removeButtons[i].setVisibility(View.VISIBLE);
|
||||
|
||||
if (itemsCount() >= 24 || secondFromMidnight(i) >= 82800) {
|
||||
addButtons[i].setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
addButtons[i].setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class SpinnerAdapter extends ArrayAdapter<CharSequence> {
|
||||
List<Integer> values;
|
||||
|
||||
SpinnerAdapter(@NonNull Context context, int resource, final @NonNull List<CharSequence> objects, final @NonNull List<Integer> values) {
|
||||
super(context, resource, objects);
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
int valueForPosition(int position) {
|
||||
return values.get(position);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillSpinner(final SpinnerHelper spinner, int secondsFromMidnight, int previous, int next) {
|
||||
int posInList = 0;
|
||||
ArrayList<CharSequence> timeList = new ArrayList<>();
|
||||
ArrayList<Integer> timeListValues = new ArrayList<>();
|
||||
int pos = 0;
|
||||
for (int t = previous + ONEHOURINSECONDS; t < next; t += ONEHOURINSECONDS) {
|
||||
timeList.add(dateUtil.timeStringFromSeconds(t));
|
||||
timeListValues.add(t);
|
||||
if (secondsFromMidnight == t) posInList = pos;
|
||||
pos++;
|
||||
}
|
||||
|
||||
final SpinnerAdapter adapter = new SpinnerAdapter(context,
|
||||
info.nightscout.core.ui.R.layout.spinner_centered, timeList, timeListValues);
|
||||
spinner.setAdapter(adapter);
|
||||
spinner.setSelection(posInList, false);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private int itemsCount() {
|
||||
return data1.length();
|
||||
}
|
||||
|
||||
private int secondFromMidnight(int index) {
|
||||
try {
|
||||
JSONObject item = (JSONObject) data1.get(index);
|
||||
if (item.has("timeAsSeconds")) {
|
||||
int time = item.getInt("timeAsSeconds");
|
||||
if (index == 0 && time != 0) {
|
||||
// fix the bug, every array must start with 0
|
||||
item.put("timeAsSeconds", 0);
|
||||
time = 0;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private double value1(int index) {
|
||||
try {
|
||||
JSONObject item = (JSONObject) data1.get(index);
|
||||
if (item.has("value")) {
|
||||
return item.getDouble("value");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
return 0d;
|
||||
}
|
||||
|
||||
private double value2(int index) {
|
||||
if (data2 != null) {
|
||||
try {
|
||||
JSONObject item = (JSONObject) data2.get(index);
|
||||
if (item.has("value")) {
|
||||
return item.getDouble("value");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
return 0d;
|
||||
}
|
||||
|
||||
private void editItem(int index, int timeAsSeconds, double value1, double value2) {
|
||||
try {
|
||||
String time;
|
||||
int hour = timeAsSeconds / 60 / 60;
|
||||
DecimalFormat df = new DecimalFormat("00");
|
||||
time = df.format(hour) + ":00";
|
||||
|
||||
JSONObject newObject1 = new JSONObject();
|
||||
newObject1.put("time", time);
|
||||
newObject1.put("timeAsSeconds", timeAsSeconds);
|
||||
newObject1.put("value", value1);
|
||||
data1.put(index, newObject1);
|
||||
if (data2 != null) {
|
||||
JSONObject newObject2 = new JSONObject();
|
||||
newObject2.put("time", time);
|
||||
newObject2.put("timeAsSeconds", timeAsSeconds);
|
||||
newObject2.put("value", value2);
|
||||
data2.put(index, newObject2);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private void addItem(int index, int timeAsSeconds, double value1, double value2) {
|
||||
if (itemsCount() >= 24) return;
|
||||
if (itemsCount() > inflatedUntil) {
|
||||
layout.removeView(finalAdd);
|
||||
inflateRow(++inflatedUntil);
|
||||
layout.addView(finalAdd);
|
||||
}
|
||||
try {
|
||||
// shift data
|
||||
for (int i = data1.length(); i > index; i--) {
|
||||
data1.put(i, data1.get(i - 1));
|
||||
if (data2 != null)
|
||||
data2.put(i, data2.get(i - 1));
|
||||
}
|
||||
// add new object
|
||||
editItem(index, timeAsSeconds, value1, value2);
|
||||
} catch (JSONException e) {
|
||||
aapsLogger.error("Unhandled exception", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeItem(int index) {
|
||||
data1.remove(index);
|
||||
if (data2 != null)
|
||||
data2.remove(index);
|
||||
}
|
||||
|
||||
private void log() {
|
||||
for (int i = 0; i < data1.length(); i++) {
|
||||
aapsLogger.debug(i + ": @" + dateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : ""));
|
||||
}
|
||||
}
|
||||
|
||||
private void callSave() {
|
||||
if (save != null) save.run();
|
||||
}
|
||||
|
||||
public void updateLabel(String txt) {
|
||||
this.label = txt;
|
||||
if (textlabel != null)
|
||||
textlabel.setText(txt);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue