adding, removing triggers properly

This commit is contained in:
Milos Kozak 2020-01-06 00:38:37 +01:00
parent e3766a229b
commit 1eb375af09
25 changed files with 244 additions and 280 deletions

View file

@ -30,7 +30,7 @@ class AutomationEvent(private val mainApp: MainApp) {
fun getPreconditions(): TriggerConnector {
val trigger = TriggerConnector(mainApp, TriggerConnector.Type.AND)
for (action in actions) {
action.precondition?.let { trigger.add(it) }
action.precondition?.let { trigger.list.add(it) }
}
return trigger
}

View file

@ -213,6 +213,7 @@ class AutomationPlugin @Inject constructor(
fun getTriggerDummyObjects(): List<Trigger> {
return listOf(
TriggerConnector(mainApp),
TriggerTime(mainApp),
TriggerRecurringTime(mainApp),
TriggerTimeRange(mainApp),

View file

@ -9,8 +9,16 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerChanged
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerClone
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerRemove
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 info.nightscout.androidaps.utils.extensions.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
import org.json.JSONObject
import javax.inject.Inject
@ -18,14 +26,17 @@ import javax.inject.Inject
class EditTriggerDialog : DialogFragmentWithDate() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var mainApp: MainApp
@Inject lateinit var fabricPrivacy: FabricPrivacy
private var trigger: Trigger? = null
private var disposable: CompositeDisposable = CompositeDisposable()
private var triggers: Trigger? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// load data from bundle
(savedInstanceState ?: arguments)?.let { bundle ->
bundle.getString("trigger")?.let { trigger = TriggerDummy(mainApp).instantiate(JSONObject(it)) }
bundle.getString("trigger")?.let { triggers = TriggerDummy(mainApp).instantiate(JSONObject(it)) }
}
onCreateViewGeneral()
@ -35,17 +46,58 @@ class EditTriggerDialog : DialogFragmentWithDate() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
disposable += rxBus
.toObservable(EventTriggerChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
automation_layoutTrigger.removeAllViews()
triggers?.generateDialog(automation_layoutTrigger)
}, { fabricPrivacy.logException(it) })
disposable += rxBus
.toObservable(EventTriggerRemove::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
findParent(triggers, it.trigger)?.list?.remove(it.trigger)
automation_layoutTrigger.removeAllViews()
triggers?.generateDialog(automation_layoutTrigger)
}, { fabricPrivacy.logException(it) })
disposable += rxBus
.toObservable(EventTriggerClone::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
findParent(triggers, it.trigger)?.list?.add(it.trigger.duplicate())
automation_layoutTrigger.removeAllViews()
triggers?.generateDialog(automation_layoutTrigger)
}, { fabricPrivacy.logException(it) })
// display root trigger
trigger?.generateDialog(automation_layoutTrigger)
triggers?.generateDialog(automation_layoutTrigger)
}
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
}
override fun submit(): Boolean {
trigger?.let { trigger -> rxBus.send(EventAutomationUpdateTrigger(trigger)) }
triggers?.let { trigger -> rxBus.send(EventAutomationUpdateTrigger(trigger)) }
return true
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
trigger?.let { savedInstanceState.putString("trigger", it.toJSON()) }
triggers?.let { savedInstanceState.putString("trigger", it.toJSON()) }
}
private fun findParent(where: Trigger?, what: Trigger): TriggerConnector? {
if (where == null) return null
if (where is TriggerConnector) {
for (i in where.list) {
if (i == what) return where
if (i is TriggerConnector) return findParent(i, what)
}
}
return null
}
}

View file

