Add description to the character sheet skills.
This commit is contained in:
		
							parent
							
								
									4606122264
								
							
						
					
					
						commit
						95122d2c99
					
				
					 14 changed files with 265 additions and 151 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,7 @@ import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
 | 
			
		|||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetJsonFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetFactory
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,7 @@ val factoryDependencies
 | 
			
		|||
        factoryOf(::CharacterSheetJsonFactory)
 | 
			
		||||
        factoryOf(::NetworkFactory)
 | 
			
		||||
        factoryOf(::SkillFieldFactory)
 | 
			
		||||
        factoryOf(::SkillDescriptionFactory)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
val viewModelDependencies
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,11 +5,30 @@ 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.CharacterSheetJson
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.Res
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
 | 
			
		||||
import org.jetbrains.compose.resources.getString
 | 
			
		||||
import kotlin.math.ceil
 | 
			
		||||
 | 
			
		||||
class CharacterSheetJsonFactory(
 | 
			
		||||
    private val bonusDamageUseCase: DamageBonusUseCase,
 | 
			
		||||
    private val arithmeticParser: ArithmeticParser,
 | 
			
		||||
    private val skillDescriptionFactory: SkillDescriptionFactory,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    fun convertToJson(
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +55,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheetJsonV1.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = null,
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +67,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheetJsonV1.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = it.description,
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +79,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheetJsonV1.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = it.description,
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +98,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
        return json
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun convertFromJson(
 | 
			
		||||
    suspend fun convertFromJson(
 | 
			
		||||
        json: CharacterSheetJson,
 | 
			
		||||
    ): CharacterSheet {
 | 
			
		||||
        return when (json) {
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +106,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun convertFromV1(
 | 
			
		||||
    private suspend fun convertFromV1(
 | 
			
		||||
        json: CharacterSheetJsonV1,
 | 
			
		||||
    ): CharacterSheet {
 | 
			
		||||
        val sheet = CharacterSheet(
 | 
			
		||||
| 
						 | 
				
			
			@ -117,6 +139,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = skillDescriptionFactory.baseSkillDescription(id = json.id),
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			@ -128,6 +151,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = it.description,
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			@ -139,6 +163,7 @@ class CharacterSheetJsonFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = it.id,
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    description = it.description,
 | 
			
		||||
                    base = it.base,
 | 
			
		||||
                    bonus = it.bonus,
 | 
			
		||||
                    level = it.level,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,8 +3,12 @@ package com.pixelized.desktop.lwa.repository.characterSheet
 | 
			
		|||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterStorePath
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Dispatchers
 | 
			
		||||
import kotlinx.coroutines.Job
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import kotlinx.serialization.encodeToString
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import java.io.File
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +17,15 @@ class CharacterSheetStore(
 | 
			
		|||
    private val factory: CharacterSheetJsonFactory,
 | 
			
		||||
) {
 | 
			
		||||
    private val characterDirectory = File(characterStorePath()).also { it.mkdirs() }
 | 
			
		||||
    private val flow = MutableStateFlow(value = load())
 | 
			
		||||
    private val jsonFormatter: Json = Json { explicitNulls = false }
 | 
			
		||||
    private val flow = MutableStateFlow<List<CharacterSheet>>(value = emptyList())
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        val scope = CoroutineScope(Dispatchers.IO + Job())
 | 
			
		||||
        scope.launch {
 | 
			
		||||
            flow.value = load()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun characterSheetFlow(): StateFlow<List<CharacterSheet>> = flow
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +37,7 @@ class CharacterSheetStore(
 | 
			
		|||
    fun save(sheet: CharacterSheet) {
 | 
			
		||||
        // convert the character sheet into json format.
 | 
			
		||||
        val json = try {
 | 
			
		||||
            factory.convertToJson(sheet = sheet).let(Json::encodeToString)
 | 
			
		||||
            factory.convertToJson(sheet = sheet).let(jsonFormatter::encodeToString)
 | 
			
		||||
        } catch (exception: Exception) {
 | 
			
		||||
            throw JsonConversionException(root = exception)
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +84,7 @@ class CharacterSheetStore(
 | 
			
		|||
        FileReadException::class,
 | 
			
		||||
        JsonConversionException::class,
 | 
			
		||||
    )
 | 
			
		||||
    fun load(): List<CharacterSheet> {
 | 
			
		||||
    suspend fun load(): List<CharacterSheet> {
 | 
			
		||||
        return characterDirectory
 | 
			
		||||
            .listFiles()
 | 
			
		||||
            ?.mapNotNull { file ->
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +98,7 @@ class CharacterSheetStore(
 | 
			
		|||
                    return@mapNotNull null
 | 
			
		||||
                }
 | 
			
		||||
                try {
 | 
			
		||||
                    val sheet = Json.decodeFromString<CharacterSheetJson>(json)
 | 
			
		||||
                    val sheet = jsonFormatter.decodeFromString<CharacterSheetJson>(json)
 | 
			
		||||
                    factory.convertFromJson(sheet)
 | 
			
		||||
                } catch (exception: Exception) {
 | 
			
		||||
                    throw JsonConversionException(root = exception)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.repository.characterSheet
 | 
			
		||||
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.Res
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
 | 
			
		||||
import org.jetbrains.compose.resources.getString
 | 
			
		||||
 | 
			
		||||
class SkillDescriptionFactory {
 | 
			
		||||
 | 
			
		||||
    suspend fun baseSkillDescription(id: String): String? {
 | 
			
		||||
        return when (id) {
 | 
			
		||||
            CharacterSheet.CommonSkillId.COMBAT_ID -> getString(Res.string.tooltip__skills__combat)
 | 
			
		||||
            CharacterSheet.CommonSkillId.DODGE_ID -> getString(Res.string.tooltip__skills__dodge)
 | 
			
		||||
            CharacterSheet.CommonSkillId.GRAB_ID -> getString(Res.string.tooltip__skills__grab)
 | 
			
		||||
            CharacterSheet.CommonSkillId.THROW_ID -> getString(Res.string.tooltip__skills__throw)
 | 
			
		||||
            CharacterSheet.CommonSkillId.ATHLETICS_ID -> getString(Res.string.tooltip__skills__athletics)
 | 
			
		||||
            CharacterSheet.CommonSkillId.ACROBATICS_ID -> getString(Res.string.tooltip__skills__acrobatics)
 | 
			
		||||
            CharacterSheet.CommonSkillId.PERCEPTION_ID -> getString(Res.string.tooltip__skills__perception)
 | 
			
		||||
            CharacterSheet.CommonSkillId.SEARCH_ID -> getString(Res.string.tooltip__skills__search)
 | 
			
		||||
            CharacterSheet.CommonSkillId.EMPATHY_ID -> getString(Res.string.tooltip__skills__empathy)
 | 
			
		||||
            CharacterSheet.CommonSkillId.PERSUASION_ID -> getString(Res.string.tooltip__skills__persuasion)
 | 
			
		||||
            CharacterSheet.CommonSkillId.INTIMIDATION_ID -> getString(Res.string.tooltip__skills__intimidation)
 | 
			
		||||
            CharacterSheet.CommonSkillId.SPIEL_ID -> getString(Res.string.tooltip__skills__spiel)
 | 
			
		||||
            CharacterSheet.CommonSkillId.BARGAIN_ID -> getString(Res.string.tooltip__skills__bargain)
 | 
			
		||||
            CharacterSheet.CommonSkillId.DISCRETION_ID -> getString(Res.string.tooltip__skills__discretion)
 | 
			
		||||
            CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID -> getString(Res.string.tooltip__skills__sleight_of_hand)
 | 
			
		||||
            CharacterSheet.CommonSkillId.AID_ID -> getString(Res.string.tooltip__skills__aid)
 | 
			
		||||
            else -> null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ data class CharacterSheet(
 | 
			
		|||
    data class Skill(
 | 
			
		||||
        val id: String,
 | 
			
		||||
        val label: String,
 | 
			
		||||
        val description: String?,
 | 
			
		||||
        val base: String,
 | 
			
		||||
        val bonus: Int?,
 | 
			
		||||
        val level: Int?,
 | 
			
		||||
| 
						 | 
				
			
			@ -48,21 +49,21 @@ data class CharacterSheet(
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
    object CommonSkillId {
 | 
			
		||||
        const val COMBAT_ID = "Bagarre"
 | 
			
		||||
        const val DODGE_ID = "Esquive"
 | 
			
		||||
        const val GRAB_ID = "Saisie"
 | 
			
		||||
        const val THROW_ID = "Lancer"
 | 
			
		||||
        const val ATHLETICS_ID = "Athlétisme"
 | 
			
		||||
        const val ACROBATICS_ID = "Acrobatie"
 | 
			
		||||
        const val PERCEPTION_ID = "Perception"
 | 
			
		||||
        const val SEARCH_ID = "Recherche"
 | 
			
		||||
        const val EMPATHY_ID = "Empathie"
 | 
			
		||||
        const val PERSUASION_ID = "Persuasion"
 | 
			
		||||
        const val INTIMIDATION_ID = "Intimidation"
 | 
			
		||||
        const val SPIEL_ID = "Baratin"
 | 
			
		||||
        const val BARGAIN_ID = "Marchandage"
 | 
			
		||||
        const val DISCRETION_ID = "Discrétion"
 | 
			
		||||
        const val SLEIGHT_OF_HAND_ID = "Escamotage"
 | 
			
		||||
        const val AID_ID = "Premiers soins"
 | 
			
		||||
        const val COMBAT_ID = "COMBAT"
 | 
			
		||||
        const val DODGE_ID = "DODGE"
 | 
			
		||||
        const val GRAB_ID = "GRAB"
 | 
			
		||||
        const val THROW_ID = "THROW"
 | 
			
		||||
        const val ATHLETICS_ID = "ATHLETICS"
 | 
			
		||||
        const val ACROBATICS_ID = "ACROBATICS"
 | 
			
		||||
        const val PERCEPTION_ID = "PERCEPTION"
 | 
			
		||||
        const val SEARCH_ID = "SEARCH"
 | 
			
		||||
        const val EMPATHY_ID = "EMPATHY"
 | 
			
		||||
        const val PERSUASION_ID = "PERSUASION"
 | 
			
		||||
        const val INTIMIDATION_ID = "INTIMIDATION"
 | 
			
		||||
        const val SPIEL_ID = "SPIEL"
 | 
			
		||||
        const val BARGAIN_ID = "BARGAIN"
 | 
			
		||||
        const val DISCRETION_ID = "DISCRETION"
 | 
			
		||||
        const val SLEIGHT_OF_HAND_ID = "SLEIGHT_OF_HAND"
 | 
			
		||||
        const val AID_ID = "AID"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -31,10 +31,12 @@ data class CharacterSheetJsonV1(
 | 
			
		|||
    // attack
 | 
			
		||||
    val rolls: List<Roll>,
 | 
			
		||||
) : CharacterSheetJson {
 | 
			
		||||
 | 
			
		||||
    @Serializable
 | 
			
		||||
    data class Skill(
 | 
			
		||||
        val id: String,
 | 
			
		||||
        val label: String,
 | 
			
		||||
        val description: String?,
 | 
			
		||||
        val base: String,
 | 
			
		||||
        val bonus: Int?,
 | 
			
		||||
        val level: Int?,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,8 @@ 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.repository.characterSheet.SkillDescriptionFactory
 | 
			
		||||
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
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.Res
 | 
			
		||||
| 
						 | 
				
			
			@ -26,22 +26,6 @@ import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics
 | 
			
		|||
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__intelligence
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__power
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__strength
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__armor
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__bonus_damage
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hit_point
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +35,7 @@ import org.jetbrains.compose.resources.getString
 | 
			
		|||
 | 
			
		||||
class CharacterSheetFactory(
 | 
			
		||||
    private val skillUseCase: SkillValueComputationUseCase,
 | 
			
		||||
    private val skillDescriptionFactory: SkillDescriptionFactory,
 | 
			
		||||
) {
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val HP = "HP"
 | 
			
		||||
| 
						 | 
				
			
			@ -189,25 +174,6 @@ class CharacterSheetFactory(
 | 
			
		|||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            commonSkills = sheet.commonSkills.map { skill ->
 | 
			
		||||
                val description = when (skill.id) {
 | 
			
		||||
                    CommonSkillId.COMBAT_ID -> getString(Res.string.tooltip__skills__combat)
 | 
			
		||||
                    CommonSkillId.DODGE_ID -> getString(Res.string.tooltip__skills__dodge)
 | 
			
		||||
                    CommonSkillId.GRAB_ID -> getString(Res.string.tooltip__skills__grab)
 | 
			
		||||
                    CommonSkillId.THROW_ID -> getString(Res.string.tooltip__skills__throw)
 | 
			
		||||
                    CommonSkillId.ATHLETICS_ID -> getString(Res.string.tooltip__skills__athletics)
 | 
			
		||||
                    CommonSkillId.ACROBATICS_ID -> getString(Res.string.tooltip__skills__acrobatics)
 | 
			
		||||
                    CommonSkillId.PERCEPTION_ID -> getString(Res.string.tooltip__skills__perception)
 | 
			
		||||
                    CommonSkillId.SEARCH_ID -> getString(Res.string.tooltip__skills__search)
 | 
			
		||||
                    CommonSkillId.EMPATHY_ID -> getString(Res.string.tooltip__skills__empathy)
 | 
			
		||||
                    CommonSkillId.PERSUASION_ID -> getString(Res.string.tooltip__skills__persuasion)
 | 
			
		||||
                    CommonSkillId.INTIMIDATION_ID -> getString(Res.string.tooltip__skills__intimidation)
 | 
			
		||||
                    CommonSkillId.SPIEL_ID -> getString(Res.string.tooltip__skills__spiel)
 | 
			
		||||
                    CommonSkillId.BARGAIN_ID -> getString(Res.string.tooltip__skills__bargain)
 | 
			
		||||
                    CommonSkillId.DISCRETION_ID -> getString(Res.string.tooltip__skills__discretion)
 | 
			
		||||
                    CommonSkillId.SLEIGHT_OF_HAND_ID -> getString(Res.string.tooltip__skills__sleight_of_hand)
 | 
			
		||||
                    CommonSkillId.AID_ID -> getString(Res.string.tooltip__skills__aid)
 | 
			
		||||
                    else -> null
 | 
			
		||||
                }
 | 
			
		||||
                Node(
 | 
			
		||||
                    label = skill.label,
 | 
			
		||||
                    value = skillUseCase.computeSkillValue(
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +181,7 @@ class CharacterSheetFactory(
 | 
			
		|||
                        skill = skill,
 | 
			
		||||
                        diminished = diminished,
 | 
			
		||||
                    ),
 | 
			
		||||
                    tooltips = description?.let {
 | 
			
		||||
                    tooltips = skillDescriptionFactory.baseSkillDescription(id = skill.id)?.let {
 | 
			
		||||
                        TooltipUio(
 | 
			
		||||
                            title = skill.label,
 | 
			
		||||
                            description = it,
 | 
			
		||||
| 
						 | 
				
			
			@ -224,26 +190,38 @@ class CharacterSheetFactory(
 | 
			
		|||
                    used = skill.used,
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            specialSKills = sheet.specialSkills.map {
 | 
			
		||||
            specialSKills = sheet.specialSkills.map { skill ->
 | 
			
		||||
                Node(
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    label = skill.label,
 | 
			
		||||
                    tooltips = skill.description?.takeIf { it.isNotBlank() }?.let { description ->
 | 
			
		||||
                        TooltipUio(
 | 
			
		||||
                            title = skill.label,
 | 
			
		||||
                            description = description,
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                    value = skillUseCase.computeSkillValue(
 | 
			
		||||
                        sheet = sheet,
 | 
			
		||||
                        skill = it,
 | 
			
		||||
                        skill = skill,
 | 
			
		||||
                        diminished = diminished,
 | 
			
		||||
                    ),
 | 
			
		||||
                    used = it.used,
 | 
			
		||||
                    used = skill.used,
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            magicsSkills = sheet.magicSkills.map {
 | 
			
		||||
            magicsSkills = sheet.magicSkills.map { skill ->
 | 
			
		||||
                Node(
 | 
			
		||||
                    label = it.label,
 | 
			
		||||
                    label = skill.label,
 | 
			
		||||
                    tooltips = skill.description?.takeIf { it.isNotBlank() }?.let { description ->
 | 
			
		||||
                        TooltipUio(
 | 
			
		||||
                            title = skill.label,
 | 
			
		||||
                            description = description,
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                    value = skillUseCase.computeSkillValue(
 | 
			
		||||
                        sheet = sheet,
 | 
			
		||||
                        skill = it,
 | 
			
		||||
                        skill = skill,
 | 
			
		||||
                        diminished = diminished,
 | 
			
		||||
                    ),
 | 
			
		||||
                    used = it.used,
 | 
			
		||||
                    used = skill.used,
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            actions = sheet.actions.mapNotNull {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
package com.pixelized.desktop.lwa.screen.characterSheet.detail
 | 
			
		||||
 | 
			
		||||
import androidx.compose.animation.AnimatedContent
 | 
			
		||||
import androidx.compose.animation.AnimatedVisibility
 | 
			
		||||
import androidx.compose.animation.SizeTransform
 | 
			
		||||
import androidx.compose.animation.fadeIn
 | 
			
		||||
import androidx.compose.animation.fadeOut
 | 
			
		||||
| 
						 | 
				
			
			@ -446,47 +447,55 @@ fun CharacterSheetPageContent(
 | 
			
		|||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    DecoratedBox(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .fillMaxWidth()
 | 
			
		||||
                            .padding(vertical = 8.dp),
 | 
			
		||||
                    AnimatedVisibility(
 | 
			
		||||
                        visible = characterSheet.specialSKills.isNotEmpty()
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Column {
 | 
			
		||||
                            Text(
 | 
			
		||||
                                modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
 | 
			
		||||
                                style = MaterialTheme.typography.caption,
 | 
			
		||||
                                textAlign = TextAlign.Center,
 | 
			
		||||
                                text = stringResource(Res.string.character_sheet__skills__special_title),
 | 
			
		||||
                            )
 | 
			
		||||
                            characterSheet.specialSKills.forEach { occupation ->
 | 
			
		||||
                                Skill(
 | 
			
		||||
                                    modifier = Modifier.cell(),
 | 
			
		||||
                                    node = occupation,
 | 
			
		||||
                                    onClick = { onSkill(occupation) },
 | 
			
		||||
                                    onUse = { onUseSkill(occupation) },
 | 
			
		||||
                        DecoratedBox(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .fillMaxWidth()
 | 
			
		||||
                                .padding(vertical = 8.dp),
 | 
			
		||||
                        ) {
 | 
			
		||||
                            Column {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
 | 
			
		||||
                                    style = MaterialTheme.typography.caption,
 | 
			
		||||
                                    textAlign = TextAlign.Center,
 | 
			
		||||
                                    text = stringResource(Res.string.character_sheet__skills__special_title),
 | 
			
		||||
                                )
 | 
			
		||||
                                characterSheet.specialSKills.forEach { occupation ->
 | 
			
		||||
                                    Skill(
 | 
			
		||||
                                        modifier = Modifier.cell(),
 | 
			
		||||
                                        node = occupation,
 | 
			
		||||
                                        onClick = { onSkill(occupation) },
 | 
			
		||||
                                        onUse = { onUseSkill(occupation) },
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    DecoratedBox(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .fillMaxWidth()
 | 
			
		||||
                            .padding(vertical = 8.dp),
 | 
			
		||||
                    AnimatedVisibility(
 | 
			
		||||
                        visible = characterSheet.magicsSkills.isNotEmpty()
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Column {
 | 
			
		||||
                            Text(
 | 
			
		||||
                                modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
 | 
			
		||||
                                style = MaterialTheme.typography.caption,
 | 
			
		||||
                                textAlign = TextAlign.Center,
 | 
			
		||||
                                text = stringResource(Res.string.character_sheet__skills__magic_title),
 | 
			
		||||
                            )
 | 
			
		||||
                            characterSheet.magicsSkills.forEach { magic ->
 | 
			
		||||
                                Skill(
 | 
			
		||||
                                    modifier = Modifier.cell(),
 | 
			
		||||
                                    node = magic,
 | 
			
		||||
                                    onClick = { onSkill(magic) },
 | 
			
		||||
                                    onUse = { onUseSkill(magic) },
 | 
			
		||||
                        DecoratedBox(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .fillMaxWidth()
 | 
			
		||||
                                .padding(vertical = 8.dp),
 | 
			
		||||
                        ) {
 | 
			
		||||
                            Column {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
 | 
			
		||||
                                    style = MaterialTheme.typography.caption,
 | 
			
		||||
                                    textAlign = TextAlign.Center,
 | 
			
		||||
                                    text = stringResource(Res.string.character_sheet__skills__magic_title),
 | 
			
		||||
                                )
 | 
			
		||||
                                characterSheet.magicsSkills.forEach { magic ->
 | 
			
		||||
                                    Skill(
 | 
			
		||||
                                        modifier = Modifier.cell(),
 | 
			
		||||
                                        node = magic,
 | 
			
		||||
                                        onClick = { onSkill(magic) },
 | 
			
		||||
                                        onUse = { onUseSkill(magic) },
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import androidx.compose.runtime.derivedStateOf
 | 
			
		|||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.occupation
 | 
			
		||||
| 
						 | 
				
			
			@ -57,10 +58,11 @@ import kotlin.math.min
 | 
			
		|||
 | 
			
		||||
class CharacterSheetEditFactory(
 | 
			
		||||
    private val bonusDamageUseCase: DamageBonusUseCase,
 | 
			
		||||
    private val skillFactory: SkillFieldFactory,
 | 
			
		||||
    private val skillFieldFactory: SkillFieldFactory,
 | 
			
		||||
    private val skillDescriptionFactory: SkillDescriptionFactory,
 | 
			
		||||
    private val normalizer: SkillNormalizerUseCase,
 | 
			
		||||
) {
 | 
			
		||||
    fun updateCharacterSheet(
 | 
			
		||||
    suspend fun updateCharacterSheet(
 | 
			
		||||
        currentSheet: CharacterSheet?,
 | 
			
		||||
        editedSheet: CharacterSheetEditPageUio,
 | 
			
		||||
    ): CharacterSheet {
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +123,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = editedSkill.id,
 | 
			
		||||
                    label = editedSkill.label,
 | 
			
		||||
                    description = skillDescriptionFactory.baseSkillDescription(editedSkill.id),
 | 
			
		||||
                    base = "${editedSkill.base.value}",
 | 
			
		||||
                    bonus = editedSkill.bonus.value.value.toIntOrNull(),
 | 
			
		||||
                    level = editedSkill.level.value.value.toIntOrNull(),
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +138,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = editedSkill.id,
 | 
			
		||||
                    label = editedSkill.label.value.value,
 | 
			
		||||
                    description = editedSkill.description.value.value,
 | 
			
		||||
                    base = editedSkill.base.value.value,
 | 
			
		||||
                    bonus = editedSkill.bonus.value.value.toIntOrNull(),
 | 
			
		||||
                    level = editedSkill.level.value.value.toIntOrNull(),
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +153,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                CharacterSheet.Skill(
 | 
			
		||||
                    id = editedSkill.id,
 | 
			
		||||
                    label = editedSkill.label.value.value,
 | 
			
		||||
                    description = editedSkill.description.value.value,
 | 
			
		||||
                    base = editedSkill.base.value.value,
 | 
			
		||||
                    bonus = editedSkill.bonus.value.value.toIntOrNull(),
 | 
			
		||||
                    level = editedSkill.level.value.value.toIntOrNull(),
 | 
			
		||||
| 
						 | 
				
			
			@ -172,49 +177,49 @@ class CharacterSheetEditFactory(
 | 
			
		|||
    ): CharacterSheetEditPageUio {
 | 
			
		||||
        val str = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__str),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.strength?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10")
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        val dex = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__dex),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.dexterity?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        val con = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__con),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.constitution?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        val hei = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__hei),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.height?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        val int = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__int),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.intelligence?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        val pow = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__pow),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.power?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        val cha = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__characteristics__cha),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = sheet?.charisma?.toString() ?: "",
 | 
			
		||||
                placeholder = mutableStateOf("10"),
 | 
			
		||||
            )
 | 
			
		||||
| 
						 | 
				
			
			@ -233,14 +238,14 @@ class CharacterSheetEditFactory(
 | 
			
		|||
 | 
			
		||||
        val maxHitPoint = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
 | 
			
		||||
                placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        val maxPowerPoint = SimpleFieldUio(
 | 
			
		||||
            label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
 | 
			
		||||
            value = skillFactory.createWrapper(
 | 
			
		||||
            value = skillFieldFactory.createWrapper(
 | 
			
		||||
                value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
 | 
			
		||||
                placeholder = derivedStateOf { "${pow()}" },
 | 
			
		||||
            )
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +253,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
 | 
			
		||||
        return CharacterSheetEditPageUio(
 | 
			
		||||
            id = sheet?.id ?: UUID.randomUUID().toString(),
 | 
			
		||||
            name = skillFactory.createWrapper(
 | 
			
		||||
            name = skillFieldFactory.createWrapper(
 | 
			
		||||
                label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
 | 
			
		||||
                value = sheet?.name ?: ""
 | 
			
		||||
            ),
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +266,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            charisma = cha,
 | 
			
		||||
            movement = SimpleFieldUio(
 | 
			
		||||
                label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
 | 
			
		||||
                value = skillFactory.createWrapper(
 | 
			
		||||
                value = skillFieldFactory.createWrapper(
 | 
			
		||||
                    value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
 | 
			
		||||
                    placeholder = mutableStateOf("10"),
 | 
			
		||||
                )
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +274,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            maxHp = maxHitPoint,
 | 
			
		||||
            currentHp = SimpleFieldUio(
 | 
			
		||||
                label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
 | 
			
		||||
                value = skillFactory.createWrapper(
 | 
			
		||||
                value = skillFieldFactory.createWrapper(
 | 
			
		||||
                    enable = false,
 | 
			
		||||
                    placeholder = derivedStateOf {
 | 
			
		||||
                        val min = min(
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +288,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            maxPp = maxPowerPoint,
 | 
			
		||||
            currentPp = SimpleFieldUio(
 | 
			
		||||
                label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
 | 
			
		||||
                value = skillFactory.createWrapper(
 | 
			
		||||
                value = skillFieldFactory.createWrapper(
 | 
			
		||||
                    enable = false,
 | 
			
		||||
                    placeholder = derivedStateOf {
 | 
			
		||||
                        val min = min(
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +301,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            ),
 | 
			
		||||
            damageBonus = SimpleFieldUio(
 | 
			
		||||
                label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
 | 
			
		||||
                value = skillFactory.createWrapper(
 | 
			
		||||
                value = skillFieldFactory.createWrapper(
 | 
			
		||||
                    value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
 | 
			
		||||
                    placeholder = derivedStateOf {
 | 
			
		||||
                        bonusDamageUseCase.bonusDamage(
 | 
			
		||||
| 
						 | 
				
			
			@ -308,7 +313,7 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            ),
 | 
			
		||||
            armor = SimpleFieldUio(
 | 
			
		||||
                label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
 | 
			
		||||
                value = skillFactory.createWrapper(
 | 
			
		||||
                value = skillFieldFactory.createWrapper(
 | 
			
		||||
                    value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
 | 
			
		||||
                    placeholder = mutableStateOf("0"),
 | 
			
		||||
                )
 | 
			
		||||
| 
						 | 
				
			
			@ -412,9 +417,10 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            specialSkills = sheet?.specialSkills?.map { skill ->
 | 
			
		||||
                skillFactory.createSkill(
 | 
			
		||||
                skillFieldFactory.createSkill(
 | 
			
		||||
                    id = skill.id,
 | 
			
		||||
                    label = specialSkillsLabel,
 | 
			
		||||
                    descriptionValue = skill.description ?: "",
 | 
			
		||||
                    labelValue = skill.label,
 | 
			
		||||
                    baseValue = skill.base,
 | 
			
		||||
                    bonusValue = skill.bonus?.toString() ?: "",
 | 
			
		||||
| 
						 | 
				
			
			@ -422,16 +428,17 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                    options = run {
 | 
			
		||||
                        val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
 | 
			
		||||
                        listOf(
 | 
			
		||||
                            skillFactory.occupationOption(checked = current?.occupation ?: false),
 | 
			
		||||
                            skillFactory.deleteOption { onDeleteSkill(skill.id) },
 | 
			
		||||
                            skillFieldFactory.occupationOption(checked = current?.occupation ?: false),
 | 
			
		||||
                            skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
            } ?: emptyList(),
 | 
			
		||||
            magicSkills = sheet?.magicSkills?.map { skill ->
 | 
			
		||||
                skillFactory.createSkill(
 | 
			
		||||
                skillFieldFactory.createSkill(
 | 
			
		||||
                    id = skill.id,
 | 
			
		||||
                    label = magicSkillsLabel,
 | 
			
		||||
                    descriptionValue = skill.description ?: "",
 | 
			
		||||
                    labelValue = skill.label,
 | 
			
		||||
                    baseValue = skill.base,
 | 
			
		||||
                    bonusValue = skill.bonus?.toString() ?: "",
 | 
			
		||||
| 
						 | 
				
			
			@ -439,8 +446,8 @@ class CharacterSheetEditFactory(
 | 
			
		|||
                    options = run {
 | 
			
		||||
                        val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
 | 
			
		||||
                        listOf(
 | 
			
		||||
                            skillFactory.occupationOption(checked = current?.occupation ?: false),
 | 
			
		||||
                            skillFactory.deleteOption { onDeleteSkill(skill.id) },
 | 
			
		||||
                            skillFieldFactory.occupationOption(checked = current?.occupation ?: false),
 | 
			
		||||
                            skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
| 
						 | 
				
			
			@ -448,15 +455,15 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            actions = sheet?.actions?.map { action ->
 | 
			
		||||
                ActionFieldUio(
 | 
			
		||||
                    id = action.id,
 | 
			
		||||
                    label = skillFactory.createWrapper(
 | 
			
		||||
                    label = skillFieldFactory.createWrapper(
 | 
			
		||||
                        label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
 | 
			
		||||
                        value = action.label,
 | 
			
		||||
                    ),
 | 
			
		||||
                    action = skillFactory.createWrapper(
 | 
			
		||||
                    action = skillFieldFactory.createWrapper(
 | 
			
		||||
                        label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
 | 
			
		||||
                        value = action.roll,
 | 
			
		||||
                    ),
 | 
			
		||||
                    option = skillFactory.deleteOption { onDeleteSkill(action.id) },
 | 
			
		||||
                    option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
 | 
			
		||||
                )
 | 
			
		||||
            } ?: emptyList(),
 | 
			
		||||
        )
 | 
			
		||||
| 
						 | 
				
			
			@ -474,15 +481,15 @@ class CharacterSheetEditFactory(
 | 
			
		|||
            id = id,
 | 
			
		||||
            label = label,
 | 
			
		||||
            base = base,
 | 
			
		||||
            bonus = skillFactory.createWrapper(
 | 
			
		||||
            bonus = skillFieldFactory.createWrapper(
 | 
			
		||||
                label = mutableStateOf(getString(Res.string.character_sheet_edit__skills__bonus_label)),
 | 
			
		||||
                value = skill?.bonus?.toString() ?: "",
 | 
			
		||||
            ),
 | 
			
		||||
            level = skillFactory.createWrapper(
 | 
			
		||||
            level = skillFieldFactory.createWrapper(
 | 
			
		||||
                label = mutableStateOf(getString(Res.string.character_sheet_edit__skills__level_label)),
 | 
			
		||||
                value = skill?.level?.toString() ?: "",
 | 
			
		||||
            ),
 | 
			
		||||
            option = skillFactory.occupationOption(skill?.occupation ?: false),
 | 
			
		||||
            option = skillFieldFactory.occupationOption(skill?.occupation ?: false),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -273,6 +273,7 @@ fun CharacterSheetEdit(
 | 
			
		|||
                    Column(
 | 
			
		||||
                        modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                        verticalArrangement = Arrangement.spacedBy(space = 16.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            modifier = Modifier.padding(vertical = 8.dp),
 | 
			
		||||
| 
						 | 
				
			
			@ -319,6 +320,7 @@ fun CharacterSheetEdit(
 | 
			
		|||
                    Column(
 | 
			
		||||
                        modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                        verticalArrangement = Arrangement.spacedBy(space = 16.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            modifier = Modifier.padding(vertical = 8.dp),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__de
 | 
			
		|||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__label
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__base_label
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__bonus_label
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__description_label
 | 
			
		||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__level_label
 | 
			
		||||
import org.jetbrains.compose.resources.getString
 | 
			
		||||
import java.util.UUID
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +26,7 @@ class SkillFieldFactory {
 | 
			
		|||
        id: String = UUID.randomUUID().toString(),
 | 
			
		||||
        label: String,
 | 
			
		||||
        labelValue: String = "",
 | 
			
		||||
        descriptionValue: String = "",
 | 
			
		||||
        baseValue: String = "",
 | 
			
		||||
        bonusValue: String = "",
 | 
			
		||||
        levelValue: String = "",
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +39,10 @@ class SkillFieldFactory {
 | 
			
		|||
                label = mutableStateOf(label),
 | 
			
		||||
                value = labelValue,
 | 
			
		||||
            ),
 | 
			
		||||
            description = createWrapper(
 | 
			
		||||
                label = mutableStateOf(getString(Res.string.character_sheet_edit__skills__description_label)),
 | 
			
		||||
                value = descriptionValue,
 | 
			
		||||
            ),
 | 
			
		||||
            base = createWrapper(
 | 
			
		||||
                label = derivedStateOf {
 | 
			
		||||
                    options
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,9 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit.composable
 | 
			
		|||
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Box
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.width
 | 
			
		||||
import androidx.compose.material.DropdownMenu
 | 
			
		||||
import androidx.compose.material.Icon
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +16,6 @@ import androidx.compose.runtime.Composable
 | 
			
		|||
import androidx.compose.runtime.Stable
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.option.DropDownMenuItemWrapper
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +27,7 @@ import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.textfield
 | 
			
		|||
class SkillFieldUio(
 | 
			
		||||
    val id: String,
 | 
			
		||||
    val label: TextFieldWrapperUio,
 | 
			
		||||
    val description: TextFieldWrapperUio,
 | 
			
		||||
    val base: TextFieldWrapperUio,
 | 
			
		||||
    val bonus: TextFieldWrapperUio,
 | 
			
		||||
    val level: TextFieldWrapperUio,
 | 
			
		||||
| 
						 | 
				
			
			@ -41,25 +43,38 @@ fun SkillForm(
 | 
			
		|||
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        horizontalArrangement = Arrangement.spacedBy(space = 4.dp, alignment = Alignment.End),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
        horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
 | 
			
		||||
    ) {
 | 
			
		||||
        TextFieldWrapper(
 | 
			
		||||
        Column(
 | 
			
		||||
            modifier = Modifier.weight(1f),
 | 
			
		||||
            wrapper = field.label,
 | 
			
		||||
        )
 | 
			
		||||
        TextFieldWrapper(
 | 
			
		||||
            modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
            wrapper = field.base,
 | 
			
		||||
        )
 | 
			
		||||
        TextFieldWrapper(
 | 
			
		||||
            modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
            wrapper = field.bonus,
 | 
			
		||||
        )
 | 
			
		||||
        TextFieldWrapper(
 | 
			
		||||
            modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
            wrapper = field.level,
 | 
			
		||||
        )
 | 
			
		||||
            verticalArrangement = Arrangement.spacedBy(space = 4.dp)
 | 
			
		||||
        ) {
 | 
			
		||||
            Row(
 | 
			
		||||
                horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
 | 
			
		||||
            ) {
 | 
			
		||||
                TextFieldWrapper(
 | 
			
		||||
                    modifier = Modifier.weight(1f),
 | 
			
		||||
                    wrapper = field.label,
 | 
			
		||||
                )
 | 
			
		||||
                TextFieldWrapper(
 | 
			
		||||
                    modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
                    wrapper = field.base,
 | 
			
		||||
                )
 | 
			
		||||
                TextFieldWrapper(
 | 
			
		||||
                    modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
                    wrapper = field.bonus,
 | 
			
		||||
                )
 | 
			
		||||
                TextFieldWrapper(
 | 
			
		||||
                    modifier = Modifier.width(width = 96.dp),
 | 
			
		||||
                    wrapper = field.level,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            TextFieldWrapper(
 | 
			
		||||
                modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                singleLine = false,
 | 
			
		||||
                wrapper = field.description,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        if (field.options.isNotEmpty()) {
 | 
			
		||||
            Box {
 | 
			
		||||
                IconButton(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ import androidx.compose.ui.platform.LocalFocusManager
 | 
			
		|||
import androidx.compose.ui.text.style.TextOverflow
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.desktop.lwa.utils.rememberKeyboardActions
 | 
			
		||||
import kotlin.math.sin
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
data class TextFieldWrapperUio(
 | 
			
		||||
| 
						 | 
				
			
			@ -28,13 +29,19 @@ data class TextFieldWrapperUio(
 | 
			
		|||
@Composable
 | 
			
		||||
fun TextFieldWrapper(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    singleLine: Boolean = true,
 | 
			
		||||
    wrapper: TextFieldWrapperUio,
 | 
			
		||||
) {
 | 
			
		||||
    val colorScheme = MaterialTheme.colors
 | 
			
		||||
    val focus = LocalFocusManager.current
 | 
			
		||||
    val localModifier = if (singleLine) {
 | 
			
		||||
        Modifier.height(height = 56.dp)
 | 
			
		||||
    } else {
 | 
			
		||||
        Modifier
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TextField(
 | 
			
		||||
        modifier = Modifier.height(height = 56.dp).then(other = modifier),
 | 
			
		||||
        modifier = localModifier.then(other = modifier),
 | 
			
		||||
        colors = TextFieldDefaults.textFieldColors(
 | 
			
		||||
            backgroundColor = remember(wrapper.enable) {
 | 
			
		||||
                when (wrapper.enable) {
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +54,7 @@ fun TextFieldWrapper(
 | 
			
		|||
            focus.moveFocus(FocusDirection.Next)
 | 
			
		||||
        },
 | 
			
		||||
        enabled = wrapper.enable,
 | 
			
		||||
        singleLine = true,
 | 
			
		||||
        singleLine = singleLine,
 | 
			
		||||
        placeholder = wrapper.placeholder.value?.let {
 | 
			
		||||
            {
 | 
			
		||||
                Text(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue