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.general.actions.ActionsFragment
|
||||
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.maintenance.MaintenanceFragment
|
||||
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.source.BGSourceFragment
|
||||
import info.nightscout.androidaps.activities.fragments.*
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.*
|
||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||
|
||||
@Module
|
||||
|
@ -81,6 +77,7 @@ abstract class FragmentsModule {
|
|||
@ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog
|
||||
@ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog
|
||||
@ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog
|
||||
@ContributesAndroidInjector abstract fun contributesChooseOperationDialog(): ChooseOperationDialog
|
||||
@ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog
|
||||
@ContributesAndroidInjector abstract fun contributesLoopDialog(): LoopDialog
|
||||
@ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.os.Bundle
|
|||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
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.bus.RxBus
|
||||
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.overview.activities.QuickWizardListActivity
|
||||
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.rx.AapsSchedulers
|
||||
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.wizard.QuickWizard
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
@ -118,6 +121,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
@Inject lateinit var glucoseStatusProvider: GlucoseStatusProvider
|
||||
@Inject lateinit var overviewData: OverviewData
|
||||
@Inject lateinit var overviewPlugin: OverviewPlugin
|
||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||
|
||||
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.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() {
|
||||
|
|
|
@ -18,6 +18,16 @@
|
|||
android:textColor="@color/colorAcceptTempButton"
|
||||
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
|
||||
android:id="@+id/buttons_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
<color name="error_background">#66FC0000</color>
|
||||
<color name="ok_background">#323232</color>
|
||||
|
||||
<color name="defaultbackground">#424242</color>
|
||||
<color name="defaulttextcolor">#B3FFFFFF</color>
|
||||
|
||||
<color name="tempTargetBackground">#77dd77</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_target_values">Error in target values</string>
|
||||
<string name="error_in_isf_values">Error in ISF values</string>
|
||||
<string name="run_question">Run %s?</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -4,7 +4,6 @@ import dagger.android.HasAndroidInjector
|
|||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
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.triggers.Trigger
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||
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 readOnly: Boolean = false // removing, editing disabled
|
||||
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()
|
||||
|
||||
var lastRun: Long = 0
|
||||
|
@ -44,7 +44,7 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
|||
|
||||
fun addAction(action: Action) = actions.add(action)
|
||||
|
||||
fun areActionsValid() : Boolean {
|
||||
fun areActionsValid(): Boolean {
|
||||
var result = true
|
||||
for (action in actions) result = result && action.isValid()
|
||||
return result
|
||||
|
@ -59,6 +59,7 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
|||
.put("systemAction", systemAction)
|
||||
.put("readOnly", readOnly)
|
||||
.put("autoRemove", autoRemove)
|
||||
.put("userAction", userAction)
|
||||
.put("trigger", trigger.toJSON())
|
||||
.put("actions", array)
|
||||
.toString()
|
||||
|
@ -71,7 +72,8 @@ class AutomationEvent(private val injector: HasAndroidInjector) {
|
|||
systemAction = d.optBoolean("systemAction", false)
|
||||
readOnly = d.optBoolean("readOnly", 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")
|
||||
actions.clear()
|
||||
for (i in 0 until array.length()) {
|
||||
|
|
|
@ -167,14 +167,19 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
|||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
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.enabled.isChecked = event.isEnabled
|
||||
holder.binding.enabled.isEnabled = !event.readOnly
|
||||
holder.binding.iconLayout.removeAllViews()
|
||||
// trigger icons
|
||||
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) {
|
||||
addImage(res, holder.context, holder.binding.iconLayout)
|
||||
}
|
||||
|
@ -239,13 +244,15 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
|
|||
|
||||
override fun onItemDismiss(position: Int) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
||||
Runnable {
|
||||
OKDialog.showConfirmation(
|
||||
activity,
|
||||
resourceHelper.gs(R.string.removerecord) + " " + automationPlugin.at(position).title,
|
||||
{
|
||||
uel.log(Action.AUTOMATION_REMOVED, Sources.Automation, automationPlugin.at(position).title)
|
||||
automationPlugin.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
rxBus.send(EventAutomationDataChanged())
|
||||
}, Runnable { rxBus.send(EventAutomationUpdateGui()) })
|
||||
}, { rxBus.send(EventAutomationUpdateGui()) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ class AutomationPlugin @Inject constructor(
|
|||
private val config: Config,
|
||||
private val locationServiceHelper: LocationServiceHelper,
|
||||
private val dateUtil: DateUtil
|
||||
) : PluginBase(PluginDescription()
|
||||
) : PluginBase(
|
||||
PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(AutomationFragment::class.qualifiedName)
|
||||
.pluginIcon(R.drawable.ic_automation)
|
||||
|
@ -82,7 +83,8 @@ class AutomationPlugin @Inject constructor(
|
|||
|
||||
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 {
|
||||
|
@ -201,7 +203,20 @@ class AutomationPlugin @Inject constructor(
|
|||
val iterator: MutableIterator<AutomationEvent> = automationEvents.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val event = iterator.next()
|
||||
if (event.isEnabled && event.shouldRun() && event.trigger.shouldRun() && event.getPreconditions().shouldRun()) {
|
||||
if (event.isEnabled && !event.userAction && event.shouldRun())
|
||||
processEvent(event, userEventsEnabled)
|
||||
}
|
||||
// we cannot detect connected BT devices
|
||||
// so let's collect all connection/disconnections between 2 runs of processActions()
|
||||
// TriggerBTDevice can pick up and process these events
|
||||
// after processing clear events to prevent repeated actions
|
||||
btConnects.clear()
|
||||
|
||||
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) {
|
||||
|
@ -236,14 +251,6 @@ class AutomationPlugin @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
// we cannot detect connected BT devices
|
||||
// so let's collect all connection/disconnections between 2 runs of processActions()
|
||||
// TriggerBTDevice can pick up and process these events
|
||||
// after processing clear events to prevent repeated actions
|
||||
btConnects.clear()
|
||||
|
||||
storeToSP() // save last run time
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun add(event: AutomationEvent) {
|
||||
|
@ -283,6 +290,16 @@ class AutomationPlugin @Inject constructor(
|
|||
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> {
|
||||
return listOf(
|
||||
//ActionLoopDisable(injector),
|
||||
|
@ -318,7 +335,7 @@ class AutomationPlugin @Inject constructor(
|
|||
TriggerAutosensValue(injector),
|
||||
TriggerBolusAgo(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.databinding.AutomationDialogEventBinding
|
||||
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||
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.EventAutomationUpdateGui
|
||||
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.ToastUtils
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import info.nightscout.androidaps.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import javax.inject.Inject
|
||||
|
||||
class EditEventDialog : DialogFragmentWithDate() {
|
||||
|
@ -73,6 +72,8 @@ class EditEventDialog : DialogFragmentWithDate() {
|
|||
binding.inputEventTitle.setText(event.title)
|
||||
binding.inputEventTitle.isFocusable = !event.readOnly
|
||||
binding.triggerDescription.text = event.trigger.friendlyDescription()
|
||||
binding.userAction.isChecked = event.userAction
|
||||
binding.enabled.isChecked = event.isEnabled
|
||||
|
||||
binding.editTrigger.visibility = (!event.readOnly).toVisibility()
|
||||
binding.editTrigger.setOnClickListener {
|
||||
|
@ -131,9 +132,11 @@ class EditEventDialog : DialogFragmentWithDate() {
|
|||
return false
|
||||
}
|
||||
event.title = title
|
||||
event.userAction = binding.userAction.isChecked
|
||||
event.isEnabled = binding.enabled.isChecked
|
||||
// check for at least one trigger
|
||||
val con = event.trigger as TriggerConnector
|
||||
if (con.size() == 0) {
|
||||
val con = event.trigger
|
||||
if (con.size() == 0 && !event.userAction) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
||||
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.TriggerDummy
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -31,7 +31,7 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
|||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private var triggers: Trigger? = null
|
||||
private var triggers: TriggerConnector? = null
|
||||
|
||||
private var _binding: AutomationDialogEditTriggerBinding? = null
|
||||
|
||||
|
@ -39,11 +39,13 @@ class EditTriggerDialog : DialogFragmentWithDate() {
|
|||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
// load data from 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()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
|
@ -42,6 +43,7 @@ class Comparator(private val resourceHelper: ResourceHelper) : Element() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
for (c in values()) {
|
||||
|
@ -59,25 +61,24 @@ class Comparator(private val resourceHelper: ResourceHelper) : Element() {
|
|||
var value = Compare.IS_EQUAL
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val spinner = Spinner(root.context)
|
||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = spinnerArrayAdapter
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(1), 0, resourceHelper.dpToPx(1))
|
||||
}
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
value = Compare.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(value.ordinal)
|
||||
root.addView(spinner)
|
||||
setSelection(value.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
|
||||
fun setValue(compare: Compare): Comparator {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
|
@ -21,6 +22,7 @@ class ComparatorConnect(private val resourceHelper: ResourceHelper) : Element()
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
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
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val spinner = Spinner(root.context)
|
||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = spinnerArrayAdapter
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
value = Compare.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(value.ordinal)
|
||||
root.addView(spinner)
|
||||
setSelection(value.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
|
@ -21,6 +22,7 @@ class ComparatorExists(private val resourceHelper: ResourceHelper, var value: Co
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
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) {
|
||||
val spinner = Spinner(root.context)
|
||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper))
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = spinnerArrayAdapter
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Compare.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
value = Compare.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(value.ordinal)
|
||||
root.addView(spinner)
|
||||
setSelection(value.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
|
@ -26,13 +27,15 @@ class InputBg(profileFunction: ProfileFunction) : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, false, root.findViewById(R.id.ok))
|
||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
root.addView(numberPicker)
|
||||
root.addView(
|
||||
NumberPicker(root.context, null).apply {
|
||||
setParams(value, minValue, maxValue, step, decimalFormat, false, root.findViewById(R.id.ok))
|
||||
setOnValueChangedListener { value: Double -> this.value = value }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
|
||||
fun setValue(value: Double) : InputBg {
|
||||
fun setValue(value: Double): InputBg {
|
||||
this.value = value
|
||||
return this
|
||||
}
|
||||
|
@ -54,6 +57,7 @@ class InputBg(profileFunction: ProfileFunction) : Element() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val MMOL_MIN = 3.0
|
||||
const val MMOL_MAX = 20.0
|
||||
const val MGDL_MIN = 54.0
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
|
||||
class InputButton() : Element() {
|
||||
|
||||
var text: String? = null
|
||||
var runnable: Runnable? = null
|
||||
|
||||
|
@ -13,9 +15,11 @@ class InputButton() : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val button = Button(root.context)
|
||||
button.text = text
|
||||
button.setOnClickListener { runnable?.run() }
|
||||
root.addView(button)
|
||||
root.addView(
|
||||
Button(root.context).apply {
|
||||
text = text
|
||||
setOnClickListener { runnable?.run() }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,26 +1,24 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||
import info.nightscout.androidaps.database.entities.UserEntry
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
|
||||
class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element() {
|
||||
|
||||
enum class EventType (val therapyEventType: TherapyEvent.Type) {
|
||||
NOTE (TherapyEvent.Type.NOTE),
|
||||
EXERCISE (TherapyEvent.Type.EXERCISE),
|
||||
QUESTION (TherapyEvent.Type.QUESTION),
|
||||
ANNOUNCEMENT (TherapyEvent.Type.ANNOUNCEMENT);
|
||||
enum class EventType(val therapyEventType: TherapyEvent.Type) {
|
||||
NOTE(TherapyEvent.Type.NOTE),
|
||||
EXERCISE(TherapyEvent.Type.EXERCISE),
|
||||
QUESTION(TherapyEvent.Type.QUESTION),
|
||||
ANNOUNCEMENT(TherapyEvent.Type.ANNOUNCEMENT);
|
||||
|
||||
@get:StringRes val stringResWithValue: Int
|
||||
get() = when (this) {
|
||||
|
@ -46,6 +44,7 @@ class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element(
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
for (e in values()) {
|
||||
|
@ -63,25 +62,25 @@ class InputCarePortalMenu(private val resourceHelper: ResourceHelper) : Element(
|
|||
var value = EventType.NOTE
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val spinner = Spinner(root.context)
|
||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, EventType.labels(resourceHelper))
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = spinnerArrayAdapter
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, EventType.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
value = EventType.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(value.ordinal)
|
||||
root.addView(spinner)
|
||||
setSelection(value.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
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)
|
||||
val px = resourceHelper.dpToPx(10)
|
||||
|
||||
// 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.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, dateSetListener,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
})
|
||||
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, timeSetListener,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import androidx.annotation.StringRes
|
||||
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.ui.NumberPicker
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
||||
|
@ -25,6 +25,7 @@ class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
for (d in values()) {
|
||||
|
@ -61,32 +62,29 @@ class InputDelta(private val resourceHelper: ResourceHelper) : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val spinner = Spinner(root.context)
|
||||
val spinnerArrayAdapter = ArrayAdapter(root.context, R.layout.spinner_centered, DeltaType.labels(resourceHelper))
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
spinner.adapter = spinnerArrayAdapter
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, DeltaType.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
deltaType = DeltaType.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(deltaType.ordinal)
|
||||
val numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null)
|
||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
val l = LinearLayout(root.context)
|
||||
l.orientation = LinearLayout.VERTICAL
|
||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
l.addView(spinner)
|
||||
l.addView(numberPicker)
|
||||
root.addView(l)
|
||||
setSelection(deltaType.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
root.addView(
|
||||
NumberPicker(root.context, null).apply {
|
||||
setParams(value, minValue, maxValue, step, decimalFormat, true, null, null)
|
||||
setOnValueChangedListener { value: Double -> this.value = value }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class InputDouble() : Element() {
|
||||
|
||||
var value = 0.0
|
||||
private var minValue = 0.0
|
||||
private var maxValue = 0.0
|
||||
|
@ -30,9 +32,11 @@ class InputDouble() : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker?.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||
numberPicker?.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
numberPicker = NumberPicker(root.context, null).apply {
|
||||
setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||
setOnValueChangedListener { value: Double -> this.value = value }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
}
|
||||
root.addView(numberPicker)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
|
@ -25,30 +25,24 @@ class InputDropdownMenu(private val resourceHelper: ResourceHelper) : Element()
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val spinner = Spinner(root.context)
|
||||
spinner.adapter = ArrayAdapter(
|
||||
root.context,
|
||||
R.layout.spinner_centered, itemList
|
||||
).also {
|
||||
it.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, itemList).apply {
|
||||
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) {
|
||||
setValue(itemList[position].toString())
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
for (i in 0 until itemList.size) if (itemList[i] == value) spinner.setSelection(i)
|
||||
root.addView(LinearLayout(root.context).also {
|
||||
it.orientation = LinearLayout.VERTICAL
|
||||
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
it.addView(spinner)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
for (i in 0 until itemList.size) if (itemList[i] == value) setSelection(i)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
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.setOnValueChangedListener { value: Double -> this.value = value.toInt() }
|
||||
numberPicker.gravity = Gravity.CENTER_HORIZONTAL
|
||||
root.addView(numberPicker)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class InputInsulin() : Element() {
|
||||
|
||||
var value = 0.0
|
||||
|
||||
constructor(another: InputInsulin) : this() {
|
||||
|
@ -13,10 +15,12 @@ class InputInsulin() : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker.setParams(0.0, -20.0, 20.0, 0.1, DecimalFormat("0.0"), true, root.findViewById(R.id.ok))
|
||||
numberPicker.value = value
|
||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
root.addView(numberPicker)
|
||||
root.addView(
|
||||
NumberPicker(root.context, null).apply {
|
||||
setParams(0.0, -20.0, 20.0, 0.1, DecimalFormat("0.0"), true, root.findViewById(R.id.ok))
|
||||
value = value
|
||||
setOnValueChangedListener { value: Double -> this.value = value }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
|
@ -30,6 +31,7 @@ class InputLocationMode(private val resourceHelper: ResourceHelper) : Element()
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun labels(resourceHelper: ResourceHelper): List<String> {
|
||||
val list: MutableList<String> = ArrayList()
|
||||
for (c in values()) {
|
||||
|
@ -47,24 +49,24 @@ class InputLocationMode(private val resourceHelper: ResourceHelper) : Element()
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Mode.labels(resourceHelper))
|
||||
val spinner = Spinner(root.context)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
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 {
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, Mode.labels(resourceHelper)).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
val spinnerParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
layoutParams = spinnerParams
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
value = Mode.values()[position]
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
spinner.setSelection(value.ordinal)
|
||||
root.addView(spinner)
|
||||
setSelection(value.ordinal)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.utils.ui.NumberPicker
|
||||
|
@ -14,11 +15,13 @@ class InputPercent() : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker.setParams(100.0, MIN, MAX, 5.0, DecimalFormat("0"), true, root.findViewById(R.id.ok))
|
||||
numberPicker.value = value
|
||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
root.addView(numberPicker)
|
||||
root.addView(
|
||||
NumberPicker(root.context, null).apply {
|
||||
setParams(100.0, MIN, MAX, 5.0, DecimalFormat("0"), true, root.findViewById(R.id.ok))
|
||||
value = value
|
||||
setOnValueChangedListener { value: Double -> this.value = value }
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
|
@ -17,28 +17,24 @@ class InputProfileName(private val resourceHelper: ResourceHelper, private val a
|
|||
override fun addToLayout(root: LinearLayout) {
|
||||
val profileStore = activePlugin.activeProfileSource.profile ?: return
|
||||
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 {
|
||||
|
||||
root.addView(
|
||||
Spinner(root.context).apply {
|
||||
adapter = ArrayAdapter(root.context, R.layout.spinner_centered, profileList).apply {
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
}
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, resourceHelper.dpToPx(4), 0, resourceHelper.dpToPx(4))
|
||||
}
|
||||
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) spinner.setSelection(i)
|
||||
val l = LinearLayout(root.context)
|
||||
l.orientation = LinearLayout.VERTICAL
|
||||
l.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
l.addView(spinner)
|
||||
root.addView(l)
|
||||
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.TextWatcher
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
|
||||
class InputString(var value: String = "") : Element() {
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: 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) {
|
||||
val editText = EditText(root.context)
|
||||
editText.setText(value)
|
||||
editText.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
editText.addTextChangedListener(textWatcher)
|
||||
root.addView(editText)
|
||||
root.addView(
|
||||
EditText(root.context).apply {
|
||||
setText(value)
|
||||
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
addTextChangedListener(textWatcher)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.automation.R
|
||||
|
@ -9,6 +10,7 @@ import info.nightscout.androidaps.utils.ui.NumberPicker
|
|||
import java.text.DecimalFormat
|
||||
|
||||
class InputTempTarget(profileFunction: ProfileFunction) : Element() {
|
||||
|
||||
var units: GlucoseUnit = GlucoseUnit.MGDL
|
||||
var value = 0.0
|
||||
|
||||
|
@ -38,9 +40,12 @@ class InputTempTarget(profileFunction: ProfileFunction) : Element() {
|
|||
step = 1.0
|
||||
decimalFormat = DecimalFormat("0")
|
||||
}
|
||||
val numberPicker = NumberPicker(root.context, null)
|
||||
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||
numberPicker.setOnValueChangedListener { value: Double -> this.value = value }
|
||||
root.addView(numberPicker)
|
||||
root.addView(
|
||||
NumberPicker(root.context, null).apply {
|
||||
setParams(value, minValue, maxValue, step, decimalFormat, true, root.findViewById(R.id.ok))
|
||||
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.graphics.Typeface
|
||||
import android.text.format.DateFormat
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
|
@ -18,37 +19,38 @@ class InputTime(private val resourceHelper: ResourceHelper, private val dateUtil
|
|||
var value: Int = getMinSinceMidnight(dateUtil.now())
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
val label = TextView(root.context)
|
||||
val startButton = TextView(root.context)
|
||||
startButton.text = dateUtil.timeString(toMills(value))
|
||||
|
||||
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||
value = 60 * hour + minute
|
||||
startButton.text = dateUtil.timeString(toMills(value))
|
||||
}
|
||||
|
||||
startButton.setOnClickListener {
|
||||
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)
|
||||
})
|
||||
addView(
|
||||
TextView(root.context).apply {
|
||||
text = dateUtil.timeString(toMills(value))
|
||||
val px = resourceHelper.dpToPx(10)
|
||||
setPadding(px, px, px, px)
|
||||
setOnClickListener {
|
||||
root.context?.let {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = toMills(value)
|
||||
TimePickerDialog(it, startTimeSetListener,
|
||||
TimePickerDialog(
|
||||
it,
|
||||
{ _, hour, minute ->
|
||||
value = 60 * hour + minute
|
||||
text = dateUtil.timeString(toMills(value))
|
||||
},
|
||||
cal.get(Calendar.HOUR_OF_DAY),
|
||||
cal.get(Calendar.MINUTE),
|
||||
DateFormat.is24HourFormat(it)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
val px = resourceHelper.dpToPx(10)
|
||||
label.text = resourceHelper.gs(R.string.atspecifiedtime, "")
|
||||
label.setTypeface(label.typeface, Typeface.BOLD)
|
||||
startButton.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(startButton)
|
||||
root.addView(l)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
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.graphics.Typeface
|
||||
import android.text.format.DateFormat
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
|
@ -19,59 +20,62 @@ class InputTimeRange(private val resourceHelper: ResourceHelper, private val dat
|
|||
var end: Int = getMinSinceMidnight(dateUtil.now())
|
||||
|
||||
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 px = resourceHelper.dpToPx(10)
|
||||
|
||||
val startTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||
start = 60 * hour + minute
|
||||
startButton.text = dateUtil.timeString(toMills(start))
|
||||
}
|
||||
|
||||
startButton.setOnClickListener {
|
||||
root.addView(
|
||||
TextView(root.context).apply {
|
||||
text = resourceHelper.gs(R.string.between)
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
})
|
||||
root.addView(
|
||||
LinearLayout(root.context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
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, startTimeSetListener,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
val endTimeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
|
||||
end = 60 * hour + minute
|
||||
endButton.text = dateUtil.timeString(toMills(end))
|
||||
}
|
||||
|
||||
endButton.setOnClickListener {
|
||||
})
|
||||
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, endTimeSetListener,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
val px = resourceHelper.dpToPx(10)
|
||||
label.text = resourceHelper.gs(R.string.between)
|
||||
label.setTypeface(label.typeface, Typeface.BOLD)
|
||||
startButton.setPadding(px, px, px, px)
|
||||
endButton.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(startButton)
|
||||
l.addView(endButton)
|
||||
root.addView(l)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
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 androidx.annotation.StringRes
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.utils.ui.WeekdayPicker
|
||||
import java.util.*
|
||||
|
@ -20,6 +19,7 @@ class InputWeekDay : Element() {
|
|||
get() = shortNames[ordinal]
|
||||
|
||||
companion object {
|
||||
|
||||
private val calendarInts = intArrayOf(
|
||||
Calendar.MONDAY,
|
||||
Calendar.TUESDAY,
|
||||
|
@ -76,10 +76,11 @@ class InputWeekDay : Element() {
|
|||
}
|
||||
|
||||
override fun addToLayout(root: LinearLayout) {
|
||||
root.addView(
|
||||
WeekdayPicker(root.context).apply {
|
||||
setSelectedDays(getSelectedDays())
|
||||
setOnWeekdaysChangeListener { i: Int, selected: Boolean -> set(DayOfWeek.fromCalendarInt(i), selected) }
|
||||
root.addView(this)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.elements
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.ViewGroup
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TableLayout
|
||||
import android.widget.TextView
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
|
||||
|
@ -15,35 +14,27 @@ class LabelWithElement(
|
|||
) : Element() {
|
||||
|
||||
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
|
||||
var px = resourceHelper.dpToPx(10)
|
||||
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)
|
||||
}
|
||||
val px = resourceHelper.dpToPx(1)
|
||||
|
||||
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
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import info.nightscout.androidaps.automation.R
|
||||
|
||||
class LayoutBuilder {
|
||||
|
||||
|
@ -16,8 +20,21 @@ class LayoutBuilder {
|
|||
}
|
||||
|
||||
fun build(layout: LinearLayout) {
|
||||
for (e in mElements) {
|
||||
e.addToLayout(layout)
|
||||
val elementLayout = LinearLayout(layout.context).apply {
|
||||
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.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class StaticLabel(private val resourceHelper: ResourceHelper) : Element() {
|
||||
|
||||
|
@ -25,24 +23,25 @@ class StaticLabel(private val resourceHelper: ResourceHelper) : Element() {
|
|||
}
|
||||
|
||||
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 textView = TextView(root.context)
|
||||
textView.text = label
|
||||
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
params.weight = 1.0f
|
||||
textView.layoutParams = params
|
||||
textView.setPadding(px, px, px, px)
|
||||
textView.setTypeface(textView.typeface, Typeface.BOLD)
|
||||
headerLayout.addView(textView)
|
||||
trigger?.let {
|
||||
headerLayout.addView(it.createDeleteButton(root.context, it))
|
||||
headerLayout.addView(it.createCloneButton(root.context, it))
|
||||
root.addView(
|
||||
LinearLayout(root.context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
setBackgroundColor(resourceHelper.gc(android.R.color.black))
|
||||
addView(
|
||||
TextView(root.context).apply {
|
||||
text = label
|
||||
layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
weight = 1.0f
|
||||
}
|
||||
root.addView(headerLayout)
|
||||
setPadding(px, px, px, px)
|
||||
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
|
||||
|
||||
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 duplicate(): Trigger
|
||||
|
||||
private fun scanForActivity(cont: Context?): AppCompatActivity? {
|
||||
fun scanForActivity(cont: Context?): AppCompatActivity? {
|
||||
return when (cont) {
|
||||
null -> null
|
||||
is AppCompatActivity -> cont
|
||||
|
@ -84,27 +84,19 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
|||
//return (clazz.primaryConstructor?.call(injector) as Trigger).fromJSON(data?.toString() ?: "")
|
||||
return when (type) {
|
||||
TriggerAutosensValue::class.java.name, // backward compatibility
|
||||
TriggerAutosensValue::class.java.simpleName -> TriggerAutosensValue(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerAutosensValue::class.java.simpleName -> TriggerAutosensValue(injector).fromJSON(data.toString())
|
||||
TriggerBg::class.java.name,
|
||||
TriggerBg::class.java.simpleName -> TriggerBg(injector).fromJSON(data.toString())
|
||||
TriggerBolusAgo::class.java.name,
|
||||
TriggerBolusAgo::class.java.simpleName -> TriggerBolusAgo(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerBolusAgo::class.java.simpleName -> TriggerBolusAgo(injector).fromJSON(data.toString())
|
||||
TriggerBTDevice::class.java.name,
|
||||
TriggerBTDevice::class.java.simpleName -> TriggerBTDevice(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerBTDevice::class.java.simpleName -> TriggerBTDevice(injector).fromJSON(data.toString())
|
||||
TriggerIob::class.java.name,
|
||||
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
||||
TriggerCOB::class.java.name,
|
||||
TriggerCOB::class.java.simpleName -> TriggerCOB(injector).fromJSON(data.toString())
|
||||
TriggerConnector::class.java.name,
|
||||
TriggerConnector::class.java.simpleName -> TriggerConnector(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerConnector::class.java.simpleName -> TriggerConnector(injector).fromJSON(data.toString())
|
||||
TriggerDelta::class.java.name,
|
||||
TriggerDelta::class.java.simpleName -> TriggerDelta(injector).fromJSON(data.toString())
|
||||
TriggerDummy::class.java.name,
|
||||
|
@ -112,55 +104,36 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
|||
TriggerIob::class.java.name,
|
||||
TriggerIob::class.java.simpleName -> TriggerIob(injector).fromJSON(data.toString())
|
||||
TriggerLocation::class.java.name,
|
||||
TriggerLocation::class.java.simpleName -> TriggerLocation(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerLocation::class.java.simpleName -> TriggerLocation(injector).fromJSON(data.toString())
|
||||
TriggerProfilePercent::class.java.name,
|
||||
TriggerProfilePercent::class.java.simpleName -> TriggerProfilePercent(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerProfilePercent::class.java.simpleName -> TriggerProfilePercent(injector).fromJSON(data.toString())
|
||||
TriggerPumpLastConnection::class.java.name,
|
||||
TriggerPumpLastConnection::class.java.simpleName -> TriggerPumpLastConnection(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerPumpLastConnection::class.java.simpleName -> TriggerPumpLastConnection(injector).fromJSON(data.toString())
|
||||
TriggerRecurringTime::class.java.name,
|
||||
TriggerRecurringTime::class.java.simpleName -> TriggerRecurringTime(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerRecurringTime::class.java.simpleName -> TriggerRecurringTime(injector).fromJSON(data.toString())
|
||||
TriggerTempTarget::class.java.name,
|
||||
TriggerTempTarget::class.java.simpleName -> TriggerTempTarget(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerTempTarget::class.java.simpleName -> TriggerTempTarget(injector).fromJSON(data.toString())
|
||||
TriggerTempTargetValue::class.java.name,
|
||||
TriggerTempTargetValue::class.java.simpleName -> TriggerTempTargetValue(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerTempTargetValue::class.java.simpleName -> TriggerTempTargetValue(injector).fromJSON(data.toString())
|
||||
TriggerTime::class.java.name,
|
||||
TriggerTime::class.java.simpleName -> TriggerTime(injector).fromJSON(data.toString())
|
||||
TriggerTimeRange::class.java.name,
|
||||
TriggerTimeRange::class.java.simpleName -> TriggerTimeRange(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerTimeRange::class.java.simpleName -> TriggerTimeRange(injector).fromJSON(data.toString())
|
||||
TriggerWifiSsid::class.java.name,
|
||||
TriggerWifiSsid::class.java.simpleName -> TriggerWifiSsid(injector).fromJSON(
|
||||
data.toString()
|
||||
)
|
||||
TriggerWifiSsid::class.java.simpleName -> TriggerWifiSsid(injector).fromJSON(data.toString())
|
||||
else -> TriggerConnector(injector)
|
||||
}
|
||||
}
|
||||
|
||||
fun createAddButton(context: Context, trigger: TriggerConnector): ImageButton {
|
||||
fun createAddButton(context: Context, trigger: TriggerConnector): ImageButton =
|
||||
// Button [+]
|
||||
val buttonAdd = ImageButton(context)
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.gravity = Gravity.CENTER
|
||||
buttonAdd.layoutParams = params
|
||||
buttonAdd.setImageResource(R.drawable.ic_add)
|
||||
buttonAdd.contentDescription = resourceHelper.gs(R.string.add_short)
|
||||
buttonAdd.setOnClickListener {
|
||||
ImageButton(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
gravity = Gravity.CENTER
|
||||
}
|
||||
setImageResource(R.drawable.ic_add)
|
||||
contentDescription = resourceHelper.gs(R.string.add_short)
|
||||
setOnClickListener {
|
||||
scanForActivity(context)?.supportFragmentManager?.let {
|
||||
val dialog = ChooseTriggerDialog()
|
||||
dialog.show(it, "ChooseTriggerDialog")
|
||||
|
@ -172,40 +145,32 @@ abstract class Trigger(val injector: HasAndroidInjector) {
|
|||
})
|
||||
}
|
||||
}
|
||||
return buttonAdd
|
||||
}
|
||||
|
||||
fun createDeleteButton(context: Context, trigger: Trigger): ImageButton {
|
||||
fun createDeleteButton(context: Context, trigger: Trigger): ImageButton =
|
||||
// Button [-]
|
||||
val buttonRemove = ImageButton(context)
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.gravity = Gravity.CENTER
|
||||
buttonRemove.layoutParams = params
|
||||
buttonRemove.setImageResource(R.drawable.ic_remove)
|
||||
buttonRemove.contentDescription = resourceHelper.gs(R.string.delete_short)
|
||||
buttonRemove.setOnClickListener {
|
||||
ImageButton(context).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
gravity = Gravity.CENTER
|
||||
}
|
||||
setImageResource(R.drawable.ic_remove)
|
||||
contentDescription = resourceHelper.gs(R.string.delete_short)
|
||||
setOnClickListener {
|
||||
rxBus.send(EventTriggerRemove(trigger))
|
||||
}
|
||||
return buttonRemove
|
||||
}
|
||||
|
||||
fun createCloneButton(context: Context, trigger: Trigger): ImageButton {
|
||||
fun createCloneButton(context: Context, trigger: Trigger): ImageButton =
|
||||
// Button [*]
|
||||
val buttonClone = ImageButton(context)
|
||||
val params = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.gravity = Gravity.CENTER
|
||||
buttonClone.layoutParams = params
|
||||
buttonClone.setImageResource(R.drawable.ic_clone)
|
||||
buttonClone.contentDescription = resourceHelper.gs(R.string.copy_short)
|
||||
buttonClone.setOnClickListener {
|
||||
ImageButton(context).apply {
|
||||
val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
gravity = Gravity.CENTER
|
||||
}
|
||||
layoutParams = params
|
||||
setImageResource(R.drawable.ic_clone)
|
||||
contentDescription = resourceHelper.gs(R.string.copy_short)
|
||||
setOnClickListener {
|
||||
rxBus.send(EventTriggerClone(trigger))
|
||||
}
|
||||
return buttonClone
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.widget.LinearLayout
|
|||
import com.google.common.base.Optional
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||
|
@ -36,7 +37,8 @@ class TriggerBolusAgo(injector: HasAndroidInjector) : Trigger(injector) {
|
|||
}
|
||||
|
||||
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)
|
||||
return if (comparator.value == Comparator.Compare.IS_NOT_AVAILABLE) {
|
||||
aapsLogger.debug(LTag.AUTOMATION, "Ready for execution: " + friendlyDescription())
|
||||
|
@ -81,7 +83,7 @@ class TriggerBolusAgo(injector: HasAndroidInjector) : Trigger(injector) {
|
|||
LayoutBuilder()
|
||||
.add(StaticLabel(resourceHelper, R.string.lastboluslabel, this))
|
||||
.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)
|
||||
}
|
||||
}
|
|
@ -1,19 +1,20 @@
|
|||
package info.nightscout.androidaps.plugins.general.automation.triggers
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.graphics.Typeface
|
||||
import android.view.Gravity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.common.base.Optional
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.automation.R
|
||||
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.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.ui.VerticalTextView
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
@ -119,51 +120,75 @@ class TriggerConnector(injector: HasAndroidInjector) : Trigger(injector) {
|
|||
override fun duplicate(): Trigger = TriggerConnector(injector, connectorType)
|
||||
|
||||
override fun generateDialog(root: LinearLayout) {
|
||||
val padding = resourceHelper.dpToPx(5)
|
||||
root.setPadding(padding, padding, padding, padding)
|
||||
root.setBackgroundResource(R.drawable.border_automation_unit)
|
||||
// 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)
|
||||
val mainLayout = LinearLayout(root.context).also {
|
||||
it.orientation = LinearLayout.HORIZONTAL
|
||||
it.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
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)
|
||||
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)
|
||||
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 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])
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
return spinner
|
||||
}
|
||||
}
|
|
@ -55,6 +55,12 @@ class TriggerProfilePercent(injector: HasAndroidInjector) : Trigger(injector) {
|
|||
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())
|
||||
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:minWidth="300dp"
|
||||
android:orientation="vertical"
|
||||
tools:context=".plugins.general.automation.dialogs.EditEventDialog">
|
||||
tools:context="info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -45,7 +45,7 @@
|
|||
android:id="@+id/layoutTrigger"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:padding="0dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<include layout="@layout/okcancel" />
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
android:focusableInTouchMode="true"
|
||||
android:minWidth="300dp"
|
||||
android:orientation="vertical"
|
||||
tools:context=".plugins.general.automation.dialogs.EditEventDialog">
|
||||
tools:context="info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
|
@ -29,17 +29,23 @@
|
|||
app:srcCompat="@drawable/ic_action_orange_48dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/automation_event"
|
||||
android:textAlignment="center"
|
||||
android:layout_weight="1"
|
||||
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
|
||||
android:id="@+id/spacer"
|
||||
|
@ -54,6 +60,27 @@
|
|||
android:orientation="vertical"
|
||||
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
|
||||
android:id="@+id/inputEventTitle"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -107,12 +107,13 @@
|
|||
<string name="edit_short">EDIT</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_operation_type">Choose a operation type</string>
|
||||
<string name="triggers">Triggers:</string>
|
||||
<string name="remove_label">REMOVE</string>
|
||||
<string name="preconditions">Preconditions:</string>
|
||||
<string name="automation_event">Automation event</string>
|
||||
<string name="reorder_label">Reorder</string>
|
||||
<string name="key_automation_settings" translatable="false">automation_settings</string>
|
||||
|
||||
<string name="user_action">User action</string>
|
||||
|
||||
</resources>
|
|
@ -8,6 +8,7 @@ import info.nightscout.androidaps.interfaces.Loop
|
|||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
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.triggers.TriggerConnector
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnectorTest
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerDummy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
|
@ -44,11 +45,12 @@ class AutomationEventTest : TestBase() {
|
|||
// create test object
|
||||
val event = AutomationEvent(injector)
|
||||
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))
|
||||
|
||||
// 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())
|
||||
|
||||
// clone
|
||||
|
|
|
@ -2,8 +2,10 @@ package info.nightscout.androidaps.plugins.general.automation.triggers
|
|||
|
||||
import com.google.common.base.Optional
|
||||
import info.nightscout.androidaps.automation.R
|
||||
import info.nightscout.androidaps.database.ValueWrapper
|
||||
import info.nightscout.androidaps.database.entities.Bolus
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator
|
||||
import io.reactivex.Single
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert
|
||||
|
@ -22,13 +24,18 @@ class TriggerBolusAgoTest : TriggerTestBase() {
|
|||
|
||||
@Test
|
||||
fun shouldRunTest() {
|
||||
`when`(repository.getLastBolusRecordOfType(Bolus.Type.NORMAL)).thenReturn(
|
||||
// Set last bolus time to now
|
||||
`when`(repository.getLastBolusRecordOfTypeWrapped(Bolus.Type.NORMAL)).thenReturn(
|
||||
Single.just(
|
||||
ValueWrapper.Existing(
|
||||
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
|
||||
var t = TriggerBolusAgo(injector).setValue(110).comparator(Comparator.Compare.IS_EQUAL)
|
||||
Assert.assertEquals(110, t.minutesAgo.value)
|
||||
|
@ -51,13 +58,18 @@ class TriggerBolusAgoTest : TriggerTestBase() {
|
|||
Assert.assertTrue(t.shouldRun())
|
||||
t = TriggerBolusAgo(injector).setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER)
|
||||
Assert.assertTrue(t.shouldRun())
|
||||
`when`(repository.getLastBolusRecordOfType(Bolus.Type.NORMAL)).thenReturn(
|
||||
// Set last bolus time to 0
|
||||
`when`(repository.getLastBolusRecordOfTypeWrapped(Bolus.Type.NORMAL)).thenReturn(
|
||||
Single.just(
|
||||
ValueWrapper.Existing(
|
||||
Bolus(
|
||||
timestamp = 0L,
|
||||
timestamp = 0,
|
||||
amount = 0.0,
|
||||
type = Bolus.Type.NORMAL
|
||||
)
|
||||
) // Set last bolus time to 0
|
||||
)
|
||||
)
|
||||
)
|
||||
t = TriggerBolusAgo(injector).comparator(Comparator.Compare.IS_NOT_AVAILABLE)
|
||||
Assert.assertTrue(t.shouldRun())
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class TriggerProfilePercentTest : TriggerTestBase() {
|
|||
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 t2 = TriggerDummy(injector).instantiate(JSONObject(t.toJSON())) as TriggerProfilePercent
|
||||
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.comparator.value)
|
||||
|
|
|
@ -14,11 +14,11 @@ object OKDialog {
|
|||
@SuppressLint("InflateParams")
|
||||
fun show(context: Context, title: String, message: String, runnable: Runnable? = null) {
|
||||
var okClicked = false
|
||||
var notEmptytitle = title
|
||||
if (notEmptytitle.isEmpty()) notEmptytitle = context.getString(R.string.message)
|
||||
var notEmptyTitle = title
|
||||
if (notEmptyTitle.isEmpty()) notEmptyTitle = context.getString(R.string.message)
|
||||
|
||||
AlertDialogHelper.Builder(context)
|
||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, notEmptytitle))
|
||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, notEmptyTitle))
|
||||
.setMessage(message)
|
||||
.setPositiveButton(context.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
||||
if (okClicked) return@setPositiveButton
|
||||
|
@ -36,11 +36,11 @@ object OKDialog {
|
|||
@SuppressLint("InflateParams")
|
||||
fun show(activity: FragmentActivity, title: String, message: Spanned, runnable: Runnable? = null) {
|
||||
var okClicked = false
|
||||
var notEmptytitle = title
|
||||
if (notEmptytitle.isEmpty()) notEmptytitle = activity.getString(R.string.message)
|
||||
var notEmptyTitle = title
|
||||
if (notEmptyTitle.isEmpty()) notEmptyTitle = activity.getString(R.string.message)
|
||||
|
||||
AlertDialogHelper.Builder(activity)
|
||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, notEmptytitle))
|
||||
.setCustomTitle(AlertDialogHelper.buildCustomTitle(activity, notEmptyTitle))
|
||||
.setMessage(message)
|
||||
.setPositiveButton(activity.getString(R.string.ok)) { dialog: DialogInterface, _: Int ->
|
||||
if (okClicked) return@setPositiveButton
|
||||
|
|
|
@ -21,5 +21,6 @@ interface ResourceHelper {
|
|||
fun decodeResource(id : Int) : Bitmap
|
||||
fun getDisplayMetrics(): DisplayMetrics
|
||||
fun dpToPx(dp: Int): Int
|
||||
fun dpToPx(dp: Float): Int
|
||||
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 =
|
||||
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)) {
|
||||
setLocale(Locale.ENGLISH)
|
||||
context.createConfigurationContext(this).getString(id, args)
|
||||
|
@ -51,7 +51,7 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
|||
override fun decodeResource(id: Int): Bitmap =
|
||||
BitmapFactory.decodeResource(context.resources, id)
|
||||
|
||||
override fun getDisplayMetrics():DisplayMetrics =
|
||||
override fun getDisplayMetrics(): DisplayMetrics =
|
||||
context.resources.displayMetrics
|
||||
|
||||
override fun dpToPx(dp: Int): Int {
|
||||
|
@ -59,5 +59,10 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont
|
|||
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)
|
||||
-->
|
||||
<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_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
@ -19,7 +20,7 @@
|
|||
android:id="@+id/alertdialog_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:tint="?dialogTitleIconTint" />
|
||||
app:tint="?dialogTitleIconTint" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alertdialog_title"
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
<color name="cardColorBackground">#121212</color>
|
||||
<color name="black_overlay">#66000000</color>
|
||||
|
||||
<color name="defaultbackground">#424242</color>
|
||||
<color name="defaulttextcolor">#B3FFFFFF</color>
|
||||
|
||||
<!-- Fragments-->
|
||||
<color name="pumpStatusBackground">#505050</color>
|
||||
|
||||
|
|
|
@ -436,8 +436,10 @@ import kotlin.math.roundToInt
|
|||
.subscribeOn(Schedulers.io())
|
||||
.toWrappedSingle()
|
||||
|
||||
fun getLastBolusRecordOfType(type: Bolus.Type): Bolus? =
|
||||
fun getLastBolusRecordOfTypeWrapped(type: Bolus.Type): Single<ValueWrapper<Bolus>> =
|
||||
database.bolusDao.getLastBolusRecordOfType(type)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.toWrappedSingle()
|
||||
|
||||
fun getOldestBolusRecord(): Bolus? =
|
||||
database.bolusDao.getOldestBolusRecord()
|
||||
|
|
|
@ -3,10 +3,8 @@ package info.nightscout.androidaps.database.daos
|
|||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
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.entities.Bolus
|
||||
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
|
||||
|
@ -42,7 +40,7 @@ internal interface BolusDao : TraceableDao<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")
|
||||
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")
|
||||
fun getOldestBolusRecord(exclude: Bolus.Type = Bolus.Type.PRIMING): Bolus?
|
||||
|
|
Loading…
Reference in a new issue