blob: 19779f67ca4890d5454b4da14a5db2d681032df4 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.spa.widget.preference
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.IntState
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.dialog.SettingsDialog
import com.android.settingslib.spa.widget.ui.SettingsDialogItem
data class ListPreferenceOption(
val id: Int,
val text: String,
)
/**
* The widget model for [ListPreference] widget.
*/
interface ListPreferenceModel {
/**
* The title of this [ListPreference].
*/
val title: String
/**
* The icon of this [ListPreference].
*
* Default is `null` which means no icon.
*/
val icon: (@Composable () -> Unit)?
get() = null
/**
* Indicates whether this [ListPreference] is enabled.
*
* Disabled [ListPreference] will be displayed in disabled style.
*/
val enabled: State<Boolean>
get() = stateOf(true)
val options: List<ListPreferenceOption>
val selectedId: IntState
val onIdSelected: (id: Int) -> Unit
}
@Composable
fun ListPreference(model: ListPreferenceModel) {
var dialogOpened by rememberSaveable { mutableStateOf(false) }
if (dialogOpened) {
SettingsDialog(
title = model.title,
onDismissRequest = { dialogOpened = false },
) {
Column(modifier = Modifier.selectableGroup()) {
for (option in model.options) {
Radio(option, model.selectedId, model.enabled) {
dialogOpened = false
model.onIdSelected(it)
}
}
}
}
}
Preference(model = remember(model) {
object : PreferenceModel {
override val title = model.title
override val summary = derivedStateOf {
model.options.find { it.id == model.selectedId.intValue }?.text ?: ""
}
override val icon = model.icon
override val enabled = model.enabled
override val onClick = { dialogOpened = true }.takeIf { model.options.isNotEmpty() }
}
})
}
@Composable
private fun Radio(
option: ListPreferenceOption,
selectedId: IntState,
enabledState: State<Boolean>,
onIdSelected: (id: Int) -> Unit,
) {
val selected = option.id == selectedId.intValue
val enabled = enabledState.value
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = selected,
enabled = enabled,
onClick = { onIdSelected(option.id) },
role = Role.RadioButton,
)
.padding(SettingsDimension.dialogItemPadding),
verticalAlignment = Alignment.CenterVertically,
) {
RadioButton(selected = selected, onClick = null, enabled = enabled)
Spacer(modifier = Modifier.width(SettingsDimension.itemPaddingEnd))
SettingsDialogItem(text = option.text, enabled = enabled)
}
}