@ -1,185 +0,0 @@
package info.nightscout.androidaps.plugins.general.automation.dialogs;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import androidx.fragment.app.FragmentManager;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
public class TriggerListAdapter {
private final LinearLayout mRootLayout;
private final Context mContext;
private final TriggerConnector rootTrigger;
private final MainApp mainApp;
private final ResourceHelper resourceHelper;
public TriggerListAdapter(MainApp mainApp, ResourceHelper resourceHelper, LinearLayout rootLayout, TriggerConnector rootTrigger) {
mRootLayout = rootLayout;
this.mainApp = mainApp;
this.resourceHelper = resourceHelper;
mContext = rootLayout.getContext();
this.rootTrigger = rootTrigger;
build(rootLayout.getContext());
}
private void destroy() {
mRootLayout.removeAllViews();
}
private void rebuild(Context context) {
destroy();
build(context);
}
private void build(Context context) {
FragmentManager fragmentManager = Trigger.scanForActivity(context).getSupportFragmentManager();
for (int i = 0; i < rootTrigger.size(); ++i) {
final Trigger trigger = rootTrigger.get(i);
// spinner
if (i > 0) {
createSpinner(trigger, context);
}
// trigger layout
trigger.generateDialog(mRootLayout);
// buttons
createButtons(mRootLayout, trigger, context);
}
if (rootTrigger.size() == 0) {
Button buttonAdd = new Button(mContext);
buttonAdd.setText(resourceHelper.gs(R.string.addnew));
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
dialog.setOnClickListener(newTriggerObject -> {
rootTrigger.add(newTriggerObject);
rebuild(context);
});
dialog.show(fragmentManager, "ChooseTriggerDialog");
});
mRootLayout.addView(buttonAdd);
}
}
private Spinner createSpinner() {
Spinner spinner = new Spinner(mContext);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, R.layout.spinner_centered, TriggerConnector.Type.AND.labels(resourceHelper));
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
return spinner;
}
private void createSpinner(Trigger trigger, Context context) {
final TriggerConnector connector = trigger.getConnector();
final int initialPosition = connector.getConnectorType().ordinal();
Spinner spinner = createSpinner();
spinner.setSelection(initialPosition);
spinner.setBackgroundColor(resourceHelper.gc(R.color.black_overlay));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, resourceHelper.dpToPx(8), 0, resourceHelper.dpToPx(8));
spinner.setLayoutParams(params);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position != initialPosition) {
// connector type changed
changeConnector(context, trigger, connector, TriggerConnector.Type.values()[position]);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mRootLayout.addView(spinner);
}
private void createButtons(LinearLayout rootLayout, Trigger trigger, Context context) {
FragmentManager fragmentManager = Trigger.scanForActivity(context).getSupportFragmentManager();
// do not create buttons for TriggerConnector
if (trigger instanceof TriggerConnector) {
return;
}
// Button Layout
LinearLayout buttonLayout = new LinearLayout(mContext);
buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
// Button [-]
Button buttonRemove = new Button(mContext);
buttonRemove.setText(resourceHelper.gs(R.string.delete_short));
buttonRemove.setOnClickListener(v -> {
final TriggerConnector connector = trigger.getConnector();
connector.remove(trigger);
connector.simplify();
rebuild(context);
});
buttonLayout.addView(buttonRemove);
// Button [+]
Button buttonAdd = new Button(mContext);
buttonAdd.setText(resourceHelper.gs(R.string.add_short));
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
dialog.show(fragmentManager, "ChooseTriggerDialog");
dialog.setOnClickListener(newTriggerObject -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger) + 1, newTriggerObject);
connector.simplify();
rebuild(context);
});
});
buttonLayout.addView(buttonAdd);
// Button [*]
Button buttonCopy = new Button(mContext);
buttonCopy.setText(resourceHelper.gs(R.string.copy_short));
buttonCopy.setOnClickListener(v -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger) + 1, trigger.duplicate());
connector.simplify();
rebuild(context);
});
buttonLayout.addView(buttonCopy);
rootLayout.addView(buttonLayout);
}
public void changeConnector(final Context context, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
if (connector.size() > 2) {
// split connector
int pos = connector.pos(trigger) - 1;
TriggerConnector newConnector = new TriggerConnector(mainApp, newConnectorType);
// move trigger from pos and pos+1 into new connector
for (int i = 0; i < 2; ++i) {
Trigger t = connector.get(pos);
newConnector.add(t);
connector.remove(t);
}
connector.add(pos, newConnector);
} else {
connector.setType(newConnectorType);
}
connector.simplify();
rebuild(context);
}
}

View file

