Update the last character sheet formfield.

This commit is contained in:
Thomas Andres Gomez 2024-11-27 17:24:17 +01:00
parent d93ffd9499
commit d1a98b9075
13 changed files with 248 additions and 463 deletions

View file

@ -8,7 +8,7 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetReposit
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
import com.pixelized.desktop.lwa.screen.characterSheet.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetFactory
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetViewModel
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditFactory

View file

@ -29,7 +29,7 @@ class CharacterSheetJsonFactory(
currentHp = sheet.currentHp,
maxHp = if (sheet.overrideMaxHp) sheet.maxHp else null,
currentPP = sheet.currentPp,
maxPP = if (sheet.overrideMaxPP) sheet.maxPP else null,
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
armor = if (sheet.overrideArmor) sheet.armor else null,
skills = sheet.commonSkills.map {
@ -104,7 +104,7 @@ class CharacterSheetJsonFactory(
maxHp = json.maxHp ?: (ceil((json.constitution + json.height) / 2f).toInt()),
currentPp = json.currentPP,
overrideMaxPP = json.maxPP != null,
maxPP = json.maxPP ?: json.power,
maxPp = json.maxPP ?: json.power,
overrideDamageBonus = json.damageBonus != null,
damageBonus = json.damageBonus
?: bonusDamageUseCase.bonusDamage(

View file

@ -19,7 +19,7 @@ data class CharacterSheet(
val maxHp: Int,
val currentPp: Int,
val overrideMaxPP: Boolean,
val maxPP: Int,
val maxPp: Int,
val overrideDamageBonus: Boolean,
val damageBonus: String,
val overrideArmor: Boolean,

View file

@ -2,7 +2,6 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
import com.pixelized.desktop.lwa.composable.tooltip.TooltipUio
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet.CommonSkillId
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
@ -52,9 +51,7 @@ import org.jetbrains.compose.resources.getString
class CharacterSheetFactory(
private val skillUseCase: SkillValueComputationUseCase,
private val arithmeticParser: ArithmeticParser,
) {
companion object {
const val HP = "HP"
const val PP = "PP"
@ -163,7 +160,7 @@ class CharacterSheetFactory(
Characteristic(
id = PP,
label = getString(Res.string.character_sheet__sub_characteristics__power_point),
value = "${sheet.currentPp}/${sheet.maxPP}",
value = "${sheet.currentPp}/${sheet.maxPp}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__sub_characteristics__power_point),
description = getString(Res.string.tooltip__sub_characteristics__power_point),

View file

@ -146,7 +146,7 @@ class CharacterSheetViewModel(
label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__power_point),
value = { value.value },
onValueChange = { value.value = it },
maxValue = "${sheet.maxPP}",
maxValue = "${sheet.maxPp}",
)
}
@ -166,7 +166,7 @@ class CharacterSheetViewModel(
val sheet = repository.characterSheetFlow(id = argument.id).value
val updated = when (characteristicId) {
CharacterSheetFactory.HP -> sheet?.copy(currentHp = max(0, min(sheet.maxHp, value)))
CharacterSheetFactory.PP -> sheet?.copy(currentPp = max(0, min(sheet.maxPP, value)))
CharacterSheetFactory.PP -> sheet?.copy(currentPp = max(0, min(sheet.maxPp, value)))
else -> null
}
updated?.let {

View file

@ -2,14 +2,15 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.screen.characterSheet.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.common.occupation
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.occupation
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.ActionFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.BaseSkillFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SimpleFieldUio
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__action_label
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__name_label
@ -60,32 +61,54 @@ class CharacterSheetEditFactory(
currentSheet: CharacterSheet?,
editedSheet: CharacterSheetEditPageUio,
): CharacterSheet {
val maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
?: currentSheet?.maxHp
?: 0
val maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
?: currentSheet?.maxPp
?: 0
return CharacterSheet(
id = editedSheet.id,
name = editedSheet.name.value.value,
strength = editedSheet.strength.unpack(),
dexterity = editedSheet.dexterity.unpack(),
constitution = editedSheet.constitution.unpack(),
height = editedSheet.height.unpack(),
intelligence = editedSheet.intelligence.unpack(),
power = editedSheet.power.unpack(),
charisma = editedSheet.charisma.unpack(),
overrideMovement = editedSheet.movement.value.value.isNotBlank(),
movement = editedSheet.movement.unpack(),
overrideMaxHp = editedSheet.maxHp.value.value.isNotBlank(),
maxHp = editedSheet.maxHp.unpack(),
currentHp = editedSheet.maxHp.unpack<Int>().let {
max(0, min(it, currentSheet?.currentHp ?: it))
},
overrideMaxPP = editedSheet.maxPP.value.value.isNotBlank(),
maxPP = editedSheet.maxPP.unpack(),
currentPp = editedSheet.maxPP.unpack<Int>().let {
max(0, min(it, currentSheet?.currentPp ?: it))
},
overrideDamageBonus = editedSheet.damageBonus.value.value.isNotBlank(),
damageBonus = editedSheet.damageBonus.unpack(),
overrideArmor = editedSheet.armor.value.value.isNotBlank(),
armor = editedSheet.armor.unpack(),
strength = editedSheet.strength.unpack()?.toIntOrNull()
?: currentSheet?.strength
?: 0,
dexterity = editedSheet.dexterity.unpack()?.toIntOrNull()
?: currentSheet?.dexterity
?: 0,
constitution = editedSheet.constitution.unpack()?.toIntOrNull()
?: currentSheet?.constitution
?: 0,
height = editedSheet.height.unpack()?.toIntOrNull()
?: currentSheet?.height
?: 0,
intelligence = editedSheet.intelligence.unpack()?.toIntOrNull()
?: currentSheet?.intelligence
?: 0,
power = editedSheet.power.unpack()?.toIntOrNull()
?: currentSheet?.power
?: 0,
charisma = editedSheet.charisma.unpack()?.toIntOrNull()
?: currentSheet?.charisma
?: 0,
overrideMovement = editedSheet.movement.value.value.value.isNotBlank(),
movement = editedSheet.movement.unpack()?.toIntOrNull()
?: currentSheet?.movement
?: 10,
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
maxHp = maxHp,
currentHp = max(0, min(maxHp, currentSheet?.currentHp ?: maxHp)),
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
maxPp = maxPp,
currentPp = max(0, min(maxPp, currentSheet?.currentPp ?: maxPp)),
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
damageBonus = editedSheet.damageBonus.unpack()
?: currentSheet?.damageBonus
?: "",
overrideArmor = editedSheet.armor.value.value.value.isNotBlank(),
armor = editedSheet.armor.unpack()?.toIntOrNull()
?: currentSheet?.armor
?: 0,
commonSkills = editedSheet.commonSkills.map { editedSkill ->
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
it.id == editedSkill.id
@ -142,59 +165,72 @@ class CharacterSheetEditFactory(
sheet: CharacterSheet?,
onDeleteSkill: (id: String) -> Unit,
): CharacterSheetEditPageUio {
val str = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__str),
initialValue = sheet?.strength?.toString() ?: "",
valuePlaceHolder = { "10" },
val str = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__str),
value = skillFactory.createWrapper(
value = sheet?.strength?.toString() ?: "",
placeholder = mutableStateOf("10")
),
)
val dex = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__dex),
initialValue = sheet?.dexterity?.toString() ?: "",
valuePlaceHolder = { "10" }
val dex = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__dex),
value = skillFactory.createWrapper(
value = sheet?.dexterity?.toString() ?: "",
placeholder = mutableStateOf("10"),
),
)
val con = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__con),
initialValue = sheet?.constitution?.toString() ?: "",
valuePlaceHolder = { "10" }
val con = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__con),
value = skillFactory.createWrapper(
value = sheet?.constitution?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
)
val hei = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__hei),
initialValue = sheet?.height?.toString() ?: "",
valuePlaceHolder = { "10" }
val hei = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__hei),
value = skillFactory.createWrapper(
value = sheet?.height?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
)
val int = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__int),
initialValue = sheet?.intelligence?.toString() ?: "",
valuePlaceHolder = { "10" }
val int = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__int),
value = skillFactory.createWrapper(
value = sheet?.intelligence?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
)
val pow = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__pow),
initialValue = sheet?.power?.toString() ?: "",
valuePlaceHolder = { "10" }
val pow = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__pow),
value = skillFactory.createWrapper(
value = sheet?.power?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
)
val cha = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__cha),
initialValue = sheet?.charisma?.toString() ?: "",
valuePlaceHolder = { "7" }
val cha = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__characteristics__cha),
value = skillFactory.createWrapper(
value = sheet?.charisma?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
)
fun str(): Int = str.unpack() ?: 0
fun dex(): Int = dex.unpack() ?: 0
fun con(): Int = con.unpack() ?: 0
fun hei(): Int = hei.unpack() ?: 0
fun int(): Int = int.unpack() ?: 0
fun pow(): Int = pow.unpack() ?: 0
fun cha(): Int = cha.unpack() ?: 0
fun str(): Int = str.unpack()?.toIntOrNull() ?: 0
fun dex(): Int = dex.unpack()?.toIntOrNull() ?: 0
fun con(): Int = con.unpack()?.toIntOrNull() ?: 0
fun hei(): Int = hei.unpack()?.toIntOrNull() ?: 0
fun int(): Int = int.unpack()?.toIntOrNull() ?: 0
fun pow(): Int = pow.unpack()?.toIntOrNull() ?: 0
fun cha(): Int = cha.unpack()?.toIntOrNull() ?: 0
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
return CharacterSheetEditPageUio(
id = sheet?.id ?: UUID.randomUUID().toString(),
name = FieldUio.create(
isLabelDisplayed = false,
initialLabel = getString(Res.string.character_sheet_edit__name_placeholder),
initialValue = sheet?.name ?: ""
name = skillFactory.createWrapper(
label = getString(Res.string.character_sheet_edit__name_placeholder),
value = sheet?.name ?: ""
),
strength = str,
dexterity = dex,
@ -203,38 +239,45 @@ class CharacterSheetEditFactory(
intelligence = int,
power = pow,
charisma = cha,
movement = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
initialValue = (if (sheet?.overrideMovement == true) "${sheet.movement}" else null)
?: "",
valuePlaceHolder = { "10" }
movement = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
value = skillFactory.createWrapper(
value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
placeholder = mutableStateOf("10"),
)
),
maxHp = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
initialValue = (if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else null) ?: "",
valuePlaceHolder = { "${ceil((con() + hei()) / 2f).toInt()}" }
maxHp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
value = skillFactory.createWrapper(
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
)
),
maxPP = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
initialValue = (if (sheet?.overrideMaxPP == true) "${sheet.maxPP}" else null) ?: "",
valuePlaceHolder = { "${pow()}" }
maxPp = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
value = skillFactory.createWrapper(
value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
placeholder = derivedStateOf { "${pow()}" },
)
),
damageBonus = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
initialValue = (if (sheet?.overrideDamageBonus == true) sheet.damageBonus else null)
?: "",
valuePlaceHolder = {
bonusDamageUseCase.bonusDamage(
strength = str(),
height = hei()
)
}
damageBonus = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
value = skillFactory.createWrapper(
value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
placeholder = derivedStateOf {
bonusDamageUseCase.bonusDamage(
strength = str(),
height = hei()
)
},
)
),
armor = FieldUio.create(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
initialValue = (if (sheet?.overrideArmor == true) sheet.armor.toString() else null)
?: "",
valuePlaceHolder = { "0" }
armor = SimpleFieldUio(
label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
value = skillFactory.createWrapper(
value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
placeholder = mutableStateOf("0"),
)
),
commonSkills = listOf(
createBaseSkill(
@ -409,11 +452,7 @@ class CharacterSheetEditFactory(
)
}
private inline fun <reified T> FieldUio.unpack(): T {
val tmp = value.value.ifBlank { valuePlaceHolder.value }
return when (T::class) {
Int::class -> (tmp.toIntOrNull() ?: 0) as T
else -> tmp as T
}
private fun SimpleFieldUio.unpack(): String? {
return value.value.value.ifBlank { value.placeholder.value }
}
}

View file

@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Icon
@ -19,11 +18,9 @@ import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -37,10 +34,12 @@ import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.ActionFie
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.ActionFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.BaseSkillFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.BaseSkillForm
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.Form
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SimpleField
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SimpleFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SkillFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SkillForm
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapper
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapperUio
import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet__skills__common_title
@ -53,7 +52,6 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sk
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__special_action
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__title
import lwacharactersheet.composeapp.generated.resources.ic_save_24dp
import lwacharactersheet.composeapp.generated.resources.ic_skull_32dp
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
@ -61,19 +59,19 @@ import org.koin.compose.viewmodel.koinViewModel
@Stable
data class CharacterSheetEditPageUio(
val id: String,
val name: FieldUio,
val strength: FieldUio,
val dexterity: FieldUio,
val constitution: FieldUio,
val height: FieldUio,
val intelligence: FieldUio,
val power: FieldUio,
val charisma: FieldUio,
val movement: FieldUio,
val maxHp: FieldUio,
val maxPP: FieldUio,
val damageBonus: FieldUio,
val armor: FieldUio,
val name: TextFieldWrapperUio,
val strength: SimpleFieldUio,
val dexterity: SimpleFieldUio,
val constitution: SimpleFieldUio,
val height: SimpleFieldUio,
val intelligence: SimpleFieldUio,
val power: SimpleFieldUio,
val charisma: SimpleFieldUio,
val movement: SimpleFieldUio,
val maxHp: SimpleFieldUio,
val maxPp: SimpleFieldUio,
val damageBonus: SimpleFieldUio,
val armor: SimpleFieldUio,
val commonSkills: List<BaseSkillFieldUio>,
val specialSkills: List<SkillFieldUio>,
val magicSkills: List<SkillFieldUio>,
@ -94,7 +92,7 @@ data class CharacterSheetEditPageUio(
get() = listOf(
movement,
maxHp,
maxPP,
maxPp,
damageBonus,
armor,
)
@ -184,9 +182,9 @@ fun CharacterSheetEdit(
.padding(all = 16.dp),
verticalArrangement = Arrangement.spacedBy(space = 16.dp)
) {
Form(
TextFieldWrapper(
modifier = Modifier.fillMaxWidth(),
field = form.name,
wrapper = form.name,
)
DecoratedBox(
@ -203,7 +201,7 @@ fun CharacterSheetEdit(
text = stringResource(Res.string.character_sheet_edit__characteristics__title),
)
form.characteristics.forEach {
Form(
SimpleField(
modifier = Modifier.fillMaxWidth(),
field = it,
)
@ -225,7 +223,7 @@ fun CharacterSheetEdit(
text = stringResource(Res.string.character_sheet_edit__sub_characteristics__title),
)
form.subCharacteristics.forEach {
Form(
SimpleField(
modifier = Modifier.fillMaxWidth(),
field = it,
)
@ -344,7 +342,9 @@ fun CharacterSheetEdit(
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.animateContentSize(),
) {
form.actions.forEach {
ActionField(
@ -352,13 +352,8 @@ fun CharacterSheetEdit(
action = it
)
}
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
) {
TextButton(
modifier = Modifier.align(alignment = Alignment.End),
onClick = onNewAction,
) {
Text(

View file

@ -6,7 +6,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetEditDestination
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.screen.characterSheet.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.ActionFieldUio
import kotlinx.coroutines.runBlocking
import lwacharactersheet.composeapp.generated.resources.Res

View file

@ -1,13 +1,14 @@
package com.pixelized.desktop.lwa.screen.characterSheet.common
package com.pixelized.desktop.lwa.screen.characterSheet.edit.common
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SkillFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapperUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.option.ActionOption
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.option.CheckedOption
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.option.OptionUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapperUio
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__delete__label
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__label
@ -19,7 +20,6 @@ import java.util.UUID
class SkillFieldFactory {
suspend fun createSkill(
id: String = UUID.randomUUID().toString(),
label: String,
@ -53,7 +53,8 @@ class SkillFieldFactory {
fun createWrapper(
enable: Boolean = true,
label: String = "",
label: String? = null,
placeholder: State<String?> = mutableStateOf(null),
value: String = "",
): TextFieldWrapperUio {
val state = mutableStateOf(value)
@ -61,6 +62,7 @@ class SkillFieldFactory {
enable = enable,
label = label,
value = state,
placeholder = placeholder,
onValueChange = { state.value = it },
)
}

View file

@ -1,153 +0,0 @@
package com.pixelized.desktop.lwa.screen.characterSheet.edit.composable
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.utils.preview.ContentPreview
@Deprecated("redo")
@Stable
open class FieldUio(
val isLabelDisplayed: Boolean,
val isLabelEditable: Boolean,
val label: State<String>,
val labelPlaceHolder: State<String>,
val onLabelChange: (String) -> Unit,
val value: State<String>,
val valuePlaceHolder: State<String>,
val onValueChange: (String) -> Unit,
) {
companion object {
@Stable
fun create(
isLabelDisplayed: Boolean = true,
isLabelEditable: Boolean = false,
initialLabel: String = "",
labelPlaceHolder: () -> String = { "" },
initialValue: String = "",
valuePlaceHolder: () -> String = { "" },
): FieldUio {
val label = mutableStateOf(initialLabel)
val value = mutableStateOf(initialValue)
return FieldUio(
isLabelDisplayed = isLabelDisplayed,
isLabelEditable = isLabelEditable,
label = label,
labelPlaceHolder = derivedStateOf(labelPlaceHolder),
onLabelChange = { label.value = it },
value = value,
valuePlaceHolder = derivedStateOf(valuePlaceHolder),
onValueChange = { value.value = it },
)
}
}
}
@Composable
fun Form(
modifier: Modifier = Modifier,
valueWidth: Dp = 80.dp,
field: FieldUio,
) {
val focus = LocalFocusManager.current
AnimatedContent(
targetState = field.isLabelDisplayed,
transitionSpec = { fadeIn() togetherWith fadeOut() }
) {
when (it) {
true -> {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedContent(
modifier = Modifier.weight(weight = 1f),
targetState = field.isLabelEditable,
transitionSpec = { fadeIn() togetherWith fadeOut() },
) { editable ->
when (editable) {
true -> TextField(
keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) },
singleLine = true,
placeholder = { Text(text = field.labelPlaceHolder.value) },
onValueChange = field.onLabelChange,
value = field.label.value,
)
else -> Text(
modifier = Modifier.padding(horizontal = 16.dp),
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = field.label.value
)
}
}
TextField(
modifier = Modifier.width(width = valueWidth),
keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) },
singleLine = true,
placeholder = { Text(text = field.valuePlaceHolder.value) },
onValueChange = field.onValueChange,
value = field.value.value,
)
}
}
else -> {
TextField(
modifier = modifier,
keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) },
singleLine = true,
label = { Text(text = field.label.value) },
onValueChange = field.onValueChange,
value = field.value.value,
)
}
}
}
}
@Composable
@Preview
private fun Preview() {
ContentPreview(
paddingValues = PaddingValues(all = 16.dp)
) {
Form(
field = FieldUio.create(
isLabelDisplayed = true,
isLabelEditable = true,
initialLabel = "label",
labelPlaceHolder = { "labelPlaceholder" },
initialValue = "value",
valuePlaceHolder = { "valuePlaceholder" },
)
)
}
}

View file

@ -0,0 +1,49 @@
package com.pixelized.desktop.lwa.screen.characterSheet.edit.composable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapper
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapperUio
@Stable
class SimpleFieldUio(
val label: String,
val value: TextFieldWrapperUio,
)
@Composable
fun SimpleField(
modifier: Modifier = Modifier,
field: SimpleFieldUio,
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(space = 4.dp, alignment = Alignment.End),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier
.weight(1f)
.padding(start = 16.dp, bottom = 12.dp)
.align(alignment = Alignment.Bottom),
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = field.label,
)
TextFieldWrapper(
modifier = Modifier.width(width = 96.dp),
wrapper = field.value,
)
}
}

View file

@ -97,161 +97,4 @@ fun SkillForm(
}
}
}
}
// PREVIEW
@Composable
@Preview
private fun Preview() {
ContentPreview(
modifier = Modifier.width(width = 1000.dp),
paddingValues = PaddingValues(all = 16.dp),
) {
SkillForm(
field = skillFieldUio(
labelLabel = "compétence",
labelValue = "Bagarre",
baseLabel = "Base",
baseValue = "Stat(DEX*2)",
bonusLabel = "Bonus",
bonusValue = "50",
levelLabel = "Niveau",
levelValue = "5",
),
)
}
}
fun main() = singleWindowApplication(title = "Context menu") {
ContentPreview(
modifier = Modifier.width(1000.dp),
paddingValues = PaddingValues(all = 16.dp),
) {
Column(
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
) {
SkillForm(
field = skillFieldUio(
labelLabel = "compétence",
labelValue = "Bagarre",
baseLabel = "Base",
baseValue = "Stat(DEX*2)",
bonusLabel = "Bonus",
bonusValue = "55",
levelLabel = "Niveau",
levelValue = "0",
options = listOf(
CheckedOption.OccupationOption(
label = "Base minimum 40",
checked = mutableStateOf(true),
onOption = { },
),
ActionOption.DeleteOptionUio(
icon = Icons.Default.Delete,
label = "Supprimer",
onOption = { },
),
)
),
)
SkillForm(
field = skillFieldUio(
labelLabel = "compétence",
labelValue = "Esquive",
baseLabel = "Base",
baseValue = "Stat(DEX*2)",
bonusLabel = "Bonus",
bonusValue = "40",
levelLabel = "Niveau",
levelValue = "0",
options = listOf(
CheckedOption.OccupationOption(
label = "Base minimum 40",
checked = mutableStateOf(true),
onOption = { },
),
ActionOption.DeleteOptionUio(
icon = Icons.Default.Delete,
label = "Supprimer",
onOption = { },
),
)
),
)
SkillForm(
field = skillFieldUio(
labelLabel = "compétence",
labelValue = "Saisie",
baseLabel = "Base",
baseValue = "Stat(FOR+TAI)",
bonusLabel = "Bonus",
bonusValue = "0",
levelLabel = "Niveau",
levelValue = "0",
options = listOf(
CheckedOption.OccupationOption(
label = "Base minimum 40",
checked = mutableStateOf(true),
onOption = { },
),
ActionOption.DeleteOptionUio(
icon = Icons.Default.Delete,
label = "Supprimer",
onOption = { },
),
)
),
)
}
}
}
private fun skillFieldUio(
labelLabel: String,
labelValue: String,
baseLabel: String,
baseValue: String,
bonusLabel: String,
bonusValue: String,
levelLabel: String,
levelValue: String,
options: List<OptionUio> = emptyList(),
): SkillFieldUio {
return SkillFieldUio(
id = UUID.randomUUID().toString(),
label = mutableStateOf(labelValue).let { state ->
TextFieldWrapperUio(
enable = true,
label = labelLabel,
value = state,
onValueChange = { state.value = it },
)
},
base = mutableStateOf(baseValue).let { state ->
TextFieldWrapperUio(
enable = true,
label = baseLabel,
value = state,
onValueChange = { state.value = it },
)
},
bonus = mutableStateOf(bonusValue).let { state ->
TextFieldWrapperUio(
enable = true,
label = bonusLabel,
value = state,
onValueChange = { state.value = it },
)
},
level = mutableStateOf(levelValue).let { state ->
TextFieldWrapperUio(
enable = true,
label = levelLabel,
value = state,
onValueChange = { state.value = it },
)
},
options = options,
)
}
}

View file

@ -9,6 +9,7 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.style.TextOverflow
import com.pixelized.desktop.lwa.utils.rememberKeyboardActions
@ -16,8 +17,9 @@ import com.pixelized.desktop.lwa.utils.rememberKeyboardActions
@Stable
data class TextFieldWrapperUio(
val enable: Boolean,
val label: String,
val label: String?,
val value: State<String>,
val placeholder: State<String?>,
val onValueChange: (String) -> Unit,
)
@ -38,12 +40,23 @@ fun TextFieldWrapper(
},
enabled = wrapper.enable,
singleLine = true,
label = {
Text(
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = wrapper.label
)
placeholder = wrapper.placeholder.value?.let {
{
Text(
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = it
)
}
},
label = wrapper.label?.let {
{
Text(
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = it
)
}
},
onValueChange = { wrapper.onValueChange(it) },
value = wrapper.value.value,