AUTO: user actions & new layout
This commit is contained in:
parent
04a104a9b0
commit
a56bdcc7c8
|
@ -12,11 +12,6 @@ import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragm
|
||||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||||
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment
|
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment
|
||||||
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment
|
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseActionDialog
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditActionDialog
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditTriggerDialog
|
|
||||||
import info.nightscout.androidaps.plugins.general.food.FoodFragment
|
import info.nightscout.androidaps.plugins.general.food.FoodFragment
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenanceFragment
|
import info.nightscout.androidaps.plugins.general.maintenance.MaintenanceFragment
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientFragment
|
import info.nightscout.androidaps.plugins.general.nsclient.NSClientFragment
|
||||||
|
@ -30,6 +25,7 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment
|
||||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
|
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
|
||||||
import info.nightscout.androidaps.plugins.source.BGSourceFragment
|
import info.nightscout.androidaps.plugins.source.BGSourceFragment
|
||||||
import info.nightscout.androidaps.activities.fragments.*
|
import info.nightscout.androidaps.activities.fragments.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.*
|
||||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -81,6 +77,7 @@ abstract class FragmentsModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog
|
@ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog
|
||||||
@ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog
|
@ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog
|
||||||
@ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog
|
@ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog
|
||||||
|
@ContributesAndroidInjector abstract fun contributesChooseOperationDialog(): ChooseOperationDialog
|
||||||
@ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog
|
@ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog
|
||||||
@ContributesAndroidInjector abstract fun contributesLoopDialog(): LoopDialog
|
@ContributesAndroidInjector abstract fun contributesLoopDialog(): LoopDialog
|
||||||
@ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog
|
@ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog
|
||||||
|
|
|
@ -12,6 +12,7 @@ import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnLongClickListener
|
import android.view.View.OnLongClickListener
|
||||||
|
@ -49,6 +50,7 @@ import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverview
|
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverview
|
||||||
|
@ -72,6 +74,7 @@ import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import info.nightscout.androidaps.utils.ui.SingleClickButton
|
||||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
@ -118,6 +121,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
|
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
|
||||||
@Inject lateinit var overviewData: OverviewData
|
@Inject lateinit var overviewData: OverviewData
|
||||||
@Inject lateinit var overviewPlugin: OverviewPlugin
|
@Inject lateinit var overviewPlugin: OverviewPlugin
|
||||||
|
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
@ -459,6 +463,32 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
binding.buttonsLayout.calibrationButton.visibility = ((xDripIsBgSource || dexcomIsSource) && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
|
binding.buttonsLayout.calibrationButton.visibility = ((xDripIsBgSource || dexcomIsSource) && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
|
||||||
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
|
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
|
||||||
|
|
||||||
|
// Automation buttons
|
||||||
|
binding.buttonsLayout.userButtonsLayout.removeAllViews()
|
||||||
|
val events = automationPlugin.userEvents()
|
||||||
|
for (event in events)
|
||||||
|
if (event.isEnabled && event.trigger.shouldRun())
|
||||||
|
context?.let { context ->
|
||||||
|
SingleClickButton(context).also {
|
||||||
|
it.setTextColor(resourceHelper.gc(R.color.colorTreatmentButton))
|
||||||
|
it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f)
|
||||||
|
it.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.5f).also { l ->
|
||||||
|
l.setMargins(0, 0, resourceHelper.dpToPx(-4), 0)
|
||||||
|
}
|
||||||
|
it.setCompoundDrawablesWithIntrinsicBounds(null, resourceHelper.gd(R.drawable.ic_danar_useropt), null, null)
|
||||||
|
it.text = event.title
|
||||||
|
|
||||||
|
it.setOnClickListener {
|
||||||
|
OKDialog.showConfirmation(
|
||||||
|
context,
|
||||||
|
resourceHelper.gs(R.string.run_question, event.title),
|
||||||
|
{ handler.post { automationPlugin.processEvent(event, true) } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
binding.buttonsLayout.userButtonsLayout.addView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.buttonsLayout.userButtonsLayout.visibility = events.isNotEmpty().toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processAps() {
|
private fun processAps() {
|
||||||
|
|
|
@ -18,6 +18,16 @@
|
||||||
android:textColor="@color/colorAcceptTempButton"
|
android:textColor="@color/colorAcceptTempButton"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/user_buttons_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="5dp" >
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/buttons_layout"
|
android:id="@+id/buttons_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
<color name="error_background">#66FC0000</color>
|
<color name="error_background">#66FC0000</color>
|
||||||
<color name="ok_background">#323232</color>
|
<color name="ok_background">#323232</color>
|
||||||
|
|
||||||
<color name="defaultbackground">#424242</color>
|
|
||||||
<color name="defaulttextcolor">#B3FFFFFF</color>
|
|
||||||
|
|
||||||
<color name="tempTargetBackground">#77dd77</color>
|
<color name="tempTargetBackground">#77dd77</color>
|
||||||
<color name="exercise">#67DFE8</color>
|
<color name="exercise">#67DFE8</color>
|
||||||
|
|
||||||
|
|
|
@ -1124,5 +1124,6 @@
|
||||||
<string name="error_in_basal_values">Error in basal values</string>
|
<string name="error_in_basal_values">Error in basal values</string>
|
||||||
<string name="error_in_target_values">Error in target values</string>
|
<string name="error_in_target_values">Error in target values</string>
|
||||||
<string name="error_in_isf_values">Error in ISF values</string>
|
<string name="error_in_isf_values">Error in ISF values</string>
|
||||||
|
<string name="run_question">Run %s?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.ActionDummy
|
import info.nightscout.androidaps.plugins.general.automation.actions.ActionDummy
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
@ -24,8 +23,9 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
||||||
var systemAction: Boolean = false // true = generated by AAPS, false = entered by user
|
var systemAction: Boolean = false // true = generated by AAPS, false = entered by user
|
||||||
var readOnly: Boolean = false // removing, editing disabled
|
var readOnly: Boolean = false // removing, editing disabled
|
||||||
var autoRemove: Boolean = false // auto-remove once used
|
var autoRemove: Boolean = false // auto-remove once used
|
||||||
|
var userAction: Boolean = false // shows button on Overview
|
||||||
|
|
||||||
var trigger: Trigger = TriggerConnector(injector)
|
var trigger: TriggerConnector = TriggerConnector(injector)
|
||||||
val actions: MutableList<Action> = ArrayList()
|
val actions: MutableList<Action> = ArrayList()
|
||||||
|
|
||||||
var lastRun: Long = 0
|
var lastRun: Long = 0
|
||||||
|
@ -44,7 +44,7 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
||||||
|
|
||||||
fun addAction(action: Action) = actions.add(action)
|
fun addAction(action: Action) = actions.add(action)
|
||||||
|
|
||||||
fun areActionsValid() : Boolean {
|
fun areActionsValid(): Boolean {
|
||||||
var result = true
|
var result = true
|
||||||
for (action in actions) result = result && action.isValid()
|
for (action in actions) result = result && action.isValid()
|
||||||
return result
|
return result
|
||||||
|
@ -59,6 +59,7 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
||||||
.put("systemAction", systemAction)
|
.put("systemAction", systemAction)
|
||||||
.put("readOnly", readOnly)
|
.put("readOnly", readOnly)
|
||||||
.put("autoRemove", autoRemove)
|
.put("autoRemove", autoRemove)
|
||||||
|
.put("userAction", userAction)
|
||||||
.put("trigger", trigger.toJSON())
|
.put("trigger", trigger.toJSON())
|
||||||
.put("actions", array)
|
.put("actions", array)
|
||||||
.toString()
|
.toString()
|
||||||
|
@ -71,7 +72,8 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
||||||
systemAction = d.optBoolean("systemAction", false)
|
systemAction = d.optBoolean("systemAction", false)
|
||||||
readOnly = d.optBoolean("readOnly", false)
|
readOnly = d.optBoolean("readOnly", false)
|
||||||
autoRemove = d.optBoolean("autoRemove", false)
|
autoRemove = d.optBoolean("autoRemove", false)
|
||||||
trigger = TriggerDummy(injector).instantiate(JSONObject(d.getString("trigger")))
|
userAction = d.optBoolean("userAction", false)
|
||||||
|
trigger = TriggerDummy(injector).instantiate(JSONObject(d.getString("trigger"))) as TriggerConnector
|
||||||
val array = d.getJSONArray("actions")
|
val array = d.getJSONArray("actions")
|
||||||
actions.clear()
|
actions.clear()
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
|
|
|
@ -100,14 +100,14 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
.toObservable(EventAutomationUpdateGui::class.java)
|
.toObservable(EventAutomationUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
updateGui()
|
updateGui()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAutomationDataChanged::class.java)
|
.toObservable(EventAutomationDataChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
eventListAdapter.notifyDataSetChanged()
|
eventListAdapter.notifyDataSetChanged()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
updateGui()
|
updateGui()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,14 +167,19 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val event = automationPlugin.at(position)
|
val event = automationPlugin.at(position)
|
||||||
holder.binding.rootLayout.setBackgroundColor(resourceHelper.gc(if (event.areActionsValid()) R.color.ribbonDefault else R.color.errorAlertBackground))
|
holder.binding.rootLayout.setBackgroundColor(resourceHelper.gc(
|
||||||
|
if (event.userAction) R.color.mdtp_line_dark
|
||||||
|
else if (event.areActionsValid()) R.color.ribbonDefault
|
||||||
|
else R.color.errorAlertBackground)
|
||||||
|
)
|
||||||
holder.binding.eventTitle.text = event.title
|
holder.binding.eventTitle.text = event.title
|
||||||
holder.binding.enabled.isChecked = event.isEnabled
|
holder.binding.enabled.isChecked = event.isEnabled
|
||||||
holder.binding.enabled.isEnabled = !event.readOnly
|
holder.binding.enabled.isEnabled = !event.readOnly
|
||||||
holder.binding.iconLayout.removeAllViews()
|
holder.binding.iconLayout.removeAllViews()
|
||||||
// trigger icons
|
// trigger icons
|
||||||
val triggerIcons = HashSet<Int>()
|
val triggerIcons = HashSet<Int>()
|
||||||
fillIconSet(event.trigger as TriggerConnector, triggerIcons)
|
if (event.userAction) triggerIcons.add(R.drawable.ic_danar_useropt)
|
||||||
|
fillIconSet(event.trigger, triggerIcons)
|
||||||
for (res in triggerIcons) {
|
for (res in triggerIcons) {
|
||||||
addImage(res, holder.context, holder.binding.iconLayout)
|
addImage(res, holder.context, holder.binding.iconLayout)
|
||||||
}
|
}
|
||||||
|
@ -217,13 +222,13 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
// remove event
|
// remove event
|
||||||
holder.binding.iconTrash.setOnClickListener {
|
holder.binding.iconTrash.setOnClickListener {
|
||||||
OKDialog.showConfirmation(requireContext(), resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
OKDialog.showConfirmation(requireContext(), resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
||||||
{
|
{
|
||||||
uel.log(Action.AUTOMATION_REMOVED, Sources.Automation, automationPlugin.at(position).title)
|
uel.log(Action.AUTOMATION_REMOVED, Sources.Automation, automationPlugin.at(position).title)
|
||||||
automationPlugin.removeAt(position)
|
automationPlugin.removeAt(position)
|
||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
}, {
|
}, {
|
||||||
rxBus.send(EventAutomationUpdateGui())
|
rxBus.send(EventAutomationUpdateGui())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
holder.binding.iconTrash.visibility = (!event.readOnly).toVisibility()
|
holder.binding.iconTrash.visibility = (!event.readOnly).toVisibility()
|
||||||
holder.binding.aapsLogo.visibility = (event.systemAction).toVisibility()
|
holder.binding.aapsLogo.visibility = (event.systemAction).toVisibility()
|
||||||
|
@ -239,13 +244,15 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
||||||
|
|
||||||
override fun onItemDismiss(position: Int) {
|
override fun onItemDismiss(position: Int) {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
OKDialog.showConfirmation(
|
||||||
Runnable {
|
activity,
|
||||||
|
resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
||||||
|
{
|
||||||
uel.log(Action.AUTOMATION_REMOVED, Sources.Automation, automationPlugin.at(position).title)
|
uel.log(Action.AUTOMATION_REMOVED, Sources.Automation, automationPlugin.at(position).title)
|
||||||
automationPlugin.removeAt(position)
|
automationPlugin.removeAt(position)
|
||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
rxBus.send(EventAutomationDataChanged())
|
rxBus.send(EventAutomationDataChanged())
|
||||||
}, Runnable { rxBus.send(EventAutomationUpdateGui()) })
|
}, { rxBus.send(EventAutomationUpdateGui()) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,17 +55,18 @@ class AutomationPlugin @Inject constructor(
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val locationServiceHelper: LocationServiceHelper,
|
private val locationServiceHelper: LocationServiceHelper,
|
||||||
private val dateUtil: DateUtil
|
private val dateUtil: DateUtil
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(
|
||||||
.mainType(PluginType.GENERAL)
|
PluginDescription()
|
||||||
.fragmentClass(AutomationFragment::class.qualifiedName)
|
.mainType(PluginType.GENERAL)
|
||||||
.pluginIcon(R.drawable.ic_automation)
|
.fragmentClass(AutomationFragment::class.qualifiedName)
|
||||||
.pluginName(R.string.automation)
|
.pluginIcon(R.drawable.ic_automation)
|
||||||
.shortName(R.string.automation_short)
|
.pluginName(R.string.automation)
|
||||||
.showInList(config.APS)
|
.shortName(R.string.automation_short)
|
||||||
.neverVisible(!config.APS)
|
.showInList(config.APS)
|
||||||
.alwaysEnabled(!config.APS)
|
.neverVisible(!config.APS)
|
||||||
.preferencesId(R.xml.pref_automation)
|
.alwaysEnabled(!config.APS)
|
||||||
.description(R.string.automation_description),
|
.preferencesId(R.xml.pref_automation)
|
||||||
|
.description(R.string.automation_description),
|
||||||
aapsLogger, resourceHelper, injector
|
aapsLogger, resourceHelper, injector
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -82,7 +83,8 @@ class AutomationPlugin @Inject constructor(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val event = "{\"title\":\"Low\",\"enabled\":true,\"trigger\":\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\",\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\\\\\\\",\\\\\\\"data\\\\\\\":{\\\\\\\"bg\\\\\\\":4,\\\\\\\"comparator\\\\\\\":\\\\\\\"IS_LESSER\\\\\\\",\\\\\\\"units\\\\\\\":\\\\\\\"mmol\\\\\\\"}}\\\",\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDelta\\\\\\\",\\\\\\\"data\\\\\\\":{\\\\\\\"value\\\\\\\":-0.1,\\\\\\\"units\\\\\\\":\\\\\\\"mmol\\\\\\\",\\\\\\\"deltaType\\\\\\\":\\\\\\\"DELTA\\\\\\\",\\\\\\\"comparator\\\\\\\":\\\\\\\"IS_LESSER\\\\\\\"}}\\\"]}}\",\"actions\":[\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.actions.ActionStartTempTarget\\\",\\\"data\\\":{\\\"value\\\":8,\\\"units\\\":\\\"mmol\\\",\\\"durationInMinutes\\\":60}}\"]}"
|
const val event =
|
||||||
|
"{\"title\":\"Low\",\"enabled\":true,\"trigger\":\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector\\\",\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\\\\\\\",\\\\\\\"data\\\\\\\":{\\\\\\\"bg\\\\\\\":4,\\\\\\\"comparator\\\\\\\":\\\\\\\"IS_LESSER\\\\\\\",\\\\\\\"units\\\\\\\":\\\\\\\"mmol\\\\\\\"}}\\\",\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDelta\\\\\\\",\\\\\\\"data\\\\\\\":{\\\\\\\"value\\\\\\\":-0.1,\\\\\\\"units\\\\\\\":\\\\\\\"mmol\\\\\\\",\\\\\\\"deltaType\\\\\\\":\\\\\\\"DELTA\\\\\\\",\\\\\\\"comparator\\\\\\\":\\\\\\\"IS_LESSER\\\\\\\"}}\\\"]}}\",\"actions\":[\"{\\\"type\\\":\\\"info.nightscout.androidaps.plugins.general.automation.actions.ActionStartTempTarget\\\",\\\"data\\\":{\\\"value\\\":8,\\\"units\\\":\\\"mmol\\\",\\\"durationInMinutes\\\":60}}\"]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -103,11 +105,11 @@ class AutomationPlugin @Inject constructor(
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ e ->
|
.subscribe({ e ->
|
||||||
if (e.isChanged(resourceHelper, R.string.key_location)) {
|
if (e.isChanged(resourceHelper, R.string.key_location)) {
|
||||||
locationServiceHelper.stopService(context)
|
locationServiceHelper.stopService(context)
|
||||||
locationServiceHelper.startService(context)
|
locationServiceHelper.startService(context)
|
||||||
}
|
}
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAutomationDataChanged::class.java)
|
.toObservable(EventAutomationDataChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
|
@ -116,11 +118,11 @@ class AutomationPlugin @Inject constructor(
|
||||||
.toObservable(EventLocationChange::class.java)
|
.toObservable(EventLocationChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ e ->
|
.subscribe({ e ->
|
||||||
e?.let {
|
e?.let {
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider")
|
aapsLogger.debug(LTag.AUTOMATION, "Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider")
|
||||||
processActions()
|
processActions()
|
||||||
}
|
}
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventChargingState::class.java)
|
.toObservable(EventChargingState::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
|
@ -137,10 +139,10 @@ class AutomationPlugin @Inject constructor(
|
||||||
.toObservable(EventBTChange::class.java)
|
.toObservable(EventBTChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "Grabbed new BT event: $it")
|
aapsLogger.debug(LTag.AUTOMATION, "Grabbed new BT event: $it")
|
||||||
btConnects.add(it)
|
btConnects.add(it)
|
||||||
processActions()
|
processActions()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
@ -201,40 +203,8 @@ class AutomationPlugin @Inject constructor(
|
||||||
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
val event = iterator.next()
|
val event = iterator.next()
|
||||||
if (event.isEnabled && event.shouldRun() && event.trigger.shouldRun() && event.getPreconditions().shouldRun()) {
|
if (event.isEnabled && !event.userAction && event.shouldRun())
|
||||||
if (event.systemAction || userEventsEnabled) {
|
processEvent(event, userEventsEnabled)
|
||||||
val actions = event.actions
|
|
||||||
for (action in actions) {
|
|
||||||
action.title = event.title
|
|
||||||
if (action.isValid())
|
|
||||||
action.doAction(object : Callback() {
|
|
||||||
override fun run() {
|
|
||||||
val sb = StringBuilder()
|
|
||||||
sb.append(dateUtil.timeString(dateUtil.now()))
|
|
||||||
sb.append(" ")
|
|
||||||
sb.append(if (result.success) "☺" else "▼")
|
|
||||||
sb.append(" <b>")
|
|
||||||
sb.append(event.title)
|
|
||||||
sb.append(":</b> ")
|
|
||||||
sb.append(action.shortDescription())
|
|
||||||
sb.append(": ")
|
|
||||||
sb.append(result.comment)
|
|
||||||
executionLog.add(sb.toString())
|
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "Executed: $sb")
|
|
||||||
rxBus.send(EventAutomationUpdateGui())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
else {
|
|
||||||
executionLog.add("Invalid action: ${action.shortDescription()}")
|
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "Invalid action: ${action.shortDescription()}")
|
|
||||||
rxBus.send(EventAutomationUpdateGui())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SystemClock.sleep(1100)
|
|
||||||
event.lastRun = dateUtil.now()
|
|
||||||
if (event.autoRemove) automationEvents.remove(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// we cannot detect connected BT devices
|
// we cannot detect connected BT devices
|
||||||
// so let's collect all connection/disconnections between 2 runs of processActions()
|
// so let's collect all connection/disconnections between 2 runs of processActions()
|
||||||
|
@ -245,6 +215,43 @@ class AutomationPlugin @Inject constructor(
|
||||||
storeToSP() // save last run time
|
storeToSP() // save last run time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun processEvent(event: AutomationEvent, userEventsEnabled: Boolean) {
|
||||||
|
if (event.trigger.shouldRun() && event.getPreconditions().shouldRun()) {
|
||||||
|
if (event.systemAction || userEventsEnabled) {
|
||||||
|
val actions = event.actions
|
||||||
|
for (action in actions) {
|
||||||
|
action.title = event.title
|
||||||
|
if (action.isValid())
|
||||||
|
action.doAction(object : Callback() {
|
||||||
|
override fun run() {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
sb.append(dateUtil.timeString(dateUtil.now()))
|
||||||
|
sb.append(" ")
|
||||||
|
sb.append(if (result.success) "☺" else "▼")
|
||||||
|
sb.append(" <b>")
|
||||||
|
sb.append(event.title)
|
||||||
|
sb.append(":</b> ")
|
||||||
|
sb.append(action.shortDescription())
|
||||||
|
sb.append(": ")
|
||||||
|
sb.append(result.comment)
|
||||||
|
executionLog.add(sb.toString())
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Executed: $sb")
|
||||||
|
rxBus.send(EventAutomationUpdateGui())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else {
|
||||||
|
executionLog.add("Invalid action: ${action.shortDescription()}")
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Invalid action: ${action.shortDescription()}")
|
||||||
|
rxBus.send(EventAutomationUpdateGui())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemClock.sleep(1100)
|
||||||
|
event.lastRun = dateUtil.now()
|
||||||
|
if (event.autoRemove) automationEvents.remove(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun add(event: AutomationEvent) {
|
fun add(event: AutomationEvent) {
|
||||||
automationEvents.add(event)
|
automationEvents.add(event)
|
||||||
|
@ -283,6 +290,16 @@ class AutomationPlugin @Inject constructor(
|
||||||
rxBus.send(EventAutomationDataChanged())
|
rxBus.send(EventAutomationDataChanged())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun userEvents(): List<AutomationEvent> {
|
||||||
|
val list = mutableListOf<AutomationEvent>()
|
||||||
|
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val event = iterator.next()
|
||||||
|
if (event.userAction) list.add(event)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
fun getActionDummyObjects(): List<Action> {
|
fun getActionDummyObjects(): List<Action> {
|
||||||
return listOf(
|
return listOf(
|
||||||
//ActionLoopDisable(injector),
|
//ActionLoopDisable(injector),
|
||||||
|
@ -318,7 +335,7 @@ class AutomationPlugin @Inject constructor(
|
||||||
TriggerAutosensValue(injector),
|
TriggerAutosensValue(injector),
|
||||||
TriggerBolusAgo(injector),
|
TriggerBolusAgo(injector),
|
||||||
TriggerPumpLastConnection(injector),
|
TriggerPumpLastConnection(injector),
|
||||||
TriggerBTDevice(injector)
|
TriggerBTDevice(injector),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.RadioButton
|
||||||
|
import info.nightscout.androidaps.automation.databinding.AutomationDialogChooseOperationBinding
|
||||||
|
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ChooseOperationDialog : DialogFragmentWithDate() {
|
||||||
|
|
||||||
|
@Inject lateinit var resourceHelper: ResourceHelper
|
||||||
|
|
||||||
|
private var checkedIndex = -1
|
||||||
|
|
||||||
|
private var _binding: AutomationDialogChooseOperationBinding? = null
|
||||||
|
|
||||||
|
// This property is only valid between onCreateView and
|
||||||
|
// onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
abstract class Callback : Runnable {
|
||||||
|
|
||||||
|
var result: Int? = null
|
||||||
|
fun result(result: Int?): Callback {
|
||||||
|
this.result = result
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var callback: Callback? = null
|
||||||
|
|
||||||
|
fun setCallback(callback: Callback): ChooseOperationDialog {
|
||||||
|
this.callback = callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCheckedIndex(checkedIndex: Int): ChooseOperationDialog {
|
||||||
|
this.checkedIndex = checkedIndex
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
// restore checked radio button
|
||||||
|
savedInstanceState?.let { bundle ->
|
||||||
|
checkedIndex = bundle.getInt("checkedIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateViewGeneral()
|
||||||
|
_binding = AutomationDialogChooseOperationBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
for (t in TriggerConnector.Type.labels(resourceHelper)) {
|
||||||
|
val radioButton = RadioButton(context)
|
||||||
|
radioButton.text = t
|
||||||
|
binding.chooseOperationRadioGroup.addView(radioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkedIndex != -1)
|
||||||
|
(binding.chooseOperationRadioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun submit(): Boolean {
|
||||||
|
callback?.result(determineCheckedIndex())?.run()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
super.onSaveInstanceState(savedInstanceState)
|
||||||
|
savedInstanceState.putInt("checkedIndex", determineCheckedIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun determineCheckedIndex(): Int {
|
||||||
|
for (i in 0 until binding.chooseOperationRadioGroup.childCount) {
|
||||||
|
if ((binding.chooseOperationRadioGroup.getChildAt(i) as RadioButton).isChecked)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.automation.databinding.AutomationDialogEventBinding
|
import info.nightscout.androidaps.automation.databinding.AutomationDialogEventBinding
|
||||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
|
@ -22,13 +23,11 @@ import info.nightscout.androidaps.plugins.general.automation.events.EventAutomat
|
||||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
|
||||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class EditEventDialog : DialogFragmentWithDate() {
|
class EditEventDialog : DialogFragmentWithDate() {
|
||||||
|
@ -73,6 +72,8 @@ class EditEventDialog : DialogFragmentWithDate() {
|
||||||
binding.inputEventTitle.setText(event.title)
|
binding.inputEventTitle.setText(event.title)
|
||||||
binding.inputEventTitle.isFocusable = !event.readOnly
|
binding.inputEventTitle.isFocusable = !event.readOnly
|
||||||
binding.triggerDescription.text = event.trigger.friendlyDescription()
|
binding.triggerDescription.text = event.trigger.friendlyDescription()
|
||||||
|
binding.userAction.isChecked = event.userAction
|
||||||
|
binding.enabled.isChecked = event.isEnabled
|
||||||
|
|
||||||
binding.editTrigger.visibility = (!event.readOnly).toVisibility()
|
binding.editTrigger.visibility = (!event.readOnly).toVisibility()
|
||||||
binding.editTrigger.setOnClickListener {
|
binding.editTrigger.setOnClickListener {
|
||||||
|
@ -131,9 +132,11 @@ class EditEventDialog : DialogFragmentWithDate() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
event.title = title
|
event.title = title
|
||||||
|
event.userAction = binding.userAction.isChecked
|
||||||
|
event.isEnabled = binding.enabled.isChecked
|
||||||
// check for at least one trigger
|
// check for at least one trigger
|
||||||
val con = event.trigger as TriggerConnector
|
val con = event.trigger
|
||||||
if (con.size() == 0) {
|
if (con.size() == 0 && !event.userAction) {
|
||||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
private var triggers: Trigger? = null
|
private var triggers: TriggerConnector? = null
|
||||||
|
|
||||||
private var _binding: AutomationDialogEditTriggerBinding? = null
|
private var _binding: AutomationDialogEditTriggerBinding? = null
|
||||||
|
|
||||||
|
@ -39,11 +39,13 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(
|
||||||
savedInstanceState: Bundle?): View {
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
// load data from bundle
|
// load data from bundle
|
||||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
bundle.getString("trigger")?.let { triggers = TriggerDummy(injector).instantiate(JSONObject(it)) }
|
bundle.getString("trigger")?.let { triggers = TriggerDummy(injector).instantiate(JSONObject(it)) as TriggerConnector }
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
|
@ -58,26 +60,26 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
||||||
.toObservable(EventTriggerChanged::class.java)
|
.toObservable(EventTriggerChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
binding.layoutTrigger.removeAllViews()
|
binding.layoutTrigger.removeAllViews()
|
||||||
triggers?.generateDialog(binding.layoutTrigger)
|
triggers?.generateDialog(binding.layoutTrigger)
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTriggerRemove::class.java)
|
.toObservable(EventTriggerRemove::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
findParent(triggers, it.trigger)?.list?.remove(it.trigger)
|
findParent(triggers, it.trigger)?.list?.remove(it.trigger)
|
||||||
binding.layoutTrigger.removeAllViews()
|
binding.layoutTrigger.removeAllViews()
|
||||||
triggers?.generateDialog(binding.layoutTrigger)
|
triggers?.generateDialog(binding.layoutTrigger)
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTriggerClone::class.java)
|
.toObservable(EventTriggerClone::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
findParent(triggers, it.trigger)?.list?.add(it.trigger.duplicate())
|
findParent(triggers, it.trigger)?.list?.add(it.trigger.duplicate())
|
||||||
binding.layoutTrigger.removeAllViews()
|
binding.layoutTrigger.removeAllViews()
|
||||||
triggers?.generateDialog(binding.layoutTrigger)
|
triggers?.generateDialog(binding.layoutTrigger)
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
|
|
||||||
// display root trigger
|
// display root trigger
|
||||||
triggers?.generateDialog(binding.layoutTrigger)
|
triggers?.generateDialog(binding.layoutTrigger)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
@ -42,6 +43,7 @@ class Comparator(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (c in values()) {
|
for (c in values()) {
|
||||||
|
@ -59,25 +61,24 @@ class Comparator(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
var value = Compare.IS_EQUAL
|
var value = Compare.IS_EQUAL
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
Spinner(root.context).apply {
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = spinnerArrayAdapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(
|
}
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
setMargins(0, resourceHelper.dpToPx(1), 0, resourceHelper.dpToPx(1))
|
||||||
)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
spinner.layoutParams = spinnerParams
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
value = Compare.values()[position]
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
}
|
||||||
value = Compare.values()[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
spinner.setSelection(value.ordinal)
|
setSelection(value.ordinal)
|
||||||
root.addView(spinner)
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setValue(compare: Compare): Comparator {
|
fun setValue(compare: Compare): Comparator {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
@ -16,11 +17,12 @@ class ComparatorConnect(private val resourceHelper: ResourceHelper) : Element()
|
||||||
|
|
||||||
@get:StringRes val stringRes: Int
|
@get:StringRes val stringRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
ON_CONNECT -> R.string.onconnect
|
ON_CONNECT -> R.string.onconnect
|
||||||
ON_DISCONNECT -> R.string.ondisconnect
|
ON_DISCONNECT -> R.string.ondisconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
|
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
|
||||||
|
@ -36,21 +38,24 @@ class ComparatorConnect(private val resourceHelper: ResourceHelper) : Element()
|
||||||
var value = Compare.ON_CONNECT
|
var value = Compare.ON_CONNECT
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
Spinner(root.context).apply {
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = spinnerArrayAdapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
|
||||||
spinner.layoutParams = spinnerParams
|
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
value = Compare.values()[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
}
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
spinner.setSelection(value.ordinal)
|
}
|
||||||
root.addView(spinner)
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
|
value = Compare.values()[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
setSelection(value.ordinal)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
@ -16,11 +17,12 @@ class ComparatorExists(private val resourceHelper: ResourceHelper, var value: Co
|
||||||
|
|
||||||
@get:StringRes val stringRes: Int
|
@get:StringRes val stringRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
EXISTS -> R.string.exists
|
EXISTS -> R.string.exists
|
||||||
NOT_EXISTS -> R.string.notexists
|
NOT_EXISTS -> R.string.notexists
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
|
for (c in values()) list.add(resourceHelper.gs(c.stringRes))
|
||||||
|
@ -30,21 +32,24 @@ class ComparatorExists(private val resourceHelper: ResourceHelper, var value: Co
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
Spinner(root.context).apply {
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = spinnerArrayAdapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
spinner.layoutParams = spinnerParams
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
}
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
value = Compare.values()[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
}
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
spinner.setSelection(value.ordinal)
|
value = Compare.values()[position]
|
||||||
root.addView(spinner)
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
setSelection(value.ordinal)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||||
|
@ -26,13 +27,15 @@ class InputBg(profileFunction: ProfileFunction) : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val numberPicker = NumberPicker(root.context, null)
|
root.addView(
|
||||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, false, root.findViewById(R.id.ok))
|
NumberPicker(root.context, null).apply {
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
setParams(value, minValue, maxValue, step, decimalFormat, false, root.findViewById(R.id.ok))
|
||||||
root.addView(numberPicker)
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setValue(value: Double) : InputBg {
|
fun setValue(value: Double): InputBg {
|
||||||
this.value = value
|
this.value = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
@ -54,6 +57,7 @@ class InputBg(profileFunction: ProfileFunction) : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val MMOL_MIN = 3.0
|
const val MMOL_MIN = 3.0
|
||||||
const val MMOL_MAX = 20.0
|
const val MMOL_MAX = 20.0
|
||||||
const val MGDL_MIN = 54.0
|
const val MGDL_MIN = 54.0
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
||||||
class InputButton() : Element() {
|
class InputButton() : Element() {
|
||||||
|
|
||||||
var text: String? = null
|
var text: String? = null
|
||||||
var runnable: Runnable? = null
|
var runnable: Runnable? = null
|
||||||
|
|
||||||
|
@ -13,9 +15,11 @@ class InputButton() : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val button = Button(root.context)
|
root.addView(
|
||||||
button.text = text
|
Button(root.context).apply {
|
||||||
button.setOnClickListener { runnable?.run() }
|
text = text
|
||||||
root.addView(button)
|
setOnClickListener { runnable?.run() }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,51 +1,50 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.Spinner
|
import android.widget.Spinner
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.LayoutRes
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
|
||||||
class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element() {
|
class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
|
|
||||||
enum class EventType (val therapyEventType: TherapyEvent.Type) {
|
enum class EventType(val therapyEventType: TherapyEvent.Type) {
|
||||||
NOTE (TherapyEvent.Type.NOTE),
|
NOTE(TherapyEvent.Type.NOTE),
|
||||||
EXERCISE (TherapyEvent.Type.EXERCISE),
|
EXERCISE(TherapyEvent.Type.EXERCISE),
|
||||||
QUESTION (TherapyEvent.Type.QUESTION),
|
QUESTION(TherapyEvent.Type.QUESTION),
|
||||||
ANNOUNCEMENT (TherapyEvent.Type.ANNOUNCEMENT);
|
ANNOUNCEMENT(TherapyEvent.Type.ANNOUNCEMENT);
|
||||||
|
|
||||||
@get:StringRes val stringResWithValue: Int
|
@get:StringRes val stringResWithValue: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
NOTE -> R.string.careportal_note_message
|
NOTE -> R.string.careportal_note_message
|
||||||
EXERCISE -> R.string.careportal_exercise_message
|
EXERCISE -> R.string.careportal_exercise_message
|
||||||
QUESTION -> R.string.careportal_question_message
|
QUESTION -> R.string.careportal_question_message
|
||||||
ANNOUNCEMENT -> R.string.careportal_announcement_message
|
ANNOUNCEMENT -> R.string.careportal_announcement_message
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:StringRes val stringRes: Int
|
@get:StringRes val stringRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
NOTE -> R.string.careportal_note
|
NOTE -> R.string.careportal_note
|
||||||
EXERCISE -> R.string.careportal_exercise
|
EXERCISE -> R.string.careportal_exercise
|
||||||
QUESTION -> R.string.careportal_question
|
QUESTION -> R.string.careportal_question
|
||||||
ANNOUNCEMENT -> R.string.careportal_announcement
|
ANNOUNCEMENT -> R.string.careportal_announcement
|
||||||
}
|
}
|
||||||
@get:DrawableRes val drawableRes: Int
|
@get:DrawableRes val drawableRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
NOTE -> R.drawable.ic_cp_note
|
NOTE -> R.drawable.ic_cp_note
|
||||||
EXERCISE -> R.drawable.ic_cp_exercise
|
EXERCISE -> R.drawable.ic_cp_exercise
|
||||||
QUESTION -> R.drawable.ic_cp_question
|
QUESTION -> R.drawable.ic_cp_question
|
||||||
ANNOUNCEMENT -> R.drawable.ic_cp_announcement
|
ANNOUNCEMENT -> R.drawable.ic_cp_announcement
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (e in values()) {
|
for (e in values()) {
|
||||||
|
@ -63,25 +62,25 @@ class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element(
|
||||||
var value = EventType.NOTE
|
var value = EventType.NOTE
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, EventType.labels(resourceHelper))
|
Spinner(root.context).apply {
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, EventType.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = spinnerArrayAdapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(
|
}
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
|
||||||
spinner.layoutParams = spinnerParams
|
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
value = EventType.values()[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
}
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
spinner.setSelection(value.ordinal)
|
value = EventType.values()[position]
|
||||||
root.addView(spinner)
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
setSelection(value.ordinal)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setValue(eventType: EventType): InputCarePortalMenu {
|
fun setValue(eventType: EventType): InputCarePortalMenu {
|
||||||
|
|
|
@ -15,71 +15,71 @@ import java.util.*
|
||||||
class InputDateTime(private val resourceHelper: ResourceHelper, private val dateUtil: DateUtil, var value: Long = dateUtil.now()) : Element() {
|
class InputDateTime(private val resourceHelper: ResourceHelper, private val dateUtil: DateUtil, var value: Long = dateUtil.now()) : Element() {
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val label = TextView(root.context)
|
|
||||||
val dateButton = TextView(root.context)
|
|
||||||
val timeButton = TextView(root.context)
|
|
||||||
dateButton.text = dateUtil.dateString(value)
|
|
||||||
timeButton.text = dateUtil.timeString(value)
|
|
||||||
|
|
||||||
// create an OnDateSetListener
|
|
||||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = value
|
|
||||||
cal.set(Calendar.YEAR, year)
|
|
||||||
cal.set(Calendar.MONTH, monthOfYear)
|
|
||||||
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
|
||||||
value = cal.timeInMillis
|
|
||||||
dateButton.text = dateUtil.dateString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
dateButton.setOnClickListener {
|
|
||||||
root.context?.let {
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = value
|
|
||||||
DatePickerDialog(it, dateSetListener,
|
|
||||||
cal.get(Calendar.YEAR),
|
|
||||||
cal.get(Calendar.MONTH),
|
|
||||||
cal.get(Calendar.DAY_OF_MONTH)
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an OnTimeSetListener
|
|
||||||
val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = value
|
|
||||||
cal.set(Calendar.HOUR_OF_DAY, hour)
|
|
||||||
cal.set(Calendar.MINUTE, minute)
|
|
||||||
cal.set(Calendar.SECOND, 0) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
|
||||||
value = cal.timeInMillis
|
|
||||||
timeButton.text = dateUtil.timeString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
timeButton.setOnClickListener {
|
|
||||||
root.context?.let {
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = value
|
|
||||||
TimePickerDialog(it, timeSetListener,
|
|
||||||
cal.get(Calendar.HOUR_OF_DAY),
|
|
||||||
cal.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(it)
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val px = resourceHelper.dpToPx(10)
|
val px = resourceHelper.dpToPx(10)
|
||||||
label.text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
|
||||||
label.setTypeface(label.typeface, Typeface.BOLD)
|
|
||||||
label.setPadding(px, px, px, px)
|
|
||||||
dateButton.setPadding(px, px, px, px)
|
|
||||||
timeButton.setPadding(px, px, px, px)
|
|
||||||
val l = LinearLayout(root.context)
|
|
||||||
l.orientation = LinearLayout.HORIZONTAL
|
|
||||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
l.addView(label)
|
|
||||||
l.addView(dateButton)
|
|
||||||
l.addView(timeButton)
|
|
||||||
root.addView(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
root.addView(
|
||||||
|
LinearLayout(root.context).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
||||||
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
})
|
||||||
|
addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = dateUtil.dateString(value)
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = value
|
||||||
|
DatePickerDialog(
|
||||||
|
it,
|
||||||
|
{ _, year, monthOfYear, dayOfMonth ->
|
||||||
|
value = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = value
|
||||||
|
set(Calendar.YEAR, year)
|
||||||
|
set(Calendar.MONTH, monthOfYear)
|
||||||
|
set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||||
|
}.timeInMillis
|
||||||
|
text = dateUtil.dateString(value)
|
||||||
|
},
|
||||||
|
cal.get(Calendar.YEAR),
|
||||||
|
cal.get(Calendar.MONTH),
|
||||||
|
cal.get(Calendar.DAY_OF_MONTH)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = dateUtil.timeString(value)
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = value
|
||||||
|
TimePickerDialog(
|
||||||
|
it,
|
||||||
|
{ _, hour, minute ->
|
||||||
|
value = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = value
|
||||||
|
set(Calendar.HOUR_OF_DAY, hour)
|
||||||
|
set(Calendar.MINUTE, minute)
|
||||||
|
set(Calendar.SECOND, 0) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||||
|
}.timeInMillis
|
||||||
|
text = dateUtil.timeString(value)
|
||||||
|
},
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(it)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.Spinner
|
import android.widget.Spinner
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
|
@ -19,12 +19,13 @@ class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
|
|
||||||
@get:StringRes val stringRes: Int
|
@get:StringRes val stringRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
DELTA -> R.string.delta
|
DELTA -> R.string.delta
|
||||||
SHORT_AVERAGE -> R.string.short_avgdelta
|
SHORT_AVERAGE -> R.string.short_avgdelta
|
||||||
LONG_AVERAGE -> R.string.long_avgdelta
|
LONG_AVERAGE -> R.string.long_avgdelta
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (d in values()) {
|
for (d in values()) {
|
||||||
|
@ -61,32 +62,29 @@ class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, DeltaType.labels(resourceHelper))
|
Spinner(root.context).apply {
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, DeltaType.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = spinnerArrayAdapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(
|
}
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
spinner.layoutParams = spinnerParams
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
deltaType = DeltaType.values()[position]
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
}
|
||||||
deltaType = DeltaType.values()[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
spinner.setSelection(deltaType.ordinal)
|
setSelection(deltaType.ordinal)
|
||||||
val numberPicker = NumberPicker(root.context, null)
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null)
|
})
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
root.addView(
|
||||||
val l = LinearLayout(root.context)
|
NumberPicker(root.context, null).apply {
|
||||||
l.orientation = LinearLayout.VERTICAL
|
setParams(value, minValue, maxValue, step, decimalFormat, true, null, null)
|
||||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
l.addView(spinner)
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
l.addView(numberPicker)
|
})
|
||||||
root.addView(l)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class InputDouble() : Element() {
|
class InputDouble() : Element() {
|
||||||
|
|
||||||
var value = 0.0
|
var value = 0.0
|
||||||
private var minValue = 0.0
|
private var minValue = 0.0
|
||||||
private var maxValue = 0.0
|
private var maxValue = 0.0
|
||||||
|
@ -30,9 +32,11 @@ class InputDouble() : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
numberPicker = NumberPicker(root.context, null)
|
numberPicker = NumberPicker(root.context, null).apply {
|
||||||
numberPicker?.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||||
numberPicker?.setOnValueChangedListener { value: Double -> this.value = value }
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
}
|
||||||
root.addView(numberPicker)
|
root.addView(numberPicker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
@ -25,31 +25,25 @@ class InputDropdownMenu(private val resourceHelper: ResourceHelper) : Element()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val spinner = Spinner(root.context)
|
root.addView(
|
||||||
spinner.adapter = ArrayAdapter(
|
Spinner(root.context).apply {
|
||||||
root.context,
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, itemList).apply {
|
||||||
R.layout.spinner_centered, itemList
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
).also {
|
}
|
||||||
it.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).also {
|
||||||
}
|
it.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
spinner.layoutParams = LinearLayout.LayoutParams(
|
}
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
).also { it.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4)) }
|
|
||||||
|
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
setValue(itemList[position].toString())
|
setValue(itemList[position].toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
for (i in 0 until itemList.size) if (itemList[i] == value) spinner.setSelection(i)
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
root.addView(LinearLayout(root.context).also {
|
for (i in 0 until itemList.size) if (itemList[i] == value) setSelection(i)
|
||||||
it.orientation = LinearLayout.VERTICAL
|
})
|
||||||
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
it.addView(spinner)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setValue(name: String): InputDropdownMenu {
|
fun setValue(name: String): InputDropdownMenu {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
import info.nightscout.androidaps.utils.ui.MinutesNumberPicker
|
||||||
|
@ -25,6 +26,7 @@ class InputDuration(
|
||||||
numberPicker.setParams(value.toDouble(), 1.0, 24.0, 1.0, DecimalFormat("0"), false, root.findViewById(R.id.ok))
|
numberPicker.setParams(value.toDouble(), 1.0, 24.0, 1.0, DecimalFormat("0"), false, root.findViewById(R.id.ok))
|
||||||
}
|
}
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value.toInt() }
|
numberPicker.setOnValueChangedListener { value: Double -> this.value = value.toInt() }
|
||||||
|
numberPicker.gravity = Gravity.CENTER_HORIZONTAL
|
||||||
root.addView(numberPicker)
|
root.addView(numberPicker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class InputInsulin() : Element() {
|
class InputInsulin() : Element() {
|
||||||
|
|
||||||
var value = 0.0
|
var value = 0.0
|
||||||
|
|
||||||
constructor(another: InputInsulin) : this() {
|
constructor(another: InputInsulin) : this() {
|
||||||
|
@ -13,10 +15,12 @@ class InputInsulin() : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val numberPicker = NumberPicker(root.context, null)
|
root.addView(
|
||||||
numberPicker.setParams(0.0, -20.0, 20.0, 0.1, DecimalFormat("0.0"), true, root.findViewById(R.id.ok))
|
NumberPicker(root.context, null).apply {
|
||||||
numberPicker.value = value
|
setParams(0.0, -20.0, 20.0, 0.1, DecimalFormat("0.0"), true, root.findViewById(R.id.ok))
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
value = value
|
||||||
root.addView(numberPicker)
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
@ -30,6 +31,7 @@ class InputLocationMode(private val resourceHelper: ResourceHelper) : Element()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||||
val list: MutableList<String> = ArrayList()
|
val list: MutableList<String> = ArrayList()
|
||||||
for (c in values()) {
|
for (c in values()) {
|
||||||
|
@ -47,24 +49,24 @@ class InputLocationMode(private val resourceHelper: ResourceHelper) : Element()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Mode.labels(resourceHelper))
|
root.addView(
|
||||||
val spinner = Spinner(root.context)
|
Spinner(root.context).apply {
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Mode.labels(resourceHelper)).apply {
|
||||||
spinner.adapter = adapter
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
val spinnerParams = LinearLayout.LayoutParams(
|
}
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
)
|
}
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
layoutParams = spinnerParams
|
||||||
spinner.layoutParams = spinnerParams
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
value = Mode.values()[position]
|
||||||
value = Mode.values()[position]
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
}
|
}
|
||||||
spinner.setSelection(value.ordinal)
|
setSelection(value.ordinal)
|
||||||
root.addView(spinner)
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
|
@ -14,11 +15,13 @@ class InputPercent() : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val numberPicker = NumberPicker(root.context, null)
|
root.addView(
|
||||||
numberPicker.setParams(100.0, MIN, MAX, 5.0, DecimalFormat("0"), true, root.findViewById(R.id.ok))
|
NumberPicker(root.context, null).apply {
|
||||||
numberPicker.value = value
|
setParams(100.0, MIN, MAX, 5.0, DecimalFormat("0"), true, root.findViewById(R.id.ok))
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
value = value
|
||||||
root.addView(numberPicker)
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
@ -17,28 +17,24 @@ class InputProfileName(private val resourceHelper: ResourceHelper, private val a
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val profileStore = activePlugin.activeProfileSource.profile ?: return
|
val profileStore = activePlugin.activeProfileSource.profile ?: return
|
||||||
val profileList = profileStore.getProfileList()
|
val profileList = profileStore.getProfileList()
|
||||||
val adapter = ArrayAdapter(root.context, R.layout.spinner_centered, profileList)
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
val spinner = Spinner(root.context)
|
|
||||||
spinner.adapter = adapter
|
|
||||||
val spinnerParams = LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
)
|
|
||||||
spinnerParams.setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
|
||||||
spinner.layoutParams = spinnerParams
|
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
value = profileList[position].toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
root.addView(
|
||||||
}
|
Spinner(root.context).apply {
|
||||||
for (i in 0 until profileList.size) if (profileList[i] == value) spinner.setSelection(i)
|
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, profileList).apply {
|
||||||
val l = LinearLayout(root.context)
|
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
l.orientation = LinearLayout.VERTICAL
|
}
|
||||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
l.addView(spinner)
|
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||||
root.addView(l)
|
}
|
||||||
|
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||||
|
value = profileList[position].toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||||
|
}
|
||||||
|
for (i in 0 until profileList.size) if (profileList[i] == value) setSelection(i)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,13 @@ package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
||||||
class InputString(var value: String = "") : Element() {
|
class InputString(var value: String = "") : Element() {
|
||||||
|
|
||||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
|
@ -16,10 +18,12 @@ class InputString(var value: String = "") : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val editText = EditText(root.context)
|
root.addView(
|
||||||
editText.setText(value)
|
EditText(root.context).apply {
|
||||||
editText.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
setText(value)
|
||||||
editText.addTextChangedListener(textWatcher)
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
root.addView(editText)
|
addTextChangedListener(textWatcher)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
|
@ -9,6 +10,7 @@ import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
|
||||||
class InputTempTarget(profileFunction: ProfileFunction) : Element() {
|
class InputTempTarget(profileFunction: ProfileFunction) : Element() {
|
||||||
|
|
||||||
var units: GlucoseUnit = GlucoseUnit.MGDL
|
var units: GlucoseUnit = GlucoseUnit.MGDL
|
||||||
var value = 0.0
|
var value = 0.0
|
||||||
|
|
||||||
|
@ -38,9 +40,12 @@ class InputTempTarget(profileFunction: ProfileFunction) : Element() {
|
||||||
step = 1.0
|
step = 1.0
|
||||||
decimalFormat = DecimalFormat("0")
|
decimalFormat = DecimalFormat("0")
|
||||||
}
|
}
|
||||||
val numberPicker = NumberPicker(root.context, null)
|
root.addView(
|
||||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
NumberPicker(root.context, null).apply {
|
||||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||||
root.addView(numberPicker)
|
setOnValueChangedListener { value: Double -> this.value = value }
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
import android.app.TimePickerDialog
|
import android.app.TimePickerDialog
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -18,37 +19,38 @@ class InputTime(private val resourceHelper: ResourceHelper, private val dateUtil
|
||||||
var value: Int = getMinSinceMidnight(dateUtil.now())
|
var value: Int = getMinSinceMidnight(dateUtil.now())
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val label = TextView(root.context)
|
root.addView(
|
||||||
val startButton = TextView(root.context)
|
LinearLayout(root.context).apply {
|
||||||
startButton.text = dateUtil.timeString(toMills(value))
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
addView(
|
||||||
value = 60 * hour + minute
|
TextView(root.context).apply {
|
||||||
startButton.text = dateUtil.timeString(toMills(value))
|
text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
||||||
}
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
})
|
||||||
startButton.setOnClickListener {
|
addView(
|
||||||
root.context?.let {
|
TextView(root.context).apply {
|
||||||
val cal = Calendar.getInstance()
|
text = dateUtil.timeString(toMills(value))
|
||||||
cal.timeInMillis = toMills(value)
|
val px = resourceHelper.dpToPx(10)
|
||||||
TimePickerDialog(it, startTimeSetListener,
|
setPadding(px, px, px, px)
|
||||||
cal.get(Calendar.HOUR_OF_DAY),
|
setOnClickListener {
|
||||||
cal.get(Calendar.MINUTE),
|
root.context?.let {
|
||||||
DateFormat.is24HourFormat(it)
|
val cal = Calendar.getInstance()
|
||||||
).show()
|
cal.timeInMillis = toMills(value)
|
||||||
}
|
TimePickerDialog(
|
||||||
}
|
it,
|
||||||
|
{ _, hour, minute ->
|
||||||
val px = resourceHelper.dpToPx(10)
|
value = 60 * hour + minute
|
||||||
label.text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
text = dateUtil.timeString(toMills(value))
|
||||||
label.setTypeface(label.typeface, Typeface.BOLD)
|
},
|
||||||
startButton.setPadding(px, px, px, px)
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
val l = LinearLayout(root.context)
|
cal.get(Calendar.MINUTE),
|
||||||
l.orientation = LinearLayout.HORIZONTAL
|
DateFormat.is24HourFormat(it)
|
||||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
).show()
|
||||||
l.addView(label)
|
}
|
||||||
l.addView(startButton)
|
}
|
||||||
root.addView(l)
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calcPlusMinutes(minutesSinceMidnight)
|
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calcPlusMinutes(minutesSinceMidnight)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
import android.app.TimePickerDialog
|
import android.app.TimePickerDialog
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -19,59 +20,62 @@ class InputTimeRange(private val resourceHelper: ResourceHelper, private val dat
|
||||||
var end: Int = getMinSinceMidnight(dateUtil.now())
|
var end: Int = getMinSinceMidnight(dateUtil.now())
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val label = TextView(root.context)
|
|
||||||
val startButton = TextView(root.context)
|
|
||||||
val endButton = TextView(root.context)
|
|
||||||
startButton.text = dateUtil.timeString(toMills(start))
|
|
||||||
@Suppress("SetTextI18n")
|
|
||||||
endButton.text = resourceHelper.gs(R.string.and) + " " + dateUtil.timeString(toMills(end))
|
|
||||||
|
|
||||||
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
|
||||||
start = 60 * hour + minute
|
|
||||||
startButton.text = dateUtil.timeString(toMills(start))
|
|
||||||
}
|
|
||||||
|
|
||||||
startButton.setOnClickListener {
|
|
||||||
root.context?.let {
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = toMills(start)
|
|
||||||
TimePickerDialog(it, startTimeSetListener,
|
|
||||||
cal.get(Calendar.HOUR_OF_DAY),
|
|
||||||
cal.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(it)
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val endTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
|
||||||
end = 60 * hour + minute
|
|
||||||
endButton.text = dateUtil.timeString(toMills(end))
|
|
||||||
}
|
|
||||||
|
|
||||||
endButton.setOnClickListener {
|
|
||||||
root.context?.let {
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.timeInMillis = toMills(end)
|
|
||||||
TimePickerDialog(it, endTimeSetListener,
|
|
||||||
cal.get(Calendar.HOUR_OF_DAY),
|
|
||||||
cal.get(Calendar.MINUTE),
|
|
||||||
DateFormat.is24HourFormat(it)
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val px = resourceHelper.dpToPx(10)
|
val px = resourceHelper.dpToPx(10)
|
||||||
label.text = resourceHelper.gs(R.string.between)
|
|
||||||
label.setTypeface(label.typeface, Typeface.BOLD)
|
root.addView(
|
||||||
startButton.setPadding(px, px, px, px)
|
TextView(root.context).apply {
|
||||||
endButton.setPadding(px, px, px, px)
|
text = resourceHelper.gs(R.string.between)
|
||||||
val l = LinearLayout(root.context)
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
l.orientation = LinearLayout.HORIZONTAL
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
})
|
||||||
l.addView(label)
|
root.addView(
|
||||||
l.addView(startButton)
|
LinearLayout(root.context).apply {
|
||||||
l.addView(endButton)
|
orientation = LinearLayout.HORIZONTAL
|
||||||
root.addView(l)
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
|
addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = dateUtil.timeString(toMills(start))
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(start)
|
||||||
|
TimePickerDialog(
|
||||||
|
it,
|
||||||
|
{ _, hour, minute ->
|
||||||
|
start = 60 * hour + minute
|
||||||
|
text = dateUtil.timeString(toMills(start))
|
||||||
|
},
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(it)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
addView(TextView(root.context).apply {
|
||||||
|
@Suppress("SetTextI18n")
|
||||||
|
text = resourceHelper.gs(R.string.and) + " " + dateUtil.timeString(toMills(end))
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setOnClickListener {
|
||||||
|
root.context?.let {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.timeInMillis = toMills(end)
|
||||||
|
TimePickerDialog(
|
||||||
|
it,
|
||||||
|
{ _, hour, minute ->
|
||||||
|
end = 60 * hour + minute
|
||||||
|
text = dateUtil.timeString(toMills(end))
|
||||||
|
},
|
||||||
|
cal.get(Calendar.HOUR_OF_DAY),
|
||||||
|
cal.get(Calendar.MINUTE),
|
||||||
|
DateFormat.is24HourFormat(it)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calcPlusMinutes(minutesSinceMidnight)
|
private fun toMills(minutesSinceMidnight: Int): Long = MidnightTime.calcPlusMinutes(minutesSinceMidnight)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import dagger.android.HasAndroidInjector
|
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.utils.ui.WeekdayPicker
|
import info.nightscout.androidaps.utils.ui.WeekdayPicker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -20,6 +19,7 @@ class InputWeekDay : Element() {
|
||||||
get() = shortNames[ordinal]
|
get() = shortNames[ordinal]
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val calendarInts = intArrayOf(
|
private val calendarInts = intArrayOf(
|
||||||
Calendar.MONDAY,
|
Calendar.MONDAY,
|
||||||
Calendar.TUESDAY,
|
Calendar.TUESDAY,
|
||||||
|
@ -76,10 +76,11 @@ class InputWeekDay : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
WeekdayPicker(root.context).apply {
|
root.addView(
|
||||||
setSelectedDays(getSelectedDays())
|
WeekdayPicker(root.context).apply {
|
||||||
setOnWeekdaysChangeListener { i: Int, selected: Boolean -> set(DayOfWeek.fromCalendarInt(i), selected) }
|
setSelectedDays(getSelectedDays())
|
||||||
root.addView(this)
|
setOnWeekdaysChangeListener { i: Int, selected: Boolean -> set(DayOfWeek.fromCalendarInt(i), selected) }
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.view.ViewGroup
|
import android.view.Gravity
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TableLayout
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
|
||||||
|
@ -15,35 +14,27 @@ class LabelWithElement(
|
||||||
) : Element() {
|
) : Element() {
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) { // container layout
|
override fun addToLayout(root: LinearLayout) { // container layout
|
||||||
val layout = LinearLayout(root.context)
|
|
||||||
layout.orientation = LinearLayout.HORIZONTAL
|
|
||||||
layout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
// text view pre element
|
// text view pre element
|
||||||
var px = resourceHelper.dpToPx(10)
|
val px = resourceHelper.dpToPx(1)
|
||||||
val textViewPre = TextView(root.context)
|
|
||||||
textViewPre.text = textPre
|
|
||||||
textViewPre.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
textViewPre.setPadding(px, px, px, px)
|
|
||||||
textViewPre.setTypeface(textViewPre.typeface, Typeface.BOLD)
|
|
||||||
layout.addView(textViewPre)
|
|
||||||
val spacer = TextView(root.context)
|
|
||||||
spacer.layoutParams = TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
|
||||||
layout.addView(spacer)
|
|
||||||
// add element to layout
|
|
||||||
element?.addToLayout(layout)
|
|
||||||
// text view post element
|
|
||||||
px = resourceHelper.dpToPx(5)
|
|
||||||
val textViewPost = TextView(root.context)
|
|
||||||
textViewPost.text = textPost
|
|
||||||
textViewPost.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
textViewPost.setPadding(px, px, px, px)
|
|
||||||
textViewPost.setTypeface(textViewPost.typeface, Typeface.BOLD)
|
|
||||||
layout.addView(textViewPost)
|
|
||||||
// add layout to root layout
|
|
||||||
root.addView(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
root.addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = textPre
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// add element to layout
|
||||||
|
element?.addToLayout(root)
|
||||||
|
// text view post element
|
||||||
|
root.addView(
|
||||||
|
TextView(root.context).apply {
|
||||||
|
text = textPost
|
||||||
|
setPadding(px, px, px, px)
|
||||||
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.elements
|
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import info.nightscout.androidaps.automation.R
|
||||||
|
|
||||||
class LayoutBuilder {
|
class LayoutBuilder {
|
||||||
|
|
||||||
|
@ -16,8 +20,21 @@ class LayoutBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(layout: LinearLayout) {
|
fun build(layout: LinearLayout) {
|
||||||
for (e in mElements) {
|
val elementLayout = LinearLayout(layout.context).apply {
|
||||||
e.addToLayout(layout)
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||||
|
setMargins(0, 0, dpToPx(layout.context, 2), dpToPx(layout.context, 2))
|
||||||
|
}
|
||||||
|
setBackgroundColor(layout.context.getColor(R.color.mdtp_line_dark))
|
||||||
}
|
}
|
||||||
|
for (e in mElements) {
|
||||||
|
e.addToLayout(elementLayout)
|
||||||
|
}
|
||||||
|
layout.addView(elementLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dpToPx(context: Context, dp: Int): Int {
|
||||||
|
val scale = context.resources.displayMetrics.density
|
||||||
|
return (dp * scale + 0.5f).toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,10 +4,8 @@ import android.graphics.Typeface
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import dagger.android.HasAndroidInjector
|
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class StaticLabel(private val resourceHelper: ResourceHelper) : Element() {
|
class StaticLabel(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
|
|
||||||
|
@ -25,24 +23,25 @@ class StaticLabel(private val resourceHelper: ResourceHelper) : Element() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addToLayout(root: LinearLayout) {
|
override fun addToLayout(root: LinearLayout) {
|
||||||
val headerLayout = LinearLayout(root.context)
|
|
||||||
headerLayout.orientation = LinearLayout.HORIZONTAL
|
|
||||||
headerLayout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
headerLayout.setBackgroundColor(resourceHelper.gc(android.R.color.black))
|
|
||||||
// text
|
|
||||||
val px = resourceHelper.dpToPx(10)
|
val px = resourceHelper.dpToPx(10)
|
||||||
val textView = TextView(root.context)
|
root.addView(
|
||||||
textView.text = label
|
LinearLayout(root.context).apply {
|
||||||
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
orientation = LinearLayout.HORIZONTAL
|
||||||
params.weight = 1.0f
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
textView.layoutParams = params
|
setBackgroundColor(resourceHelper.gc(android.R.color.black))
|
||||||
textView.setPadding(px, px, px, px)
|
addView(
|
||||||
textView.setTypeface(textView.typeface, Typeface.BOLD)
|
TextView(root.context).apply {
|
||||||
headerLayout.addView(textView)
|
text = label
|
||||||
trigger?.let {
|
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||||
headerLayout.addView(it.createDeleteButton(root.context, it))
|
weight = 1.0f
|
||||||
headerLayout.addView(it.createCloneButton(root.context, it))
|
}
|
||||||
}
|
setPadding(px, px, px, px)
|
||||||
root.addView(headerLayout)
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
})
|
||||||
|
trigger?.let {
|
||||||
|
addView(it.createDeleteButton(root.context, it))
|
||||||
|
addView(it.createCloneButton(root.context, it))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.events
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
import info.nightscout.androidaps.events.Event
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
|
|
||||||
class EventAutomationUpdateTrigger(val trigger: Trigger) : Event()
|
class EventAutomationUpdateTrigger(val trigger: TriggerConnector) : Event()
|
||||||
|
|
|
@ -56,7 +56,7 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
||||||
abstract fun icon(): Optional<Int?>
|
abstract fun icon(): Optional<Int?>
|
||||||
abstract fun duplicate(): Trigger
|
abstract fun duplicate(): Trigger
|
||||||
|
|
||||||
private fun scanForActivity(cont: Context?): AppCompatActivity? {
|
fun scanForActivity(cont: Context?): AppCompatActivity? {
|
||||||
return when (cont) {
|
return when (cont) {
|
||||||
null -> null
|
null -> null
|
||||||
is AppCompatActivity -> cont
|
is AppCompatActivity -> cont
|
||||||
|
@ -84,27 +84,19 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
||||||
//return (clazz.primaryConstructor?.call(injector) as Trigger).fromJSON(data?.toString() ?: "")
|
//return (clazz.primaryConstructor?.call(injector) as Trigger).fromJSON(data?.toString() ?: "")
|
||||||
return when (type) {
|
return when (type) {
|
||||||
TriggerAutosensValue::class.java.name, // backward compatibility
|
TriggerAutosensValue::class.java.name, // backward compatibility
|
||||||
TriggerAutosensValue::class.java.simpleName -> TriggerAutosensValue(injector).fromJSON(
|
TriggerAutosensValue::class.java.simpleName -> TriggerAutosensValue(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerBg::class.java.name,
|
TriggerBg::class.java.name,
|
||||||
TriggerBg::class.java.simpleName -> TriggerBg(injector).fromJSON(data.toString())
|
TriggerBg::class.java.simpleName -> TriggerBg(injector).fromJSON(data.toString())
|
||||||
TriggerBolusAgo::class.java.name,
|
TriggerBolusAgo::class.java.name,
|
||||||
TriggerBolusAgo::class.java.simpleName -> TriggerBolusAgo(injector).fromJSON(
|
TriggerBolusAgo::class.java.simpleName -> TriggerBolusAgo(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerBTDevice::class.java.name,
|
TriggerBTDevice::class.java.name,
|
||||||
TriggerBTDevice::class.java.simpleName -> TriggerBTDevice(injector).fromJSON(
|
TriggerBTDevice::class.java.simpleName -> TriggerBTDevice(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerIob::class.java.name,
|
TriggerIob::class.java.name,
|
||||||
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
||||||
TriggerCOB::class.java.name,
|
TriggerCOB::class.java.name,
|
||||||
TriggerCOB::class.java.simpleName -> TriggerCOB(injector).fromJSON(data.toString())
|
TriggerCOB::class.java.simpleName -> TriggerCOB(injector).fromJSON(data.toString())
|
||||||
TriggerConnector::class.java.name,
|
TriggerConnector::class.java.name,
|
||||||
TriggerConnector::class.java.simpleName -> TriggerConnector(injector).fromJSON(
|
TriggerConnector::class.java.simpleName -> TriggerConnector(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerDelta::class.java.name,
|
TriggerDelta::class.java.name,
|
||||||
TriggerDelta::class.java.simpleName -> TriggerDelta(injector).fromJSON(data.toString())
|
TriggerDelta::class.java.simpleName -> TriggerDelta(injector).fromJSON(data.toString())
|
||||||
TriggerDummy::class.java.name,
|
TriggerDummy::class.java.name,
|
||||||
|
@ -112,100 +104,73 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
||||||
TriggerIob::class.java.name,
|
TriggerIob::class.java.name,
|
||||||
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
||||||
TriggerLocation::class.java.name,
|
TriggerLocation::class.java.name,
|
||||||
TriggerLocation::class.java.simpleName -> TriggerLocation(injector).fromJSON(
|
TriggerLocation::class.java.simpleName -> TriggerLocation(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerProfilePercent::class.java.name,
|
TriggerProfilePercent::class.java.name,
|
||||||
TriggerProfilePercent::class.java.simpleName -> TriggerProfilePercent(injector).fromJSON(
|
TriggerProfilePercent::class.java.simpleName -> TriggerProfilePercent(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerPumpLastConnection::class.java.name,
|
TriggerPumpLastConnection::class.java.name,
|
||||||
TriggerPumpLastConnection::class.java.simpleName -> TriggerPumpLastConnection(injector).fromJSON(
|
TriggerPumpLastConnection::class.java.simpleName -> TriggerPumpLastConnection(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerRecurringTime::class.java.name,
|
TriggerRecurringTime::class.java.name,
|
||||||
TriggerRecurringTime::class.java.simpleName -> TriggerRecurringTime(injector).fromJSON(
|
TriggerRecurringTime::class.java.simpleName -> TriggerRecurringTime(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerTempTarget::class.java.name,
|
TriggerTempTarget::class.java.name,
|
||||||
TriggerTempTarget::class.java.simpleName -> TriggerTempTarget(injector).fromJSON(
|
TriggerTempTarget::class.java.simpleName -> TriggerTempTarget(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerTempTargetValue::class.java.name,
|
TriggerTempTargetValue::class.java.name,
|
||||||
TriggerTempTargetValue::class.java.simpleName -> TriggerTempTargetValue(injector).fromJSON(
|
TriggerTempTargetValue::class.java.simpleName -> TriggerTempTargetValue(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerTime::class.java.name,
|
TriggerTime::class.java.name,
|
||||||
TriggerTime::class.java.simpleName -> TriggerTime(injector).fromJSON(data.toString())
|
TriggerTime::class.java.simpleName -> TriggerTime(injector).fromJSON(data.toString())
|
||||||
TriggerTimeRange::class.java.name,
|
TriggerTimeRange::class.java.name,
|
||||||
TriggerTimeRange::class.java.simpleName -> TriggerTimeRange(injector).fromJSON(
|
TriggerTimeRange::class.java.simpleName -> TriggerTimeRange(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
TriggerWifiSsid::class.java.name,
|
TriggerWifiSsid::class.java.name,
|
||||||
TriggerWifiSsid::class.java.simpleName -> TriggerWifiSsid(injector).fromJSON(
|
TriggerWifiSsid::class.java.simpleName -> TriggerWifiSsid(injector).fromJSON(data.toString())
|
||||||
data.toString()
|
|
||||||
)
|
|
||||||
else -> TriggerConnector(injector)
|
else -> TriggerConnector(injector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createAddButton(context: Context, trigger: TriggerConnector): ImageButton {
|
fun createAddButton(context: Context, trigger: TriggerConnector): ImageButton =
|
||||||
// Button [+]
|
// Button [+]
|
||||||
val buttonAdd = ImageButton(context)
|
ImageButton(context).apply {
|
||||||
val params = LinearLayout.LayoutParams(
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
gravity = Gravity.CENTER
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
}
|
||||||
)
|
setImageResource(R.drawable.ic_add)
|
||||||
params.gravity = Gravity.CENTER
|
contentDescription = resourceHelper.gs(R.string.add_short)
|
||||||
buttonAdd.layoutParams = params
|
setOnClickListener {
|
||||||
buttonAdd.setImageResource(R.drawable.ic_add)
|
scanForActivity(context)?.supportFragmentManager?.let {
|
||||||
buttonAdd.contentDescription = resourceHelper.gs(R.string.add_short)
|
val dialog = ChooseTriggerDialog()
|
||||||
buttonAdd.setOnClickListener {
|
dialog.show(it, "ChooseTriggerDialog")
|
||||||
scanForActivity(context)?.supportFragmentManager?.let {
|
dialog.setOnClickListener(object : ChooseTriggerDialog.OnClickListener {
|
||||||
val dialog = ChooseTriggerDialog()
|
override fun onClick(newTriggerObject: Trigger) {
|
||||||
dialog.show(it, "ChooseTriggerDialog")
|
trigger.list.add(newTriggerObject)
|
||||||
dialog.setOnClickListener(object : ChooseTriggerDialog.OnClickListener {
|
rxBus.send(EventTriggerChanged())
|
||||||
override fun onClick(newTriggerObject: Trigger) {
|
}
|
||||||
trigger.list.add(newTriggerObject)
|
})
|
||||||
rxBus.send(EventTriggerChanged())
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buttonAdd
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createDeleteButton(context: Context, trigger: Trigger): ImageButton {
|
fun createDeleteButton(context: Context, trigger: Trigger): ImageButton =
|
||||||
// Button [-]
|
// Button [-]
|
||||||
val buttonRemove = ImageButton(context)
|
ImageButton(context).apply {
|
||||||
val params = LinearLayout.LayoutParams(
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
gravity = Gravity.CENTER
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
}
|
||||||
)
|
setImageResource(R.drawable.ic_remove)
|
||||||
params.gravity = Gravity.CENTER
|
contentDescription = resourceHelper.gs(R.string.delete_short)
|
||||||
buttonRemove.layoutParams = params
|
setOnClickListener {
|
||||||
buttonRemove.setImageResource(R.drawable.ic_remove)
|
rxBus.send(EventTriggerRemove(trigger))
|
||||||
buttonRemove.contentDescription = resourceHelper.gs(R.string.delete_short)
|
}
|
||||||
buttonRemove.setOnClickListener {
|
|
||||||
rxBus.send(EventTriggerRemove(trigger))
|
|
||||||
}
|
}
|
||||||
return buttonRemove
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createCloneButton(context: Context, trigger: Trigger): ImageButton {
|
fun createCloneButton(context: Context, trigger: Trigger): ImageButton =
|
||||||
// Button [*]
|
// Button [*]
|
||||||
val buttonClone = ImageButton(context)
|
ImageButton(context).apply {
|
||||||
val params = LinearLayout.LayoutParams(
|
val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
gravity = Gravity.CENTER
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
}
|
||||||
)
|
layoutParams = params
|
||||||
params.gravity = Gravity.CENTER
|
setImageResource(R.drawable.ic_clone)
|
||||||
buttonClone.layoutParams = params
|
contentDescription = resourceHelper.gs(R.string.copy_short)
|
||||||
buttonClone.setImageResource(R.drawable.ic_clone)
|
setOnClickListener {
|
||||||
buttonClone.contentDescription = resourceHelper.gs(R.string.copy_short)
|
rxBus.send(EventTriggerClone(trigger))
|
||||||
buttonClone.setOnClickListener {
|
}
|
||||||
rxBus.send(EventTriggerClone(trigger))
|
|
||||||
}
|
}
|
||||||
return buttonClone
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ import android.widget.LinearLayout
|
||||||
import com.google.common.base.Optional
|
import com.google.common.base.Optional
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
@ -36,7 +37,8 @@ class TriggerBolusAgo(injector: HasAndroidInjector) : Trigger(injector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldRun(): Boolean {
|
override fun shouldRun(): Boolean {
|
||||||
val lastBolusTime = repository.getLastBolusRecordOfType(Bolus.Type.NORMAL)?.timestamp ?: 0L
|
val lastBolus = repository.getLastBolusRecordOfTypeWrapped(Bolus.Type.NORMAL).blockingGet()
|
||||||
|
val lastBolusTime = if (lastBolus is ValueWrapper.Existing) lastBolus.value.timestamp else 0L
|
||||||
if (lastBolusTime == 0L)
|
if (lastBolusTime == 0L)
|
||||||
return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
@ -81,7 +83,7 @@ class TriggerBolusAgo(injector: HasAndroidInjector) : Trigger(injector) {
|
||||||
LayoutBuilder()
|
LayoutBuilder()
|
||||||
.add(StaticLabel(resourceHelper, R.string.lastboluslabel, this))
|
.add(StaticLabel(resourceHelper, R.string.lastboluslabel, this))
|
||||||
.add(comparator)
|
.add(comparator)
|
||||||
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
|
.add(LabelWithElement(resourceHelper, resourceHelper.gs(R.string.lastboluslabel) + ": ", resourceHelper.gs(R.string.unit_minutes), minutesAgo))
|
||||||
.build(root)
|
.build(root)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,20 @@
|
||||||
package info.nightscout.androidaps.plugins.general.automation.triggers
|
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.graphics.Typeface
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.Spinner
|
import android.widget.TextView
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import com.google.common.base.Optional
|
import com.google.common.base.Optional
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseOperationDialog
|
||||||
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.ui.VerticalTextView
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -35,7 +36,7 @@ class TriggerConnector(injector: HasAndroidInjector) : Trigger(injector) {
|
||||||
|
|
||||||
@get:StringRes val stringRes: Int
|
@get:StringRes val stringRes: Int
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
OR -> R.string.or
|
OR -> R.string.or
|
||||||
XOR -> R.string.xor
|
XOR -> R.string.xor
|
||||||
AND -> R.string.and
|
AND -> R.string.and
|
||||||
}
|
}
|
||||||
|
@ -119,51 +120,75 @@ class TriggerConnector(injector: HasAndroidInjector) : Trigger(injector) {
|
||||||
override fun duplicate(): Trigger = TriggerConnector(injector, connectorType)
|
override fun duplicate(): Trigger = TriggerConnector(injector, connectorType)
|
||||||
|
|
||||||
override fun generateDialog(root: LinearLayout) {
|
override fun generateDialog(root: LinearLayout) {
|
||||||
val padding = resourceHelper.dpToPx(5)
|
val mainLayout = LinearLayout(root.context).also {
|
||||||
root.setPadding(padding, padding, padding, padding)
|
it.orientation = LinearLayout.HORIZONTAL
|
||||||
root.setBackgroundResource(R.drawable.border_automation_unit)
|
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
// Header with spinner
|
|
||||||
val headerLayout = LinearLayout(root.context)
|
|
||||||
headerLayout.orientation = LinearLayout.HORIZONTAL
|
|
||||||
headerLayout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
headerLayout.addView(createSpinner(root.context))
|
|
||||||
headerLayout.addView(createAddButton(root.context, this))
|
|
||||||
headerLayout.addView(createDeleteButton(root.context, this))
|
|
||||||
root.addView(headerLayout)
|
|
||||||
// Child triggers
|
|
||||||
val listLayout = LinearLayout(root.context)
|
|
||||||
listLayout.orientation = LinearLayout.VERTICAL
|
|
||||||
listLayout.setBackgroundColor(resourceHelper.gc(R.color.mdtp_line_dark))
|
|
||||||
//listLayout.setPadding(resourceHelper.dpToPx(5), resourceHelper.dpToPx(5), resourceHelper.dpToPx(5), 0)
|
|
||||||
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
params.setMargins(resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(5), resourceHelper.dpToPx(4))
|
|
||||||
listLayout.layoutParams = params
|
|
||||||
for (t in list) t.generateDialog(listLayout)
|
|
||||||
root.addView(listLayout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createSpinner(context: Context): Spinner {
|
|
||||||
val initialPosition = connectorType.ordinal
|
|
||||||
val spinner = Spinner(context)
|
|
||||||
val spinnerArrayAdapter = ArrayAdapter(context, R.layout.spinner_centered, Type.labels(resourceHelper))
|
|
||||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
|
||||||
spinner.adapter = spinnerArrayAdapter
|
|
||||||
spinner.setSelection(initialPosition)
|
|
||||||
spinner.setBackgroundColor(resourceHelper.gc(R.color.black_overlay))
|
|
||||||
val params = LinearLayout.LayoutParams(
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
)
|
|
||||||
params.setMargins(0, resourceHelper.dpToPx(8), 0, resourceHelper.dpToPx(8))
|
|
||||||
params.weight = 1.0f
|
|
||||||
spinner.layoutParams = params
|
|
||||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
setType(Type.values()[position])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
|
||||||
}
|
}
|
||||||
return spinner
|
val padding = resourceHelper.dpToPx(3)
|
||||||
|
mainLayout.setPadding(padding, padding, padding, padding)
|
||||||
|
mainLayout.setBackgroundResource(R.drawable.border_automation_unit)
|
||||||
|
|
||||||
|
val buttonLayout = LinearLayout(root.context).also {
|
||||||
|
it.orientation = LinearLayout.HORIZONTAL
|
||||||
|
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
}
|
||||||
|
buttonLayout.addView(createAddButton(root.context, this))
|
||||||
|
buttonLayout.addView(createDeleteButton(root.context, this))
|
||||||
|
|
||||||
|
val rightSideLayout = LinearLayout(root.context).also {
|
||||||
|
it.orientation = LinearLayout.VERTICAL
|
||||||
|
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
rightSideLayout.addView(buttonLayout)
|
||||||
|
|
||||||
|
// Child triggers
|
||||||
|
val listLayout = LinearLayout(root.context).also {
|
||||||
|
it.orientation = LinearLayout.VERTICAL
|
||||||
|
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { params ->
|
||||||
|
params.setMargins(resourceHelper.dpToPx(1), 0, resourceHelper.dpToPx(1), resourceHelper.dpToPx(2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (t in list) {
|
||||||
|
t.generateDialog(listLayout)
|
||||||
|
listLayout.addView(
|
||||||
|
TextView(root.context).also {
|
||||||
|
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
it.setPadding(0, resourceHelper.dpToPx(0.3f), 0, 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
rightSideLayout.addView(listLayout)
|
||||||
|
|
||||||
|
// Header with spinner
|
||||||
|
mainLayout.addView(createVerticalView(root.context))
|
||||||
|
mainLayout.addView(rightSideLayout)
|
||||||
|
root.addView(mainLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createVerticalView(context: Context): VerticalTextView =
|
||||||
|
VerticalTextView(context).apply {
|
||||||
|
text = resourceHelper.gs(connectorType.stringRes)
|
||||||
|
gravity = gravity or Gravity.CENTER_VERTICAL
|
||||||
|
setTypeface(typeface, Typeface.BOLD)
|
||||||
|
setBackgroundColor(resourceHelper.gc(R.color.black_overlay))
|
||||||
|
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT).also { ll ->
|
||||||
|
ll.setMargins(resourceHelper.dpToPx(3), resourceHelper.dpToPx(3), resourceHelper.dpToPx(3), resourceHelper.dpToPx(3))
|
||||||
|
}
|
||||||
|
setOnClickListener {
|
||||||
|
scanForActivity(context)?.supportFragmentManager?.let {
|
||||||
|
ChooseOperationDialog().also { dialog ->
|
||||||
|
dialog.setCallback(object : ChooseOperationDialog.Callback() {
|
||||||
|
override fun run() {
|
||||||
|
result?.let { result ->
|
||||||
|
setType(Type.values()[result])
|
||||||
|
text = resourceHelper.gs(connectorType.stringRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dialog.setCheckedIndex(connectorType.ordinal)
|
||||||
|
dialog.show(it, "TriggerConnector")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -55,6 +55,12 @@ class TriggerProfilePercent(injector: HasAndroidInjector) : Trigger(injector) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (profile is ProfileSealed.Pure) {
|
||||||
|
if (comparator.value.check(100.0, pct.value)) {
|
||||||
|
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
aapsLogger.debug(LTag.AUTOMATION, "NOT ready for execution: " + friendlyDescription())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:minWidth="300dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context="info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseOperationDialog">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@color/dialog_title_background"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/please_choose_a_operation_type"
|
||||||
|
app:srcCompat="@drawable/ic_trigger_green_48dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:text="@string/please_choose_a_operation_type"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/chooseOperationRadioGroup"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="10dp"/>
|
||||||
|
|
||||||
|
<include layout="@layout/okcancel" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
|
@ -7,7 +7,7 @@
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
android:minWidth="300dp"
|
android:minWidth="300dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".plugins.general.automation.dialogs.EditEventDialog">
|
tools:context="info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
android:id="@+id/layoutTrigger"
|
android:id="@+id/layoutTrigger"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="10dp"
|
android:padding="0dp"
|
||||||
android:orientation="vertical" />
|
android:orientation="vertical" />
|
||||||
|
|
||||||
<include layout="@layout/okcancel" />
|
<include layout="@layout/okcancel" />
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
android:minWidth="300dp"
|
android:minWidth="300dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".plugins.general.automation.dialogs.EditEventDialog">
|
tools:context="info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<RelativeLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -29,17 +29,23 @@
|
||||||
app:srcCompat="@drawable/ic_action_orange_48dp" />
|
app:srcCompat="@drawable/ic_action_orange_48dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_marginRight="10dp"
|
android:layout_marginRight="10dp"
|
||||||
android:text="@string/automation_event"
|
android:text="@string/automation_event"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
|
android:layout_weight="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
</RelativeLayout>
|
<CheckBox
|
||||||
|
android:id="@+id/enabled"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/spacer"
|
android:id="@+id/spacer"
|
||||||
|
@ -54,6 +60,27 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/imageButton"
|
||||||
|
android:layout_width="27dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scaleX="0.7"
|
||||||
|
android:scaleY="0.7"
|
||||||
|
android:src="@drawable/ic_danar_useropt" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/user_action"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/user_action" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/inputEventTitle"
|
android:id="@+id/inputEventTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -107,12 +107,13 @@
|
||||||
<string name="edit_short">EDIT</string>
|
<string name="edit_short">EDIT</string>
|
||||||
<string name="please_choose_an_action_type">Choose an action type</string>
|
<string name="please_choose_an_action_type">Choose an action type</string>
|
||||||
<string name="please_choose_a_trigger_type">Choose a trigger type</string>
|
<string name="please_choose_a_trigger_type">Choose a trigger type</string>
|
||||||
|
<string name="please_choose_a_operation_type">Choose a operation type</string>
|
||||||
<string name="triggers">Triggers:</string>
|
<string name="triggers">Triggers:</string>
|
||||||
<string name="remove_label">REMOVE</string>
|
<string name="remove_label">REMOVE</string>
|
||||||
<string name="preconditions">Preconditions:</string>
|
<string name="preconditions">Preconditions:</string>
|
||||||
<string name="automation_event">Automation event</string>
|
<string name="automation_event">Automation event</string>
|
||||||
<string name="reorder_label">Reorder</string>
|
<string name="reorder_label">Reorder</string>
|
||||||
<string name="key_automation_settings" translatable="false">automation_settings</string>
|
<string name="key_automation_settings" translatable="false">automation_settings</string>
|
||||||
|
<string name="user_action">User action</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -8,6 +8,7 @@ import info.nightscout.androidaps.interfaces.Loop
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
import info.nightscout.androidaps.plugins.general.automation.actions.ActionLoopEnable
|
import info.nightscout.androidaps.plugins.general.automation.actions.ActionLoopEnable
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnectorTest
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnectorTest
|
||||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -44,11 +45,12 @@ class AutomationEventTest : TestBase() {
|
||||||
// create test object
|
// create test object
|
||||||
val event = AutomationEvent(injector)
|
val event = AutomationEvent(injector)
|
||||||
event.title = "Test"
|
event.title = "Test"
|
||||||
event.trigger = TriggerDummy(injector).instantiate(JSONObject(TriggerConnectorTest.oneItem))
|
event.trigger = TriggerDummy(injector).instantiate(JSONObject(TriggerConnectorTest.oneItem)) as TriggerConnector
|
||||||
event.addAction(ActionLoopEnable(injector))
|
event.addAction(ActionLoopEnable(injector))
|
||||||
|
|
||||||
// export to json
|
// export to json
|
||||||
val eventJsonExpected = "{\"autoRemove\":false,\"readOnly\":false,\"trigger\":\"{\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"data\\\\\\\":{\\\\\\\"connectorType\\\\\\\":\\\\\\\"AND\\\\\\\",\\\\\\\"triggerList\\\\\\\":[]},\\\\\\\"type\\\\\\\":\\\\\\\"TriggerConnector\\\\\\\"}\\\"]},\\\"type\\\":\\\"TriggerConnector\\\"}\",\"title\":\"Test\",\"systemAction\":false,\"actions\":[\"{\\\"type\\\":\\\"ActionLoopEnable\\\"}\"],\"enabled\":true}"
|
val eventJsonExpected =
|
||||||
|
"{\"userAction\":false,\"autoRemove\":false,\"readOnly\":false,\"trigger\":\"{\\\"data\\\":{\\\"connectorType\\\":\\\"AND\\\",\\\"triggerList\\\":[\\\"{\\\\\\\"data\\\\\\\":{\\\\\\\"connectorType\\\\\\\":\\\\\\\"AND\\\\\\\",\\\\\\\"triggerList\\\\\\\":[]},\\\\\\\"type\\\\\\\":\\\\\\\"TriggerConnector\\\\\\\"}\\\"]},\\\"type\\\":\\\"TriggerConnector\\\"}\",\"title\":\"Test\",\"systemAction\":false,\"actions\":[\"{\\\"type\\\":\\\"ActionLoopEnable\\\"}\"],\"enabled\":true}"
|
||||||
Assert.assertEquals(eventJsonExpected, event.toJSON())
|
Assert.assertEquals(eventJsonExpected, event.toJSON())
|
||||||
|
|
||||||
// clone
|
// clone
|
||||||
|
|
|
@ -2,8 +2,10 @@ package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||||
|
|
||||||
import com.google.common.base.Optional
|
import com.google.common.base.Optional
|
||||||
import info.nightscout.androidaps.automation.R
|
import info.nightscout.androidaps.automation.R
|
||||||
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||||
|
import io.reactivex.Single
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
@ -22,13 +24,18 @@ class TriggerBolusAgoTest : TriggerTestBase() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun shouldRunTest() {
|
fun shouldRunTest() {
|
||||||
`when`(repository.getLastBolusRecordOfType(Bolus.Type.NORMAL)).thenReturn(
|
// Set last bolus time to now
|
||||||
Bolus(
|
`when`(repository.getLastBolusRecordOfTypeWrapped(Bolus.Type.NORMAL)).thenReturn(
|
||||||
timestamp = now,
|
Single.just(
|
||||||
amount = 0.0,
|
ValueWrapper.Existing(
|
||||||
type = Bolus.Type.NORMAL
|
Bolus(
|
||||||
|
timestamp = now,
|
||||||
|
amount = 0.0,
|
||||||
|
type = Bolus.Type.NORMAL
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
) // Set last bolus time to now
|
)
|
||||||
`when`(dateUtil.now()).thenReturn(now + 10 * 60 * 1000) // set current time to now + 10 min
|
`when`(dateUtil.now()).thenReturn(now + 10 * 60 * 1000) // set current time to now + 10 min
|
||||||
var t = TriggerBolusAgo(injector).setValue(110).comparator(Comparator.Compare.IS_EQUAL)
|
var t = TriggerBolusAgo(injector).setValue(110).comparator(Comparator.Compare.IS_EQUAL)
|
||||||
Assert.assertEquals(110, t.minutesAgo.value)
|
Assert.assertEquals(110, t.minutesAgo.value)
|
||||||
|
@ -51,13 +58,18 @@ class TriggerBolusAgoTest : TriggerTestBase() {
|
||||||
Assert.assertTrue(t.shouldRun())
|
Assert.assertTrue(t.shouldRun())
|
||||||
t = TriggerBolusAgo(injector).setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER)
|
t = TriggerBolusAgo(injector).setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER)
|
||||||
Assert.assertTrue(t.shouldRun())
|
Assert.assertTrue(t.shouldRun())
|
||||||
`when`(repository.getLastBolusRecordOfType(Bolus.Type.NORMAL)).thenReturn(
|
// Set last bolus time to 0
|
||||||
Bolus(
|
`when`(repository.getLastBolusRecordOfTypeWrapped(Bolus.Type.NORMAL)).thenReturn(
|
||||||
timestamp = 0L,
|
Single.just(
|
||||||
amount = 0.0,
|
ValueWrapper.Existing(
|
||||||
type = Bolus.Type.NORMAL
|
Bolus(
|
||||||
|
timestamp = 0,
|
||||||
|
amount = 0.0,
|
||||||
|
type = Bolus.Type.NORMAL
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
) // Set last bolus time to 0
|
)
|
||||||
t = TriggerBolusAgo(injector).comparator(Comparator.Compare.IS_NOT_AVAILABLE)
|
t = TriggerBolusAgo(injector).comparator(Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
Assert.assertTrue(t.shouldRun())
|
Assert.assertTrue(t.shouldRun())
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ class TriggerProfilePercentTest : TriggerTestBase() {
|
||||||
Assert.assertEquals(bgJson, t.toJSON())
|
Assert.assertEquals(bgJson, t.toJSON())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Throws(JSONException::class) fun fromJSONTest() {
|
@Test fun fromJSONTest() {
|
||||||
val t: TriggerProfilePercent = TriggerProfilePercent(injector).setValue(120.0).comparator(Comparator.Compare.IS_EQUAL)
|
val t: TriggerProfilePercent = TriggerProfilePercent(injector).setValue(120.0).comparator(Comparator.Compare.IS_EQUAL)
|
||||||
val t2 = TriggerDummy(injector).instantiate(JSONObject(t.toJSON())) as TriggerProfilePercent
|
val t2 = TriggerDummy(injector).instantiate(JSONObject(t.toJSON())) as TriggerProfilePercent
|
||||||
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.comparator.value)
|
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.comparator.value)
|
||||||
|
|
|
@ -14,11 +14,11 @@ object OKDialog {
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
fun show(context: Context, title: String, message: String, runnable: Runnable? = null) {
|
fun show(context: Context, title: String, message: String, runnable: Runnable? = null) {
|
||||||
var okClicked = false
|
var okClicked = false
|
||||||
var notEmptytitle = title
|
var notEmptyTitle = title
|
||||||
if (notEmptytitle.isEmpty()) notEmptytitle = context.getString(R.string.message)
|
if (notEmptyTitle.isEmpty()) notEmptyTitle = context.getString(R.string.message)
|
||||||
|
|
||||||
AlertDialogHelper.Builder(context)
|
AlertDialogHelper.Builder(context)
|
||||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, notEmptytitle))
|
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, notEmptyTitle))
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setPositiveButton(context.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
.setPositiveButton(context.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
||||||
if (okClicked) return@setPositiveButton
|
if (okClicked) return@setPositiveButton
|
||||||
|
@ -36,11 +36,11 @@ object OKDialog {
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
fun show(activity: FragmentActivity, title: String, message: Spanned, runnable: Runnable? = null) {
|
fun show(activity: FragmentActivity, title: String, message: Spanned, runnable: Runnable? = null) {
|
||||||
var okClicked = false
|
var okClicked = false
|
||||||
var notEmptytitle = title
|
var notEmptyTitle = title
|
||||||
if (notEmptytitle.isEmpty()) notEmptytitle = activity.getString(R.string.message)
|
if (notEmptyTitle.isEmpty()) notEmptyTitle = activity.getString(R.string.message)
|
||||||
|
|
||||||
AlertDialogHelper.Builder(activity)
|
AlertDialogHelper.Builder(activity)
|
||||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, notEmptytitle))
|
.setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, notEmptyTitle))
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setPositiveButton(activity.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
.setPositiveButton(activity.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
||||||
if (okClicked) return@setPositiveButton
|
if (okClicked) return@setPositiveButton
|
||||||
|
|
|
@ -21,5 +21,6 @@ interface ResourceHelper {
|
||||||
fun decodeResource(id : Int) : Bitmap
|
fun decodeResource(id : Int) : Bitmap
|
||||||
fun getDisplayMetrics(): DisplayMetrics
|
fun getDisplayMetrics(): DisplayMetrics
|
||||||
fun dpToPx(dp: Int): Int
|
fun dpToPx(dp: Int): Int
|
||||||
|
fun dpToPx(dp: Float): Int
|
||||||
fun shortTextMode(): Boolean
|
fun shortTextMode(): Boolean
|
||||||
}
|
}
|
|
@ -26,7 +26,7 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
||||||
override fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String =
|
override fun gq(@PluralsRes id: Int, quantity: Int, vararg args: Any?): String =
|
||||||
context.resources.getQuantityString(id, quantity, *args)
|
context.resources.getQuantityString(id, quantity, *args)
|
||||||
|
|
||||||
override fun gsNotLocalised(@StringRes id: Int, vararg args: Any?) : String =
|
override fun gsNotLocalised(@StringRes id: Int, vararg args: Any?): String =
|
||||||
with(Configuration(context.resources.configuration)) {
|
with(Configuration(context.resources.configuration)) {
|
||||||
setLocale(Locale.ENGLISH)
|
setLocale(Locale.ENGLISH)
|
||||||
context.createConfigurationContext(this).getString(id, args)
|
context.createConfigurationContext(this).getString(id, args)
|
||||||
|
@ -51,7 +51,7 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
||||||
override fun decodeResource(id: Int): Bitmap =
|
override fun decodeResource(id: Int): Bitmap =
|
||||||
BitmapFactory.decodeResource(context.resources, id)
|
BitmapFactory.decodeResource(context.resources, id)
|
||||||
|
|
||||||
override fun getDisplayMetrics():DisplayMetrics =
|
override fun getDisplayMetrics(): DisplayMetrics =
|
||||||
context.resources.displayMetrics
|
context.resources.displayMetrics
|
||||||
|
|
||||||
override fun dpToPx(dp: Int): Int {
|
override fun dpToPx(dp: Int): Int {
|
||||||
|
@ -59,5 +59,10 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
||||||
return (dp * scale + 0.5f).toInt()
|
return (dp * scale + 0.5f).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shortTextMode() : Boolean = !gb(R.bool.isTablet)
|
override fun dpToPx(dp: Float): Int {
|
||||||
|
val scale = context.resources.displayMetrics.density
|
||||||
|
return (dp * scale + 0.5f).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shortTextMode(): Boolean = !gb(R.bool.isTablet)
|
||||||
}
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.utils.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.Gravity
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
|
||||||
|
class VerticalTextView(context: Context, attrs: AttributeSet? = null) : AppCompatTextView(context, attrs) {
|
||||||
|
|
||||||
|
private var topDown = false
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
super.onMeasure(heightMeasureSpec, widthMeasureSpec)
|
||||||
|
setMeasuredDimension(measuredHeight, measuredWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
val textPaint = paint
|
||||||
|
textPaint.color = currentTextColor
|
||||||
|
textPaint.drawableState = drawableState
|
||||||
|
canvas.save()
|
||||||
|
if (topDown) {
|
||||||
|
canvas.translate(width.toFloat(), 0f)
|
||||||
|
canvas.rotate(90f)
|
||||||
|
} else {
|
||||||
|
canvas.translate(0f, height.toFloat())
|
||||||
|
canvas.rotate(-90f)
|
||||||
|
}
|
||||||
|
canvas.translate(compoundPaddingLeft.toFloat(), extendedPaddingTop.toFloat())
|
||||||
|
layout.draw(canvas)
|
||||||
|
canvas.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val gravity = gravity
|
||||||
|
topDown = if (Gravity.isVertical(gravity) && gravity and Gravity.VERTICAL_GRAVITY_MASK == Gravity.BOTTOM) {
|
||||||
|
setGravity(gravity and Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.TOP)
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
Please use AlertDialogHelper or wrap inflater context with ContextThemeWrapper(context, R.style.AppTheme)
|
Please use AlertDialogHelper or wrap inflater context with ContextThemeWrapper(context, R.style.AppTheme)
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
android:id="@+id/alertdialog_icon"
|
android:id="@+id/alertdialog_icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:tint="?dialogTitleIconTint" />
|
app:tint="?dialogTitleIconTint" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/alertdialog_title"
|
android:id="@+id/alertdialog_title"
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
<color name="cardColorBackground">#121212</color>
|
<color name="cardColorBackground">#121212</color>
|
||||||
<color name="black_overlay">#66000000</color>
|
<color name="black_overlay">#66000000</color>
|
||||||
|
|
||||||
|
<color name="defaultbackground">#424242</color>
|
||||||
|
<color name="defaulttextcolor">#B3FFFFFF</color>
|
||||||
|
|
||||||
<!-- Fragments-->
|
<!-- Fragments-->
|
||||||
<color name="pumpStatusBackground">#505050</color>
|
<color name="pumpStatusBackground">#505050</color>
|
||||||
|
|
||||||
|
|
|
@ -436,8 +436,10 @@ import kotlin.math.roundToInt
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.toWrappedSingle()
|
.toWrappedSingle()
|
||||||
|
|
||||||
fun getLastBolusRecordOfType(type: Bolus.Type): Bolus? =
|
fun getLastBolusRecordOfTypeWrapped(type: Bolus.Type): Single<ValueWrapper<Bolus>> =
|
||||||
database.bolusDao.getLastBolusRecordOfType(type)
|
database.bolusDao.getLastBolusRecordOfType(type)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.toWrappedSingle()
|
||||||
|
|
||||||
fun getOldestBolusRecord(): Bolus? =
|
fun getOldestBolusRecord(): Bolus? =
|
||||||
database.bolusDao.getOldestBolusRecord()
|
database.bolusDao.getOldestBolusRecord()
|
||||||
|
|
|
@ -3,10 +3,8 @@ package info.nightscout.androidaps.database.daos
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import info.nightscout.androidaps.database.TABLE_BOLUSES
|
import info.nightscout.androidaps.database.TABLE_BOLUSES
|
||||||
import info.nightscout.androidaps.database.TABLE_BOLUS_CALCULATOR_RESULTS
|
|
||||||
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
import info.nightscout.androidaps.database.embedments.InterfaceIDs
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
|
@ -42,7 +40,7 @@ internal interface BolusDao : TraceableDao<Bolus> {
|
||||||
fun getLastBolusRecordMaybe(exclude: Bolus.Type = Bolus.Type.PRIMING): Maybe<Bolus>
|
fun getLastBolusRecordMaybe(exclude: Bolus.Type = Bolus.Type.PRIMING): Maybe<Bolus>
|
||||||
|
|
||||||
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type == :only AND referenceId IS NULL ORDER BY timestamp DESC LIMIT 1")
|
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type == :only AND referenceId IS NULL ORDER BY timestamp DESC LIMIT 1")
|
||||||
fun getLastBolusRecordOfType(only: Bolus.Type): Bolus?
|
fun getLastBolusRecordOfType(only: Bolus.Type): Maybe<Bolus>
|
||||||
|
|
||||||
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type <> :exclude AND referenceId IS NULL ORDER BY timestamp ASC LIMIT 1")
|
@Query("SELECT * FROM $TABLE_BOLUSES WHERE isValid = 1 AND type <> :exclude AND referenceId IS NULL ORDER BY timestamp ASC LIMIT 1")
|
||||||
fun getOldestBolusRecord(exclude: Bolus.Type = Bolus.Type.PRIMING): Bolus?
|
fun getOldestBolusRecord(exclude: Bolus.Type = Bolus.Type.PRIMING): Bolus?
|
||||||
|
|
Loading…
Reference in a new issue