Skip to content

Commit

Permalink
Implement buttongrid
Browse files Browse the repository at this point in the history
Closes openhab#3494

Signed-off-by: mueller-ma <[email protected]>
  • Loading branch information
mueller-ma committed Dec 26, 2023
1 parent cca8eab commit 9f6c987
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/openhab.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions mobile/src/main/java/org/openhab/habdroid/model/LabeledValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ import org.json.JSONObject
import org.openhab.habdroid.util.optStringOrNull

@Parcelize
data class LabeledValue internal constructor(val value: String, val label: String, val icon: IconResource?) : Parcelable
data class LabeledValue internal constructor(
val value: String,
val label: String,
val icon: IconResource?,
val row: Int,
val column: Int
) : Parcelable

@Throws(JSONException::class)
fun JSONObject.toLabeledValue(valueKey: String, labelKey: String): LabeledValue {
val value = getString(valueKey)
val label = optString(labelKey, value)
val icon = optStringOrNull("icon")?.toOH2IconResource()
return LabeledValue(value, label, icon)
return LabeledValue(value, label, icon, optInt("row"), optInt("column"))
}
3 changes: 2 additions & 1 deletion mobile/src/main/java/org/openhab/habdroid/model/Widget.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ data class Widget(
Video,
Webview,
Input,
Buttongrid,
Unknown
}

Expand Down Expand Up @@ -303,7 +304,7 @@ fun Node.collectWidgets(parent: Widget?): List<Widget> {
"label" -> mappingLabel = childNode.textContent
}
}
mappings.add(LabeledValue(mappingCommand, mappingLabel, null))
mappings.add(LabeledValue(mappingCommand, mappingLabel, null, 0, 0))
}
else -> {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ fun RemoteViews.duplicate(): RemoteViews {
}

fun MaterialButton.setTextAndIcon(connection: Connection, mapping: LabeledValue) {
contentDescription = mapping.label
val iconUrl = mapping.icon?.toUrl(context, true)
if (iconUrl == null) {
icon = null
Expand Down
47 changes: 46 additions & 1 deletion mobile/src/main/java/org/openhab/habdroid/ui/WidgetAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import android.view.inputmethod.EditorInfo
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.widget.Button
import android.widget.GridLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
Expand All @@ -40,9 +41,11 @@ import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat
import androidx.core.view.allViews
import androidx.core.view.children
import androidx.core.view.get
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.widget.ContentLoadingProgressBar
import androidx.core.widget.doAfterTextChanged
Expand Down Expand Up @@ -221,6 +224,7 @@ class WidgetAdapter(
TYPE_LOCATION -> MapViewHelper.createViewHolder(initData)
TYPE_INPUT -> InputViewHolder(initData)
TYPE_DATETIMEINPUT -> DateTimeInputViewHolder(initData)
TYPE_BUTTONGRID -> ButtongridViewHolder(initData)
TYPE_INVISIBLE -> InvisibleWidgetViewHolder(initData)
else -> throw IllegalArgumentException("View type $viewType is not known")
}
Expand Down Expand Up @@ -345,6 +349,7 @@ class WidgetAdapter(
Widget.Type.Colorpicker -> TYPE_COLOR
Widget.Type.Mapview -> TYPE_LOCATION
Widget.Type.Input -> if (widget.shouldUseDateTimePickerForInput()) TYPE_DATETIMEINPUT else TYPE_INPUT
Widget.Type.Buttongrid -> TYPE_BUTTONGRID
else -> TYPE_GENERICITEM
}
return toInternalViewType(actualViewType, compactMode)
Expand Down Expand Up @@ -780,6 +785,45 @@ class WidgetAdapter(
}
}

class ButtongridViewHolder internal constructor(private val initData: ViewHolderInitData) :
LabeledItemBaseViewHolder(initData, R.layout.widgetlist_buttongriditem), View.OnClickListener {
private val table: GridLayout = itemView.findViewById(R.id.widget_content)

override fun bind(widget: Widget) {
super.bind(widget)
val mappings = widget.mappings.filter { it.column != 0 && it.row != 0 }
table.rowCount = mappings.maxOfOrNull { it.row } ?: 0
table.columnCount = mappings.maxOfOrNull { it.column } ?: 0
(0..<table.rowCount).forEach { row ->
(0..<table.columnCount).forEach { column ->
val buttonView = initData.inflater.inflate(R.layout.widgetlist_sectionswitchitem_button, null) as MaterialButton
// Rows and columns start with 1 in Sitemap definition, thus decrement them here
val mapping = mappings.firstOrNull { it.row - 1 == row && it.column - 1 == column }
if (mapping == null) {
buttonView.visibility = View.INVISIBLE
} else {
buttonView.setOnClickListener(this)
buttonView.setTextAndIcon(connection, mapping)
buttonView.tag = mapping.value
buttonView.visibility = View.VISIBLE
}

table.addView(
buttonView,
GridLayout.LayoutParams(
GridLayout.spec(row, GridLayout.FILL, 1f),
GridLayout.spec(column, GridLayout.FILL, 1f)
)
)
}
}
}

override fun onClick(view: View) {
connection.httpClient.sendItemCommand(boundWidget?.item, view.tag as String)
}
}

class SliderViewHolder internal constructor(initData: ViewHolderInitData) :
LabeledItemBaseViewHolder(initData, R.layout.widgetlist_slideritem, R.layout.widgetlist_slideritem_compact),
WidgetSlider.UpdateListener {
Expand Down Expand Up @@ -1555,7 +1599,8 @@ class WidgetAdapter(
private const val TYPE_LOCATION = 18
private const val TYPE_INPUT = 19
private const val TYPE_DATETIMEINPUT = 20
private const val TYPE_INVISIBLE = 21
private const val TYPE_BUTTONGRID = 21
private const val TYPE_INVISIBLE = 22

private fun toInternalViewType(viewType: Int, compactMode: Boolean): Int {
return viewType or (if (compactMode) 0x100 else 0)
Expand Down
18 changes: 18 additions & 0 deletions mobile/src/main/res/layout/widgetlist_buttongriditem.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:orientation="vertical"
style="@style/WidgetListItemContainer">

<include layout="@layout/widgetlist_icontext_for_heavy_data" />

<GridLayout
android:id="@+id/widget_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:useDefaultMargins="true" />

</LinearLayout>
8 changes: 5 additions & 3 deletions mobile/src/test/java/org/openhab/habdroid/model/ItemTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ class ItemTest {
@Test
fun getCommandOptions() {
val sut = itemWithCommandOptions.toItem()
assertEquals(LabeledValue("1", "One", "switch".toOH2IconResource()), sut.options!!.component1())
assertEquals(LabeledValue("2", "Two", null), sut.options!!.component2())
assertEquals(LabeledValue("1", "One", "switch".toOH2IconResource(), 1, 2), sut.options!!.component1())
assertEquals(LabeledValue("2", "Two", null, 0, 0), sut.options!!.component2())
}

@Test
Expand Down Expand Up @@ -209,7 +209,9 @@ class ItemTest {
{
'command': '1',
'label': 'One',
'icon': 'switch'
'icon': 'switch',
'row': 1,
'column': 2
},
{
'command': '2',
Expand Down

0 comments on commit 9f6c987

Please sign in to comment.