@ -1,30 +1,45 @@
package info.nightscout.androidaps.plugins.general.automation.elements
import android.graphics.Typeface
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
class StaticLabel(mainApp: MainApp) : Element(mainApp) {
var label = ""
var trigger: Trigger? = null
constructor(mainApp: MainApp, label: String) : this(mainApp) {
constructor(mainApp: MainApp, label: String, trigger: Trigger) : this(mainApp) {
this.label = label
this.trigger = trigger
}
constructor(mainApp: MainApp, resourceId: Int) : this(mainApp) {
constructor(mainApp: MainApp, resourceId: Int, trigger: Trigger) : this(mainApp) {
label = resourceHelper.gs(resourceId)
this.trigger = trigger
}
override fun addToLayout(root: LinearLayout) { // text view pre 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
// textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
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)
textView.setBackgroundColor(resourceHelper.gc(R.color.mdtp_line_dark))
root.addView(textView)
headerLayout.addView(textView)
trigger?.let {
headerLayout.addView(it.createDeleteButton(root.context, it))
headerLayout.addView(it.createCloneButton(root.context, it))
}
root.addView(headerLayout)
}
}

View file

@ -3,5 +3,4 @@ package info.nightscout.androidaps.plugins.general.automation.events
import info.nightscout.androidaps.events.Event
import info.nightscout.androidaps.plugins.general.automation.actions.Action
class EventAutomationUpdateAction(val action: Action, val position : Int) : Event() {
}
class EventAutomationUpdateAction(val action: Action, val position: Int) : Event()

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.automation.events
import info.nightscout.androidaps.events.Event
class EventTriggerChanged : Event()

View file

@ -0,0 +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
class EventTriggerClone(val trigger: Trigger) : Event()

View file

@ -0,0 +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
class EventTriggerRemove(val trigger: Trigger) : Event()

View file

@ -2,14 +2,22 @@ package info.nightscout.androidaps.plugins.general.automation.triggers
import android.content.Context
import android.content.ContextWrapper
import android.view.Gravity
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.common.base.Optional
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerChanged
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerClone
import info.nightscout.androidaps.plugins.general.automation.events.EventTriggerRemove
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.services.LocationService
@ -22,16 +30,15 @@ import kotlin.reflect.full.primaryConstructor
abstract class Trigger(val mainApp: MainApp) {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var sp : SP
@Inject lateinit var sp: SP
@Inject lateinit var locationService: LocationService
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
var connector: TriggerConnector? = null
init {
mainApp.androidInjector().inject(this)
}
@ -45,14 +52,15 @@ abstract class Trigger(val mainApp: MainApp) {
abstract fun icon(): Optional<Int?>
abstract fun duplicate(): Trigger
companion object {
@JvmStatic
fun scanForActivity(cont: Context?): AppCompatActivity? {
if (cont == null) return null
else if (cont is AppCompatActivity) return cont
else if (cont is ContextWrapper) return scanForActivity(cont.baseContext)
return null
when (cont) {
null -> return null
is AppCompatActivity -> return cont
is ContextWrapper -> return scanForActivity(cont.baseContext)
else -> return null
}
}
}
@ -80,4 +88,64 @@ abstract class Trigger(val mainApp: MainApp) {
}
return null
}
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.add)
buttonAdd.contentDescription = resourceHelper.gs(R.string.add_short)
buttonAdd.setOnClickListener {
scanForActivity(context)?.supportFragmentManager?.let {
val dialog = ChooseTriggerDialog()
dialog.show(it, "ChooseTriggerDialog")
dialog.setOnClickListener(object : ChooseTriggerDialog.OnClickListener {
override fun onClick(newTriggerObject: Trigger) {
trigger.list.add(newTriggerObject)
rxBus.send(EventTriggerChanged())
}
})
}
}
return buttonAdd
}
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.remove)
buttonRemove.contentDescription = resourceHelper.gs(R.string.delete_short)
buttonRemove.setOnClickListener {
rxBus.send(EventTriggerRemove(trigger))
}
return buttonRemove
}
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.clone)
buttonClone.contentDescription = resourceHelper.gs(R.string.copy_short)
buttonClone.setOnClickListener {
rxBus.send(EventTriggerClone(trigger))
}
return buttonClone
}
}

View file

