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.characterSheet.CharacterSheetStore
import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository 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.CharacterSheetFactory
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetViewModel import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetViewModel
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditFactory import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditFactory

View file

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

View file

@ -19,7 +19,7 @@ data class CharacterSheet(
val maxHp: Int, val maxHp: Int,
val currentPp: Int, val currentPp: Int,
val overrideMaxPP: Boolean, val overrideMaxPP: Boolean,
val maxPP: Int, val maxPp: Int,
val overrideDamageBonus: Boolean, val overrideDamageBonus: Boolean,
val damageBonus: String, val damageBonus: String,
val overrideArmor: Boolean, 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.business.SkillValueComputationUseCase
import com.pixelized.desktop.lwa.composable.tooltip.TooltipUio 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
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet.CommonSkillId import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet.CommonSkillId
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
@ -52,9 +51,7 @@ import org.jetbrains.compose.resources.getString
class CharacterSheetFactory( class CharacterSheetFactory(
private val skillUseCase: SkillValueComputationUseCase, private val skillUseCase: SkillValueComputationUseCase,
private val arithmeticParser: ArithmeticParser,
) { ) {
companion object { companion object {
const val HP = "HP" const val HP = "HP"
const val PP = "PP" const val PP = "PP"
@ -163,7 +160,7 @@ class CharacterSheetFactory(
Characteristic( Characteristic(
id = PP, id = PP,
label = getString(Res.string.character_sheet__sub_characteristics__power_point), label = getString(Res.string.character_sheet__sub_characteristics__power_point),
value = "${sheet.currentPp}/${sheet.maxPP}", value = "${sheet.currentPp}/${sheet.maxPp}",
tooltips = TooltipUio( tooltips = TooltipUio(
title = getString(Res.string.character_sheet__sub_characteristics__power_point), title = getString(Res.string.character_sheet__sub_characteristics__power_point),
description = getString(Res.string.tooltip__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), label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__power_point),
value = { value.value }, value = { value.value },
onValueChange = { value.value = it }, 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 sheet = repository.characterSheetFlow(id = argument.id).value
val updated = when (characteristicId) { val updated = when (characteristicId) {
CharacterSheetFactory.HP -> sheet?.copy(currentHp = max(0, min(sheet.maxHp, value))) 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 else -> null
} }
updated?.let { 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.State
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import com.pixelized.desktop.lwa.business.DamageBonusUseCase import com.pixelized.desktop.lwa.business.DamageBonusUseCase
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet 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.edit.common.SkillFieldFactory
import com.pixelized.desktop.lwa.screen.characterSheet.common.occupation 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.ActionFieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.BaseSkillFieldUio 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.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__action_label import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__action_label
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__name_label import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__actions__name_label
@ -60,32 +61,54 @@ class CharacterSheetEditFactory(
currentSheet: CharacterSheet?, currentSheet: CharacterSheet?,
editedSheet: CharacterSheetEditPageUio, editedSheet: CharacterSheetEditPageUio,
): CharacterSheet { ): CharacterSheet {
val maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
?: currentSheet?.maxHp
?: 0
val maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
?: currentSheet?.maxPp
?: 0
return CharacterSheet( return CharacterSheet(
id = editedSheet.id, id = editedSheet.id,
name = editedSheet.name.value.value, name = editedSheet.name.value.value,
strength = editedSheet.strength.unpack(), strength = editedSheet.strength.unpack()?.toIntOrNull()
dexterity = editedSheet.dexterity.unpack(), ?: currentSheet?.strength
constitution = editedSheet.constitution.unpack(), ?: 0,
height = editedSheet.height.unpack(), dexterity = editedSheet.dexterity.unpack()?.toIntOrNull()
intelligence = editedSheet.intelligence.unpack(), ?: currentSheet?.dexterity
power = editedSheet.power.unpack(), ?: 0,
charisma = editedSheet.charisma.unpack(), constitution = editedSheet.constitution.unpack()?.toIntOrNull()
overrideMovement = editedSheet.movement.value.value.isNotBlank(), ?: currentSheet?.constitution
movement = editedSheet.movement.unpack(), ?: 0,
overrideMaxHp = editedSheet.maxHp.value.value.isNotBlank(), height = editedSheet.height.unpack()?.toIntOrNull()
maxHp = editedSheet.maxHp.unpack(), ?: currentSheet?.height
currentHp = editedSheet.maxHp.unpack<Int>().let { ?: 0,
max(0, min(it, currentSheet?.currentHp ?: it)) intelligence = editedSheet.intelligence.unpack()?.toIntOrNull()
}, ?: currentSheet?.intelligence
overrideMaxPP = editedSheet.maxPP.value.value.isNotBlank(), ?: 0,
maxPP = editedSheet.maxPP.unpack(), power = editedSheet.power.unpack()?.toIntOrNull()
currentPp = editedSheet.maxPP.unpack<Int>().let { ?: currentSheet?.power
max(0, min(it, currentSheet?.currentPp ?: it)) ?: 0,
}, charisma = editedSheet.charisma.unpack()?.toIntOrNull()
overrideDamageBonus = editedSheet.damageBonus.value.value.isNotBlank(), ?: currentSheet?.charisma
damageBonus = editedSheet.damageBonus.unpack(), ?: 0,
overrideArmor = editedSheet.armor.value.value.isNotBlank(), overrideMovement = editedSheet.movement.value.value.value.isNotBlank(),
armor = editedSheet.armor.unpack(), 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 -> commonSkills = editedSheet.commonSkills.map { editedSkill ->
val currentSkill = currentSheet?.commonSkills?.firstOrNull { val currentSkill = currentSheet?.commonSkills?.firstOrNull {
it.id == editedSkill.id it.id == editedSkill.id
@ -142,59 +165,72 @@ class CharacterSheetEditFactory(
sheet: CharacterSheet?, sheet: CharacterSheet?,
onDeleteSkill: (id: String) -> Unit, onDeleteSkill: (id: String) -> Unit,
): CharacterSheetEditPageUio { ): CharacterSheetEditPageUio {
val str = FieldUio.create( val str = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__str), label = getString(Res.string.character_sheet_edit__characteristics__str),
initialValue = sheet?.strength?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" }, value = sheet?.strength?.toString() ?: "",
placeholder = mutableStateOf("10")
),
) )
val dex = FieldUio.create( val dex = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__dex), label = getString(Res.string.character_sheet_edit__characteristics__dex),
initialValue = sheet?.dexterity?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" } value = sheet?.dexterity?.toString() ?: "",
placeholder = mutableStateOf("10"),
),
) )
val con = FieldUio.create( val con = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__con), label = getString(Res.string.character_sheet_edit__characteristics__con),
initialValue = sheet?.constitution?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" } value = sheet?.constitution?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
) )
val hei = FieldUio.create( val hei = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__hei), label = getString(Res.string.character_sheet_edit__characteristics__hei),
initialValue = sheet?.height?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" } value = sheet?.height?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
) )
val int = FieldUio.create( val int = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__int), label = getString(Res.string.character_sheet_edit__characteristics__int),
initialValue = sheet?.intelligence?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" } value = sheet?.intelligence?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
) )
val pow = FieldUio.create( val pow = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__pow), label = getString(Res.string.character_sheet_edit__characteristics__pow),
initialValue = sheet?.power?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "10" } value = sheet?.power?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
) )
val cha = FieldUio.create( val cha = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__characteristics__cha), label = getString(Res.string.character_sheet_edit__characteristics__cha),
initialValue = sheet?.charisma?.toString() ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "7" } value = sheet?.charisma?.toString() ?: "",
placeholder = mutableStateOf("10"),
)
) )
fun str(): Int = str.unpack() ?: 0 fun str(): Int = str.unpack()?.toIntOrNull() ?: 0
fun dex(): Int = dex.unpack() ?: 0 fun dex(): Int = dex.unpack()?.toIntOrNull() ?: 0
fun con(): Int = con.unpack() ?: 0 fun con(): Int = con.unpack()?.toIntOrNull() ?: 0
fun hei(): Int = hei.unpack() ?: 0 fun hei(): Int = hei.unpack()?.toIntOrNull() ?: 0
fun int(): Int = int.unpack() ?: 0 fun int(): Int = int.unpack()?.toIntOrNull() ?: 0
fun pow(): Int = pow.unpack() ?: 0 fun pow(): Int = pow.unpack()?.toIntOrNull() ?: 0
fun cha(): Int = cha.unpack() ?: 0 fun cha(): Int = cha.unpack()?.toIntOrNull() ?: 0
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title) val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title) val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
return CharacterSheetEditPageUio( return CharacterSheetEditPageUio(
id = sheet?.id ?: UUID.randomUUID().toString(), id = sheet?.id ?: UUID.randomUUID().toString(),
name = FieldUio.create( name = skillFactory.createWrapper(
isLabelDisplayed = false, label = getString(Res.string.character_sheet_edit__name_placeholder),
initialLabel = getString(Res.string.character_sheet_edit__name_placeholder), value = sheet?.name ?: ""
initialValue = sheet?.name ?: ""
), ),
strength = str, strength = str,
dexterity = dex, dexterity = dex,
@ -203,38 +239,45 @@ class CharacterSheetEditFactory(
intelligence = int, intelligence = int,
power = pow, power = pow,
charisma = cha, charisma = cha,
movement = FieldUio.create( movement = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__movement), label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
initialValue = (if (sheet?.overrideMovement == true) "${sheet.movement}" else null) value = skillFactory.createWrapper(
?: "", value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
valuePlaceHolder = { "10" } placeholder = mutableStateOf("10"),
)
), ),
maxHp = FieldUio.create( maxHp = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point), label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
initialValue = (if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else null) ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "${ceil((con() + hei()) / 2f).toInt()}" } value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
)
), ),
maxPP = FieldUio.create( maxPp = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__power_point), label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
initialValue = (if (sheet?.overrideMaxPP == true) "${sheet.maxPP}" else null) ?: "", value = skillFactory.createWrapper(
valuePlaceHolder = { "${pow()}" } value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
placeholder = derivedStateOf { "${pow()}" },
)
), ),
damageBonus = FieldUio.create( damageBonus = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus), label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
initialValue = (if (sheet?.overrideDamageBonus == true) sheet.damageBonus else null) value = skillFactory.createWrapper(
?: "", value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
valuePlaceHolder = { placeholder = derivedStateOf {
bonusDamageUseCase.bonusDamage( bonusDamageUseCase.bonusDamage(
strength = str(), strength = str(),
height = hei() height = hei()
) )
} },
)
), ),
armor = FieldUio.create( armor = SimpleFieldUio(
initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__armor), label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
initialValue = (if (sheet?.overrideArmor == true) sheet.armor.toString() else null) value = skillFactory.createWrapper(
?: "", value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
valuePlaceHolder = { "0" } placeholder = mutableStateOf("0"),
)
), ),
commonSkills = listOf( commonSkills = listOf(
createBaseSkill( createBaseSkill(
@ -409,11 +452,7 @@ class CharacterSheetEditFactory(
) )
} }
private inline fun <reified T> FieldUio.unpack(): T { private fun SimpleFieldUio.unpack(): String? {
val tmp = value.value.ifBlank { valuePlaceHolder.value } return value.value.value.ifBlank { value.placeholder.value }
return when (T::class) {
Int::class -> (tmp.toIntOrNull() ?: 0) as T
else -> tmp as T
}
} }
} }