@ -74,7 +74,7 @@ class TriggerAutosensValue(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.autosenslabel))
.add(StaticLabel(mainApp, R.string.autosenslabel, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.autosenslabel) + ": ", "", autosens))
.build(root)

View file

@ -20,12 +20,12 @@ class TriggerBg(mainApp: MainApp) : Trigger(mainApp) {
private var bg = InputBg(mainApp)
var comparator = Comparator(mainApp)
constructor(mainApp: MainApp, value : Double, units : String, compare: Comparator.Compare) : this(mainApp){
constructor(mainApp: MainApp, value: Double, units: String, compare: Comparator.Compare) : this(mainApp) {
bg = InputBg(mainApp, value, units)
comparator = Comparator(mainApp, compare)
}
constructor(mainApp: MainApp, triggerBg: TriggerBg) : this(mainApp){
constructor(mainApp: MainApp, triggerBg: TriggerBg) : this(mainApp) {
bg = InputBg(mainApp, triggerBg.bg.value, triggerBg.bg.units)
comparator = Comparator(mainApp, triggerBg.comparator.value)
}
@ -82,7 +82,7 @@ class TriggerBg(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.glucose))
.add(StaticLabel(mainApp, R.string.glucose, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.glucose_u, bg.units), "", bg))
.build(root)

View file

@ -73,7 +73,7 @@ class TriggerBolusAgo(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.lastboluslabel))
.add(StaticLabel(mainApp, R.string.lastboluslabel, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
.build(root)

View file

@ -73,7 +73,7 @@ class TriggerCOB(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.triggercoblabel))
.add(StaticLabel(mainApp, R.string.triggercoblabel, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.triggercoblabel) + ": ", "", cob))
.build(root)

View file

@ -1,13 +1,17 @@
package info.nightscout.androidaps.plugins.general.automation.triggers
import android.content.Context
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 com.google.common.base.Optional
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.general.automation.dialogs.TriggerListAdapter
import info.nightscout.androidaps.utils.JsonHelper.safeGetString
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.json.JSONArray
@ -16,7 +20,9 @@ import java.util.*
class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
var list: MutableList<Trigger> = ArrayList()
var connectorType: Type = Type.AND
private var connectorType: Type = Type.AND
// TODO move to TriggerConnector
//var connector: TriggerConnector = TriggerConnector(mainApp, TriggerConnector.Type.AND)
enum class Type {
AND, OR, XOR;
@ -35,12 +41,14 @@ class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
AND -> R.string.and
}
fun labels(resourceHelper: ResourceHelper): List<String> {
val list: MutableList<String> = ArrayList()
for (t in values()) {
list.add(resourceHelper.gs(t.stringRes))
companion object {
fun labels(resourceHelper: ResourceHelper): List<String> {
val list: MutableList<String> = ArrayList()
for (t in values()) {
list.add(resourceHelper.gs(t.stringRes))
}
return list
}
return list
}
}
@ -52,25 +60,8 @@ class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
connectorType = type
}
@Synchronized
fun add(t: Trigger) {
list.add(t)
t.connector = this
}
@Synchronized
fun add(pos: Int, t: Trigger) {
list.add(pos, t)
t.connector = this
}
@Synchronized
fun remove(t: Trigger): Boolean = list.remove(t)
fun size(): Int = list.size
operator fun get(i: Int): Trigger = list[i]
fun pos(trigger: Trigger): Int {
for (i in list.indices) {
if (list[i] === trigger) return i
@ -109,7 +100,7 @@ class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
list.clear()
for (i in 0 until array.length()) {
instantiate(JSONObject(array.getString(i)))?.let {
add(it)
list.add(it)
}
}
return this
@ -135,42 +126,48 @@ class TriggerConnector(mainApp: MainApp) : Trigger(mainApp) {
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)
// Child triggers
val listLayout = LinearLayout(root.context)
listLayout.orientation = LinearLayout.VERTICAL
listLayout.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
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)
TriggerListAdapter(mainApp, resourceHelper, listLayout, this)
}
fun simplify(): TriggerConnector { // simplify children
for (i in 0 until size()) {
if (get(i) is TriggerConnector) {
val t = get(i) as TriggerConnector
t.simplify()
private fun createSpinner(context: Context): Spinner {
val initialPosition = connectorType.ordinal
val spinner = Spinner(context)
val spinnerArrayAdapter = ArrayAdapter(context, R.layout.spinner_centered, Type.labels(resourceHelper))
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = spinnerArrayAdapter
spinner.setSelection(initialPosition)
spinner.setBackgroundColor(resourceHelper.gc(R.color.black_overlay))
val params = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
params.setMargins(0, resourceHelper.dpToPx(8), 0, resourceHelper.dpToPx(8))
params.weight = 1.0f
spinner.layoutParams = params
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
setType(Type.values()[position])
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
// drop connector with only 1 element
if (size() == 1 && get(0) is TriggerConnector) {
val c = get(0) as TriggerConnector
remove(c)
connectorType = c.connectorType
for (t in c.list) add(t)
c.list.clear()
return simplify()
}
// merge connectors
connector?.let { connector ->
if (connector.connectorType == connectorType || size() == 1) {
val pos = connector.pos(this)
connector.remove(this)
// move triggers of child connector into parent connector
for (i in size() - 1 downTo 0) {
connector.add(pos, get(i))
}
list.clear()
return connector.simplify()
}
}
return this
return spinner
}
}

View file

@ -98,7 +98,7 @@ class TriggerDelta(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.deltalabel))
.add(StaticLabel(mainApp, R.string.deltalabel, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.deltalabel_u, units) + ": ", "", delta))
.build(root)