View file

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

View file

@ -6,7 +6,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetEditDestination import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetEditDestination
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository 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 com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.ActionFieldUio
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import lwacharactersheet.composeapp.generated.resources.Res 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.Icons
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.SkillFieldUio 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.ActionOption
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.option.CheckedOption 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.option.OptionUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield.TextFieldWrapperUio
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__delete__label import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__delete__label
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__label import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__label
@ -19,7 +20,6 @@ import java.util.UUID
class SkillFieldFactory { class SkillFieldFactory {
suspend fun createSkill( suspend fun createSkill(
id: String = UUID.randomUUID().toString(), id: String = UUID.randomUUID().toString(),
label: String, label: String,
@ -53,7 +53,8 @@ class SkillFieldFactory {
fun createWrapper( fun createWrapper(
enable: Boolean = true, enable: Boolean = true,
label: String = "", label: String? = null,
placeholder: State<String?> = mutableStateOf(null),
value: String = "", value: String = "",
): TextFieldWrapperUio { ): TextFieldWrapperUio {
val state = mutableStateOf(value) val state = mutableStateOf(value)
@ -61,6 +62,7 @@ class SkillFieldFactory {
enable = enable, enable = enable,
label = label, label = label,
value = state, value = state,
placeholder = placeholder,
onValueChange = { state.value = it }, 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.runtime.State
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import com.pixelized.desktop.lwa.utils.rememberKeyboardActions import com.pixelized.desktop.lwa.utils.rememberKeyboardActions
@ -16,8 +17,9 @@ import com.pixelized.desktop.lwa.utils.rememberKeyboardActions
@Stable @Stable
data class TextFieldWrapperUio( data class TextFieldWrapperUio(
val enable: Boolean, val enable: Boolean,
val label: String, val label: String?,
val value: State<String>, val value: State<String>,
val placeholder: State<String?>,
val onValueChange: (String) -> Unit, val onValueChange: (String) -> Unit,
) )
@ -38,12 +40,23 @@ fun TextFieldWrapper(
}, },
enabled = wrapper.enable, enabled = wrapper.enable,
singleLine = true, singleLine = true,
label = { placeholder = wrapper.placeholder.value?.let {
Text( {
overflow = TextOverflow.Ellipsis, Text(
maxLines = 1, overflow = TextOverflow.Ellipsis,
text = wrapper.label maxLines = 1,
) text = it
)
}
},
label = wrapper.label?.let {
{
Text(
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = it
)
}
}, },
onValueChange = { wrapper.onValueChange(it) }, onValueChange = { wrapper.onValueChange(it) },
value = wrapper.value.value, value = wrapper.value.value,