View file

@ -64,7 +64,7 @@ class TriggerIob(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.iob))
.add(StaticLabel(mainApp, R.string.iob, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.iob_u), "", insulin))
.build(root)

View file

@ -92,7 +92,7 @@ class TriggerLocation(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.location))
.add(StaticLabel(mainApp, R.string.location, this))
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.name_short), "", name))
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.latitude_short), "", latitude))
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.longitude_short), "", longitude))

View file

@ -73,7 +73,7 @@ class TriggerProfilePercent(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.profilepercentage))
.add(StaticLabel(mainApp, R.string.profilepercentage, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.percent_u), "", pct))
.build(root)

View file

@ -73,7 +73,7 @@ class TriggerPumpLastConnection(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.automation_trigger_pump_last_connection_label))
.add(StaticLabel(mainApp, R.string.automation_trigger_pump_last_connection_label, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.automation_trigger_pump_last_connection_description) + ": ", "", minutesAgo))
.build(root)

View file

@ -94,7 +94,7 @@ class TriggerRecurringTime(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.recurringTime))
.add(StaticLabel(mainApp, R.string.recurringTime, this))
.add(days)
.add(time)
.build(root)

View file

@ -62,7 +62,7 @@ class TriggerTempTarget(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.careportal_temporarytarget))
.add(StaticLabel(mainApp, R.string.careportal_temporarytarget, this))
.add(comparator)
.build(root)
}

View file

@ -60,7 +60,7 @@ class TriggerTime(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.time))
.add(StaticLabel(mainApp, R.string.time, this))
.add(time)
.build(root)
}

View file

@ -76,7 +76,7 @@ class TriggerTimeRange(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.time_range))
.add(StaticLabel(mainApp, R.string.time_range, this))
.add(range)
.build(root)
}

View file

@ -44,7 +44,7 @@ class TriggerWifiSsid(mainApp: MainApp) : Trigger(mainApp) {
override fun toJSON(): String {
val data = JSONObject()
.put("ssid", ssid)
.put("ssid", ssid.value)
.put("comparator", comparator.value.toString())
return JSONObject()
.put("type", this::class.java.name)
@ -70,7 +70,7 @@ class TriggerWifiSsid(mainApp: MainApp) : Trigger(mainApp) {
override fun generateDialog(root: LinearLayout) {
LayoutBuilder()
.add(StaticLabel(mainApp, R.string.ns_wifi_ssids))
.add(StaticLabel(mainApp, R.string.ns_wifi_ssids, this))
.add(comparator)
.add(LabelWithElement(mainApp, resourceHelper.gs(R.string.ns_wifi_ssids) + ": ", "", ssid))
.build(root)