Rework the UI of the character sheet to fit the paper one.
This commit is contained in:
		
							parent
							
								
									f840777929
								
							
						
					
					
						commit
						5fe6cd0c01
					
				
					 16 changed files with 1024 additions and 1100 deletions
				
			
		| 
						 | 
				
			
			@ -5,14 +5,12 @@ import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		|||
import com.pixelized.rplexicon.ui.screens.character.CharacterSheetUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.LabelPointUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.ProficiencyUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.SavingsThrowsUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.StatUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.modifier
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.toLabel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class ConvertCharacterSheetIntoDisplayableFactory @Inject constructor() {
 | 
			
		||||
 | 
			
		||||
    fun toUio(sheet: CharacterSheet): CharacterSheetUio {
 | 
			
		||||
        return CharacterSheetUio(
 | 
			
		||||
            armorClass = LabelPointUio(
 | 
			
		||||
| 
						 | 
				
			
			@ -20,183 +18,176 @@ class ConvertCharacterSheetIntoDisplayableFactory @Inject constructor() {
 | 
			
		|||
                value = "${sheet.armorClass}",
 | 
			
		||||
                max = null,
 | 
			
		||||
            ),
 | 
			
		||||
            speed = LabelPointUio(
 | 
			
		||||
                label = R.string.character_sheet_title_speed,
 | 
			
		||||
                value = "${sheet.speed}",
 | 
			
		||||
                max = "m",
 | 
			
		||||
            ),
 | 
			
		||||
            hitPoint = LabelPointUio(
 | 
			
		||||
                label = R.string.character_sheet_title_hp,
 | 
			
		||||
                value = "${sheet.hitPoint}",
 | 
			
		||||
                max = "${sheet.maxHitPoint}",
 | 
			
		||||
                max = "/ ${sheet.maxHitPoint}",
 | 
			
		||||
            ),
 | 
			
		||||
            initiative = LabelPointUio(
 | 
			
		||||
                label = R.string.character_sheet_title_initiative,
 | 
			
		||||
                value = sheet.dexterity.modifier.toLabel(),
 | 
			
		||||
                max = null,
 | 
			
		||||
            ),
 | 
			
		||||
            strength = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_strength,
 | 
			
		||||
                value = sheet.strength,
 | 
			
		||||
                modifier = sheet.strength.modifier,
 | 
			
		||||
            stats = listOf(
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.STRENGTH,
 | 
			
		||||
                    value = sheet.strength,
 | 
			
		||||
                    modifier = sheet.strength.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.DEXTERITY,
 | 
			
		||||
                    value = sheet.dexterity,
 | 
			
		||||
                    modifier = sheet.dexterity.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.CONSTITUTION,
 | 
			
		||||
                    value = sheet.constitution,
 | 
			
		||||
                    modifier = sheet.constitution.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.INTELLIGENCE,
 | 
			
		||||
                    value = sheet.intelligence,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.WISDOM,
 | 
			
		||||
                    value = sheet.wisdom,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
                StatUio(
 | 
			
		||||
                    id = StatUio.ID.CHARISMA,
 | 
			
		||||
                    value = sheet.charisma,
 | 
			
		||||
                    modifier = sheet.charisma.modifier,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            dexterity = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
                value = sheet.dexterity,
 | 
			
		||||
                modifier = sheet.dexterity.modifier,
 | 
			
		||||
            savingThrows = listOf(
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.STRENGTH_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.strengthSavingThrows,
 | 
			
		||||
                    modifier = sheet.strength.modifier + sheet.strengthSavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.DEXTERITY_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.dexteritySavingThrows,
 | 
			
		||||
                    modifier = sheet.dexterity.modifier + sheet.dexteritySavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.CONSTITUTION_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.constitutionSavingThrows,
 | 
			
		||||
                    modifier = sheet.constitution.modifier + sheet.constitutionSavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.INTELLIGENCE_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.intelligenceSavingThrows,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.intelligenceSavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.WISDOM_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.wisdomSavingThrows,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.wisdomSavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.CHARISMA_SAVING_THROW,
 | 
			
		||||
                    multiplier = sheet.charismaSavingThrows,
 | 
			
		||||
                    modifier = sheet.charisma.modifier + sheet.charismaSavingThrows * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            constitution = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
                value = sheet.constitution,
 | 
			
		||||
                modifier = sheet.constitution.modifier,
 | 
			
		||||
            ),
 | 
			
		||||
            intelligence = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
                value = sheet.intelligence,
 | 
			
		||||
                modifier = sheet.intelligence.modifier,
 | 
			
		||||
            ),
 | 
			
		||||
            wisdom = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_wisdom,
 | 
			
		||||
                value = sheet.wisdom,
 | 
			
		||||
                modifier = sheet.wisdom.modifier,
 | 
			
		||||
            ),
 | 
			
		||||
            charisma = StatUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
                value = sheet.charisma,
 | 
			
		||||
                modifier = sheet.charisma.modifier,
 | 
			
		||||
            ),
 | 
			
		||||
            strengthSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_strength,
 | 
			
		||||
                multiplier = sheet.strengthSavingThrows,
 | 
			
		||||
                modifier = sheet.strength.modifier + sheet.strengthSavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            dexteritySavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
                multiplier = sheet.dexteritySavingThrows,
 | 
			
		||||
                modifier = sheet.dexterity.modifier + sheet.dexteritySavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            constitutionSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
                multiplier = sheet.constitutionSavingThrows,
 | 
			
		||||
                modifier = sheet.constitution.modifier + sheet.constitutionSavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            intelligenceSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
                multiplier = sheet.intelligenceSavingThrows,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.intelligenceSavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            wisdomSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_wisdom,
 | 
			
		||||
                multiplier = sheet.wisdomSavingThrows,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.wisdomSavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            charismaSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
                multiplier = sheet.charismaSavingThrows,
 | 
			
		||||
                modifier = sheet.charisma.modifier + sheet.charismaSavingThrows * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            acrobatics = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_acrobatics,
 | 
			
		||||
                related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                multiplier = sheet.acrobatics,
 | 
			
		||||
                modifier = sheet.dexterity.modifier + sheet.acrobatics * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            animalHandling = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_animal_handling,
 | 
			
		||||
                related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                multiplier = sheet.animalHandling,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.animalHandling * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            arcana = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_arcana,
 | 
			
		||||
                related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                multiplier = sheet.arcana,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.arcana * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            athletics = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_athletics,
 | 
			
		||||
                related = R.string.character_sheet_stat_strength_short,
 | 
			
		||||
                multiplier = sheet.athletics,
 | 
			
		||||
                modifier = sheet.strength.modifier + sheet.athletics * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            deception = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_deception,
 | 
			
		||||
                related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                multiplier = sheet.deception,
 | 
			
		||||
                modifier = sheet.charisma.modifier + sheet.deception * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            history = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_history,
 | 
			
		||||
                related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                multiplier = sheet.history,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.history * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            insight = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_insight,
 | 
			
		||||
                related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                multiplier = sheet.insight,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.insight * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            intimidation = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_intimidation,
 | 
			
		||||
                related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                multiplier = sheet.intimidation,
 | 
			
		||||
                modifier = sheet.charisma.modifier + sheet.intimidation * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            investigation = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_investigation,
 | 
			
		||||
                related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                multiplier = sheet.investigation,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.investigation * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            medicine = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_medicine,
 | 
			
		||||
                related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                multiplier = sheet.medicine,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.medicine * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            nature = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_nature,
 | 
			
		||||
                related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                multiplier = sheet.nature,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.nature * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            perception = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_perception,
 | 
			
		||||
                related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                multiplier = sheet.perception,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.perception * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            performance = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_performance,
 | 
			
		||||
                related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                multiplier = sheet.performance,
 | 
			
		||||
                modifier = sheet.charisma.modifier + sheet.performance * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            persuasion = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_persuasion,
 | 
			
		||||
                related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                multiplier = sheet.persuasion,
 | 
			
		||||
                modifier = sheet.charisma.modifier + sheet.persuasion * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            religion = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_religion,
 | 
			
		||||
                related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                multiplier = sheet.religion,
 | 
			
		||||
                modifier = sheet.intelligence.modifier + sheet.religion * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            sleightOfHand = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_sleight_of_hand,
 | 
			
		||||
                related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                multiplier = sheet.sleightOfHand,
 | 
			
		||||
                modifier = sheet.dexterity.modifier + sheet.sleightOfHand * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            stealth = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_stealth,
 | 
			
		||||
                related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                multiplier = sheet.stealth,
 | 
			
		||||
                modifier = sheet.dexterity.modifier + sheet.stealth * sheet.proficiency,
 | 
			
		||||
            ),
 | 
			
		||||
            survival = ProficiencyUio(
 | 
			
		||||
                label = R.string.character_sheet_proficiency_survival,
 | 
			
		||||
                related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                multiplier = sheet.survival,
 | 
			
		||||
                modifier = sheet.wisdom.modifier + sheet.survival * sheet.proficiency,
 | 
			
		||||
            proficiencies = listOf(
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.ACROBATICS,
 | 
			
		||||
                    multiplier = sheet.acrobatics,
 | 
			
		||||
                    modifier = sheet.dexterity.modifier + sheet.acrobatics * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.ARCANA,
 | 
			
		||||
                    multiplier = sheet.arcana,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.arcana * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.ATHLETICS,
 | 
			
		||||
                    multiplier = sheet.athletics,
 | 
			
		||||
                    modifier = sheet.strength.modifier + sheet.athletics * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.STEALTH,
 | 
			
		||||
                    multiplier = sheet.stealth,
 | 
			
		||||
                    modifier = sheet.dexterity.modifier + sheet.stealth * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.ANIMAL_HANDLING,
 | 
			
		||||
                    multiplier = sheet.animalHandling,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.animalHandling * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.SLEIGHT_OF_HAND,
 | 
			
		||||
                    multiplier = sheet.sleightOfHand,
 | 
			
		||||
                    modifier = sheet.dexterity.modifier + sheet.sleightOfHand * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.HISTORY,
 | 
			
		||||
                    multiplier = sheet.history,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.history * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.INTIMIDATION,
 | 
			
		||||
                    multiplier = sheet.intimidation,
 | 
			
		||||
                    modifier = sheet.charisma.modifier + sheet.intimidation * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.INSIGHT,
 | 
			
		||||
                    multiplier = sheet.insight,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.insight * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.INVESTIGATION,
 | 
			
		||||
                    multiplier = sheet.investigation,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.investigation * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.MEDICINE,
 | 
			
		||||
                    multiplier = sheet.medicine,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.medicine * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.NATURE,
 | 
			
		||||
                    multiplier = sheet.nature,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.nature * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.PERCEPTION,
 | 
			
		||||
                    multiplier = sheet.perception,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.perception * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.PERSUASION,
 | 
			
		||||
                    multiplier = sheet.persuasion,
 | 
			
		||||
                    modifier = sheet.charisma.modifier + sheet.persuasion * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.RELIGION,
 | 
			
		||||
                    multiplier = sheet.religion,
 | 
			
		||||
                    modifier = sheet.intelligence.modifier + sheet.religion * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.PERFORMANCE,
 | 
			
		||||
                    multiplier = sheet.performance,
 | 
			
		||||
                    modifier = sheet.charisma.modifier + sheet.performance * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.SURVIVAL,
 | 
			
		||||
                    multiplier = sheet.survival,
 | 
			
		||||
                    modifier = sheet.wisdom.modifier + sheet.survival * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
                ProficiencyUio(
 | 
			
		||||
                    id = ProficiencyUio.ID.DECEPTION,
 | 
			
		||||
                    multiplier = sheet.deception,
 | 
			
		||||
                    modifier = sheet.charisma.modifier + sheet.deception * sheet.proficiency,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,9 +22,12 @@ class CharacterSheetParser @Inject constructor() {
 | 
			
		|||
 | 
			
		||||
        // prepare a hash on the structure & function to get index in it.
 | 
			
		||||
        lateinit var structure: Map<String, Int>
 | 
			
		||||
        fun List<*>.parse(key: String): Int =
 | 
			
		||||
        fun List<*>.parseInt(key: String): Int =
 | 
			
		||||
            (getOrNull(structure.getValue(key)) as? String)?.toIntOrNull() ?: 0
 | 
			
		||||
 | 
			
		||||
        fun List<*>.parseString(key: String): String? =
 | 
			
		||||
            (getOrNull(structure.getValue(key)) as? String)
 | 
			
		||||
 | 
			
		||||
        // parse the sheet
 | 
			
		||||
        return sheet?.mapIndexedNotNull { index, item ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,44 +37,45 @@ class CharacterSheetParser @Inject constructor() {
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
                else -> {
 | 
			
		||||
                    val name = item.getOrNull(structure.getValue(NAME)) as String?
 | 
			
		||||
                    val name = item.parseString(NAME)
 | 
			
		||||
                    if (name != null) {
 | 
			
		||||
                        CharacterSheet(
 | 
			
		||||
                            name = name,
 | 
			
		||||
                            hitPoint = item.parse(HIT_POINT),
 | 
			
		||||
                            maxHitPoint = item.parse(MAX_HIT_POINT),
 | 
			
		||||
                            armorClass = item.parse(ARMOR_CLASS),
 | 
			
		||||
                            proficiency = item.parse(MASTERY),
 | 
			
		||||
                            strength = item.parse(STRENGTH),
 | 
			
		||||
                            dexterity = item.parse(DEXTERITY),
 | 
			
		||||
                            constitution = item.parse(CONSTITUTION),
 | 
			
		||||
                            intelligence = item.parse(INTELLIGENCE),
 | 
			
		||||
                            wisdom = item.parse(WISDOM),
 | 
			
		||||
                            charisma = item.parse(CHARISMA),
 | 
			
		||||
                            strengthSavingThrows = item.parse(STRENGTH_SAVING_THROW),
 | 
			
		||||
                            dexteritySavingThrows = item.parse(DEXTERITY_SAVING_THROW),
 | 
			
		||||
                            constitutionSavingThrows = item.parse(CONSTITUTION_SAVING_THROW),
 | 
			
		||||
                            intelligenceSavingThrows = item.parse(INTELLIGENCE_SAVING_THROW),
 | 
			
		||||
                            wisdomSavingThrows = item.parse(WISDOM_SAVING_THROW),
 | 
			
		||||
                            charismaSavingThrows = item.parse(CHARISMA_SAVING_THROW),
 | 
			
		||||
                            acrobatics = item.parse(ACROBATICS),
 | 
			
		||||
                            animalHandling = item.parse(ANIMAL_HANDLING),
 | 
			
		||||
                            arcana = item.parse(ARCANA),
 | 
			
		||||
                            athletics = item.parse(ATHLETICS),
 | 
			
		||||
                            deception = item.parse(DECEPTION),
 | 
			
		||||
                            history = item.parse(HISTORY),
 | 
			
		||||
                            insight = item.parse(INSIGHT),
 | 
			
		||||
                            intimidation = item.parse(INTIMIDATION),
 | 
			
		||||
                            investigation = item.parse(INVESTIGATION),
 | 
			
		||||
                            medicine = item.parse(MEDICINE),
 | 
			
		||||
                            nature = item.parse(NATURE),
 | 
			
		||||
                            perception = item.parse(PERCEPTION),
 | 
			
		||||
                            performance = item.parse(PERFORMANCE),
 | 
			
		||||
                            persuasion = item.parse(PERSUASION),
 | 
			
		||||
                            religion = item.parse(RELIGION),
 | 
			
		||||
                            sleightOfHand = item.parse(SLEIGHT_OF_HAND),
 | 
			
		||||
                            stealth = item.parse(STEALTH),
 | 
			
		||||
                            survival = item.parse(SURVIVAL),
 | 
			
		||||
                            hitPoint = item.parseString(HIT_POINT) ?: "1",
 | 
			
		||||
                            maxHitPoint = item.parseString(MAX_HIT_POINT) ?: "1",
 | 
			
		||||
                            armorClass = item.parseString(ARMOR_CLASS) ?: "0",
 | 
			
		||||
                            speed = item.parseInt(SPEED),
 | 
			
		||||
                            proficiency = item.parseInt(MASTERY),
 | 
			
		||||
                            strength = item.parseInt(STRENGTH),
 | 
			
		||||
                            dexterity = item.parseInt(DEXTERITY),
 | 
			
		||||
                            constitution = item.parseInt(CONSTITUTION),
 | 
			
		||||
                            intelligence = item.parseInt(INTELLIGENCE),
 | 
			
		||||
                            wisdom = item.parseInt(WISDOM),
 | 
			
		||||
                            charisma = item.parseInt(CHARISMA),
 | 
			
		||||
                            strengthSavingThrows = item.parseInt(STRENGTH_SAVING_THROW),
 | 
			
		||||
                            dexteritySavingThrows = item.parseInt(DEXTERITY_SAVING_THROW),
 | 
			
		||||
                            constitutionSavingThrows = item.parseInt(CONSTITUTION_SAVING_THROW),
 | 
			
		||||
                            intelligenceSavingThrows = item.parseInt(INTELLIGENCE_SAVING_THROW),
 | 
			
		||||
                            wisdomSavingThrows = item.parseInt(WISDOM_SAVING_THROW),
 | 
			
		||||
                            charismaSavingThrows = item.parseInt(CHARISMA_SAVING_THROW),
 | 
			
		||||
                            acrobatics = item.parseInt(ACROBATICS),
 | 
			
		||||
                            animalHandling = item.parseInt(ANIMAL_HANDLING),
 | 
			
		||||
                            arcana = item.parseInt(ARCANA),
 | 
			
		||||
                            athletics = item.parseInt(ATHLETICS),
 | 
			
		||||
                            deception = item.parseInt(DECEPTION),
 | 
			
		||||
                            history = item.parseInt(HISTORY),
 | 
			
		||||
                            insight = item.parseInt(INSIGHT),
 | 
			
		||||
                            intimidation = item.parseInt(INTIMIDATION),
 | 
			
		||||
                            investigation = item.parseInt(INVESTIGATION),
 | 
			
		||||
                            medicine = item.parseInt(MEDICINE),
 | 
			
		||||
                            nature = item.parseInt(NATURE),
 | 
			
		||||
                            perception = item.parseInt(PERCEPTION),
 | 
			
		||||
                            performance = item.parseInt(PERFORMANCE),
 | 
			
		||||
                            persuasion = item.parseInt(PERSUASION),
 | 
			
		||||
                            religion = item.parseInt(RELIGION),
 | 
			
		||||
                            sleightOfHand = item.parseInt(SLEIGHT_OF_HAND),
 | 
			
		||||
                            stealth = item.parseInt(STEALTH),
 | 
			
		||||
                            survival = item.parseInt(SURVIVAL),
 | 
			
		||||
                        )
 | 
			
		||||
                    } else {
 | 
			
		||||
                        null
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +90,7 @@ class CharacterSheetParser @Inject constructor() {
 | 
			
		|||
        private const val HIT_POINT = "Point de vie"
 | 
			
		||||
        private const val MAX_HIT_POINT = "Point de vie MAX"
 | 
			
		||||
        private const val ARMOR_CLASS = "Classe d'armure"
 | 
			
		||||
        private const val SPEED = "Vitesse"
 | 
			
		||||
        private const val MASTERY = "Bonus de maîtrise"
 | 
			
		||||
        private const val STRENGTH = "Force"
 | 
			
		||||
        private const val DEXTERITY = "Dextérité"
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +129,7 @@ class CharacterSheetParser @Inject constructor() {
 | 
			
		|||
                HIT_POINT,
 | 
			
		||||
                MAX_HIT_POINT,
 | 
			
		||||
                ARMOR_CLASS,
 | 
			
		||||
                SPEED,
 | 
			
		||||
                MASTERY,
 | 
			
		||||
                STRENGTH,
 | 
			
		||||
                DEXTERITY,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,9 +2,10 @@ package com.pixelized.rplexicon.model
 | 
			
		|||
 | 
			
		||||
data class CharacterSheet(
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val hitPoint: Int, // Point de vie
 | 
			
		||||
    val maxHitPoint: Int,
 | 
			
		||||
    val armorClass: Int, // Classe d'armure
 | 
			
		||||
    val hitPoint: String, // Point de vie
 | 
			
		||||
    val maxHitPoint: String,
 | 
			
		||||
    val armorClass: String, // Classe d'armure
 | 
			
		||||
    val speed: Int,
 | 
			
		||||
    val proficiency: Int, // Bonus de maîtrise
 | 
			
		||||
    val strength: Int, // Force
 | 
			
		||||
    val dexterity: Int, // Dextérité
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ fun BlurredOverlayHost(
 | 
			
		|||
                Box(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .clickableInterceptor()
 | 
			
		||||
                        .background(brush = MaterialTheme.lexicon.colorScheme.rollOverlayBrush)
 | 
			
		||||
                        .background(color = MaterialTheme.lexicon.colorScheme.rollOverlayBrush)
 | 
			
		||||
                        .fillMaxSize()
 | 
			
		||||
                        .systemBarsPadding(),
 | 
			
		||||
                ) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@ package com.pixelized.rplexicon.ui.screens.character
 | 
			
		|||
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import androidx.activity.compose.BackHandler
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.Image
 | 
			
		||||
import androidx.compose.foundation.ScrollState
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
| 
						 | 
				
			
			@ -61,11 +60,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.Counter
 | 
			
		|||
import com.pixelized.rplexicon.ui.screens.character.composable.CounterUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.LabelPoint
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.LabelPointUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.Proficiency
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.ProficiencyUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.SavingsThrows
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.SavingsThrowsUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.Stat
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.StatUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
			
		||||
| 
						 | 
				
			
			@ -74,38 +69,12 @@ import kotlinx.coroutines.launch
 | 
			
		|||
@Stable
 | 
			
		||||
data class CharacterSheetUio(
 | 
			
		||||
    val armorClass: LabelPointUio,
 | 
			
		||||
    val speed: LabelPointUio,
 | 
			
		||||
    val hitPoint: LabelPointUio,
 | 
			
		||||
    val initiative: LabelPointUio,
 | 
			
		||||
    val strength: StatUio,
 | 
			
		||||
    val dexterity: StatUio,
 | 
			
		||||
    val constitution: StatUio,
 | 
			
		||||
    val intelligence: StatUio,
 | 
			
		||||
    val wisdom: StatUio,
 | 
			
		||||
    val charisma: StatUio,
 | 
			
		||||
    val strengthSavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val dexteritySavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val constitutionSavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val intelligenceSavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val wisdomSavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val charismaSavingThrows: SavingsThrowsUio,
 | 
			
		||||
    val acrobatics: ProficiencyUio,
 | 
			
		||||
    val animalHandling: ProficiencyUio,
 | 
			
		||||
    val arcana: ProficiencyUio,
 | 
			
		||||
    val athletics: ProficiencyUio,
 | 
			
		||||
    val deception: ProficiencyUio,
 | 
			
		||||
    val history: ProficiencyUio,
 | 
			
		||||
    val insight: ProficiencyUio,
 | 
			
		||||
    val intimidation: ProficiencyUio,
 | 
			
		||||
    val investigation: ProficiencyUio,
 | 
			
		||||
    val medicine: ProficiencyUio,
 | 
			
		||||
    val nature: ProficiencyUio,
 | 
			
		||||
    val perception: ProficiencyUio,
 | 
			
		||||
    val performance: ProficiencyUio,
 | 
			
		||||
    val persuasion: ProficiencyUio,
 | 
			
		||||
    val religion: ProficiencyUio,
 | 
			
		||||
    val sleightOfHand: ProficiencyUio,
 | 
			
		||||
    val stealth: ProficiencyUio,
 | 
			
		||||
    val survival: ProficiencyUio,
 | 
			
		||||
    val stats: List<StatUio>,
 | 
			
		||||
    val savingThrows: List<ProficiencyUio>,
 | 
			
		||||
    val proficiencies: List<ProficiencyUio>,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalMaterialApi::class)
 | 
			
		||||
| 
						 | 
				
			
			@ -146,153 +115,45 @@ fun CharacterSheetScreen(
 | 
			
		|||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onStrength = {
 | 
			
		||||
                    val roll = viewModel.strengthRoll()
 | 
			
		||||
                onStats = { stat ->
 | 
			
		||||
                    val roll = when (stat.id) {
 | 
			
		||||
                        StatUio.ID.STRENGTH -> viewModel.strengthRoll()
 | 
			
		||||
                        StatUio.ID.DEXTERITY -> viewModel.dexterityRoll()
 | 
			
		||||
                        StatUio.ID.CONSTITUTION -> viewModel.constitutionRoll()
 | 
			
		||||
                        StatUio.ID.INTELLIGENCE -> viewModel.intelligenceRoll()
 | 
			
		||||
                        StatUio.ID.WISDOM -> viewModel.wisdomRoll()
 | 
			
		||||
                        StatUio.ID.CHARISMA -> viewModel.charismaRoll()
 | 
			
		||||
                    }
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onDexterity = {
 | 
			
		||||
                    val roll = viewModel.dexterityRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onConstitution = {
 | 
			
		||||
                    val roll = viewModel.constitutionRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onIntelligence = {
 | 
			
		||||
                    val roll = viewModel.intelligenceRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onWisdom = {
 | 
			
		||||
                    val roll = viewModel.wisdomRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onCharisma = {
 | 
			
		||||
                    val roll = viewModel.charismaRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onStrengthSavingThrows = {
 | 
			
		||||
                    val roll = viewModel.strengthSavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onDexteritySavingThrows = {
 | 
			
		||||
                    val roll = viewModel.dexteritySavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onConstitutionSavingThrows = {
 | 
			
		||||
                    val roll = viewModel.constitutionSavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onIntelligenceSavingThrows = {
 | 
			
		||||
                    val roll = viewModel.intelligenceSavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onWisdomSavingThrows = {
 | 
			
		||||
                    val roll = viewModel.wisdomSavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onCharismaSavingThrows = {
 | 
			
		||||
                    val roll = viewModel.charismaSavingThrowsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onAcrobatics = {
 | 
			
		||||
                    val roll = viewModel.acrobaticsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onAnimalHandling = {
 | 
			
		||||
                    val roll = viewModel.animalHandlingRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onArcana = {
 | 
			
		||||
                    val roll = viewModel.arcanaRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onAthletics = {
 | 
			
		||||
                    val roll = viewModel.athleticsRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onDeception = {
 | 
			
		||||
                    val roll = viewModel.deceptionRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onHistory = {
 | 
			
		||||
                    val roll = viewModel.historyRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onInsight = {
 | 
			
		||||
                    val roll = viewModel.insightRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onIntimidation = {
 | 
			
		||||
                    val roll = viewModel.intimidationRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onInvestigation = {
 | 
			
		||||
                    val roll = viewModel.investigationRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onMedicine = {
 | 
			
		||||
                    val roll = viewModel.medicineRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onNature = {
 | 
			
		||||
                    val roll = viewModel.natureRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onPerception = {
 | 
			
		||||
                    val roll = viewModel.perceptionRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onPerformance = {
 | 
			
		||||
                    val roll = viewModel.performanceRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onPersuasion = {
 | 
			
		||||
                    val roll = viewModel.persuasionRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onReligion = {
 | 
			
		||||
                    val roll = viewModel.religionRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onSleightOfHand = {
 | 
			
		||||
                    val roll = viewModel.sleightOfHandRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onStealth = {
 | 
			
		||||
                    val roll = viewModel.stealthRoll()
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
                onSurvival = {
 | 
			
		||||
                    val roll = viewModel.survivalRoll()
 | 
			
		||||
                onProficiencies = { proficiency ->
 | 
			
		||||
                    val roll = when (proficiency.id) {
 | 
			
		||||
                        ProficiencyUio.ID.STRENGTH_SAVING_THROW -> viewModel.strengthRoll()
 | 
			
		||||
                        ProficiencyUio.ID.DEXTERITY_SAVING_THROW -> viewModel.dexterityRoll()
 | 
			
		||||
                        ProficiencyUio.ID.CONSTITUTION_SAVING_THROW -> viewModel.constitutionRoll()
 | 
			
		||||
                        ProficiencyUio.ID.INTELLIGENCE_SAVING_THROW -> viewModel.intelligenceRoll()
 | 
			
		||||
                        ProficiencyUio.ID.WISDOM_SAVING_THROW -> viewModel.wisdomRoll()
 | 
			
		||||
                        ProficiencyUio.ID.CHARISMA_SAVING_THROW -> viewModel.charismaRoll()
 | 
			
		||||
                        ProficiencyUio.ID.ACROBATICS -> viewModel.acrobaticsRoll()
 | 
			
		||||
                        ProficiencyUio.ID.ANIMAL_HANDLING -> viewModel.animalHandlingRoll()
 | 
			
		||||
                        ProficiencyUio.ID.ARCANA -> viewModel.arcanaRoll()
 | 
			
		||||
                        ProficiencyUio.ID.ATHLETICS -> viewModel.athleticsRoll()
 | 
			
		||||
                        ProficiencyUio.ID.DECEPTION -> viewModel.deceptionRoll()
 | 
			
		||||
                        ProficiencyUio.ID.HISTORY -> viewModel.historyRoll()
 | 
			
		||||
                        ProficiencyUio.ID.INSIGHT -> viewModel.insightRoll()
 | 
			
		||||
                        ProficiencyUio.ID.INTIMIDATION -> viewModel.intimidationRoll()
 | 
			
		||||
                        ProficiencyUio.ID.INVESTIGATION -> viewModel.investigationRoll()
 | 
			
		||||
                        ProficiencyUio.ID.MEDICINE -> viewModel.medicineRoll()
 | 
			
		||||
                        ProficiencyUio.ID.NATURE -> viewModel.natureRoll()
 | 
			
		||||
                        ProficiencyUio.ID.PERCEPTION -> viewModel.perceptionRoll()
 | 
			
		||||
                        ProficiencyUio.ID.PERFORMANCE -> viewModel.performanceRoll()
 | 
			
		||||
                        ProficiencyUio.ID.PERSUASION -> viewModel.persuasionRoll()
 | 
			
		||||
                        ProficiencyUio.ID.RELIGION -> viewModel.religionRoll()
 | 
			
		||||
                        ProficiencyUio.ID.SLEIGHT_OF_HAND -> viewModel.sleightOfHandRoll()
 | 
			
		||||
                        ProficiencyUio.ID.STEALTH -> viewModel.stealthRoll()
 | 
			
		||||
                        ProficiencyUio.ID.SURVIVAL -> viewModel.survivalRoll()
 | 
			
		||||
                    }
 | 
			
		||||
                    overlay.prepareRoll(roll = roll)
 | 
			
		||||
                    overlay.showOverlay()
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -328,37 +189,9 @@ private fun CharacterSheetContent(
 | 
			
		|||
    counter: State<List<CounterUio>>,
 | 
			
		||||
    alterations: State<List<String>>,
 | 
			
		||||
    onBack: () -> Unit,
 | 
			
		||||
    onStats: (StatUio) -> Unit,
 | 
			
		||||
    onProficiencies: (ProficiencyUio) -> Unit,
 | 
			
		||||
    onInitiative: () -> Unit,
 | 
			
		||||
    onStrength: () -> Unit,
 | 
			
		||||
    onDexterity: () -> Unit,
 | 
			
		||||
    onConstitution: () -> Unit,
 | 
			
		||||
    onIntelligence: () -> Unit,
 | 
			
		||||
    onWisdom: () -> Unit,
 | 
			
		||||
    onCharisma: () -> Unit,
 | 
			
		||||
    onStrengthSavingThrows: () -> Unit,
 | 
			
		||||
    onDexteritySavingThrows: () -> Unit,
 | 
			
		||||
    onConstitutionSavingThrows: () -> Unit,
 | 
			
		||||
    onIntelligenceSavingThrows: () -> Unit,
 | 
			
		||||
    onWisdomSavingThrows: () -> Unit,
 | 
			
		||||
    onCharismaSavingThrows: () -> Unit,
 | 
			
		||||
    onAcrobatics: () -> Unit,
 | 
			
		||||
    onAnimalHandling: () -> Unit,
 | 
			
		||||
    onArcana: () -> Unit,
 | 
			
		||||
    onAthletics: () -> Unit,
 | 
			
		||||
    onDeception: () -> Unit,
 | 
			
		||||
    onHistory: () -> Unit,
 | 
			
		||||
    onInsight: () -> Unit,
 | 
			
		||||
    onIntimidation: () -> Unit,
 | 
			
		||||
    onInvestigation: () -> Unit,
 | 
			
		||||
    onMedicine: () -> Unit,
 | 
			
		||||
    onNature: () -> Unit,
 | 
			
		||||
    onPerception: () -> Unit,
 | 
			
		||||
    onPerformance: () -> Unit,
 | 
			
		||||
    onPersuasion: () -> Unit,
 | 
			
		||||
    onReligion: () -> Unit,
 | 
			
		||||
    onSleightOfHand: () -> Unit,
 | 
			
		||||
    onStealth: () -> Unit,
 | 
			
		||||
    onSurvival: () -> Unit,
 | 
			
		||||
    onHit: (id: String) -> Unit,
 | 
			
		||||
    onDamage: (id: String) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
| 
						 | 
				
			
			@ -407,200 +240,24 @@ private fun CharacterSheetContent(
 | 
			
		|||
                        .padding(horizontal = 16.dp),
 | 
			
		||||
                    verticalAlignment = Alignment.Bottom,
 | 
			
		||||
                    horizontalArrangement = Arrangement.spacedBy(
 | 
			
		||||
                        16.dp,
 | 
			
		||||
                        Alignment.CenterHorizontally
 | 
			
		||||
                        space = 16.dp,
 | 
			
		||||
                        alignment = Alignment.CenterHorizontally
 | 
			
		||||
                    ),
 | 
			
		||||
                ) {
 | 
			
		||||
                    LabelPoint(
 | 
			
		||||
                        style = MaterialTheme.typography.displaySmall,
 | 
			
		||||
                        hp = sheet.armorClass,
 | 
			
		||||
                    )
 | 
			
		||||
                    LabelPoint(
 | 
			
		||||
                        hp = sheet.hitPoint,
 | 
			
		||||
                    )
 | 
			
		||||
                    LabelPoint(
 | 
			
		||||
                        style = MaterialTheme.typography.displaySmall,
 | 
			
		||||
                        hp = sheet.initiative,
 | 
			
		||||
                        onClick = onInitiative,
 | 
			
		||||
                    )
 | 
			
		||||
                    LabelPoint(label = sheet.armorClass)
 | 
			
		||||
                    LabelPoint(label = sheet.hitPoint)
 | 
			
		||||
                    LabelPoint(label = sheet.speed)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Column(
 | 
			
		||||
                    verticalArrangement = Arrangement.spacedBy(16.dp),
 | 
			
		||||
                ) {
 | 
			
		||||
                    Row(
 | 
			
		||||
                        modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                        horizontalArrangement = Arrangement.spacedBy(16.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.strength,
 | 
			
		||||
                            onClick = onStrength,
 | 
			
		||||
                        )
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.dexterity,
 | 
			
		||||
                            onClick = onDexterity,
 | 
			
		||||
                        )
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.constitution,
 | 
			
		||||
                            onClick = onConstitution,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                    Row(
 | 
			
		||||
                        modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                        horizontalArrangement = Arrangement.spacedBy(16.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.intelligence,
 | 
			
		||||
                            onClick = onIntelligence,
 | 
			
		||||
                        )
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.wisdom,
 | 
			
		||||
                            onClick = onWisdom,
 | 
			
		||||
                        )
 | 
			
		||||
                        Stat(
 | 
			
		||||
                            modifier = Modifier.weight(1f),
 | 
			
		||||
                            stat = sheet.charisma,
 | 
			
		||||
                            onClick = onCharisma,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SectionTitle(
 | 
			
		||||
                    modifier = Modifier.padding(top = 16.dp),
 | 
			
		||||
                    title = R.string.character_sheet_title_saving_throws,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                Row(
 | 
			
		||||
                    modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                    horizontalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
                ) {
 | 
			
		||||
                    Column(
 | 
			
		||||
                        modifier = Modifier.weight(1f),
 | 
			
		||||
                        verticalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.strengthSavingThrows,
 | 
			
		||||
                            onClick = onStrengthSavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.dexteritySavingThrows,
 | 
			
		||||
                            onClick = onDexteritySavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.constitutionSavingThrows,
 | 
			
		||||
                            onClick = onConstitutionSavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                    Column(
 | 
			
		||||
                        modifier = Modifier.weight(1f),
 | 
			
		||||
                        verticalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
                    ) {
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.intelligenceSavingThrows,
 | 
			
		||||
                            onClick = onIntelligenceSavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.wisdomSavingThrows,
 | 
			
		||||
                            onClick = onWisdomSavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                        SavingsThrows(
 | 
			
		||||
                            savingsThrows = sheet.charismaSavingThrows,
 | 
			
		||||
                            onClick = onCharismaSavingThrows,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SectionTitle(
 | 
			
		||||
                    modifier = Modifier.padding(top = 16.dp),
 | 
			
		||||
                    title = R.string.character_sheet_title_proficiencies,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                Column(
 | 
			
		||||
                ProficiencyPage(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .padding(horizontal = 16.dp)
 | 
			
		||||
                        .ddBorder(
 | 
			
		||||
                            inner = remember { RoundedCornerShape(size = 8.dp) },
 | 
			
		||||
                            outline = remember { CutCornerShape(size = 16.dp) },
 | 
			
		||||
                        ),
 | 
			
		||||
                ) {
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.acrobatics,
 | 
			
		||||
                        onClick = onAcrobatics,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.animalHandling,
 | 
			
		||||
                        onClick = onAnimalHandling,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.arcana,
 | 
			
		||||
                        onClick = onArcana,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.athletics,
 | 
			
		||||
                        onClick = onAthletics,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.deception,
 | 
			
		||||
                        onClick = onDeception,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.history,
 | 
			
		||||
                        onClick = onHistory,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.insight,
 | 
			
		||||
                        onClick = onInsight,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.intimidation,
 | 
			
		||||
                        onClick = onIntimidation,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.investigation,
 | 
			
		||||
                        onClick = onInvestigation,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.medicine,
 | 
			
		||||
                        onClick = onMedicine,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.nature,
 | 
			
		||||
                        onClick = onNature,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.perception,
 | 
			
		||||
                        onClick = onPerception,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.performance,
 | 
			
		||||
                        onClick = onPerformance,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.persuasion,
 | 
			
		||||
                        onClick = onPersuasion,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.religion,
 | 
			
		||||
                        onClick = onReligion,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.sleightOfHand,
 | 
			
		||||
                        onClick = onSleightOfHand,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.stealth,
 | 
			
		||||
                        onClick = onStealth,
 | 
			
		||||
                    )
 | 
			
		||||
                    Proficiency(
 | 
			
		||||
                        proficiency = sheet.survival,
 | 
			
		||||
                        onClick = onSurvival,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                        .fillMaxWidth()
 | 
			
		||||
                        .padding(horizontal = 16.dp),
 | 
			
		||||
                    sheet = sheet,
 | 
			
		||||
                    onInitiative = onInitiative,
 | 
			
		||||
                    onStats = onStats,
 | 
			
		||||
                    onProficiencies = onProficiencies,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                if (actions.value.isNotEmpty() || counter.value.isNotEmpty()) {
 | 
			
		||||
                    Row(
 | 
			
		||||
| 
						 | 
				
			
			@ -657,11 +314,6 @@ private fun CharacterSheetContent(
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
                if (alterations.value.isNotEmpty()) {
 | 
			
		||||
                    SectionTitle(
 | 
			
		||||
                        modifier = Modifier.padding(top = 16.dp),
 | 
			
		||||
                        title = R.string.character_sheet_title_alteration,
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                    Column(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .padding(horizontal = 16.dp)
 | 
			
		||||
| 
						 | 
				
			
			@ -697,45 +349,6 @@ private fun CharacterSheetContent(
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun SectionTitle(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    @StringRes title: Int
 | 
			
		||||
) {
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = modifier.fillMaxWidth(),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
        horizontalArrangement = Arrangement.Center,
 | 
			
		||||
    ) {
 | 
			
		||||
        Image(
 | 
			
		||||
            modifier = Modifier.graphicsLayer { rotationY = 180f },
 | 
			
		||||
            painter = painterResource(id = R.drawable.art_clip_1),
 | 
			
		||||
            contentScale = ContentScale.FillWidth,
 | 
			
		||||
            alignment = Alignment.Center,
 | 
			
		||||
            colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface),
 | 
			
		||||
            contentDescription = null,
 | 
			
		||||
        )
 | 
			
		||||
        Text(
 | 
			
		||||
            modifier = Modifier
 | 
			
		||||
                .weight(weight = 1f, fill = false)
 | 
			
		||||
                .padding(horizontal = 8.dp),
 | 
			
		||||
            style = MaterialTheme.typography.titleLarge,
 | 
			
		||||
            textAlign = TextAlign.Center,
 | 
			
		||||
            overflow = TextOverflow.Ellipsis,
 | 
			
		||||
            maxLines = 1,
 | 
			
		||||
            text = stringResource(title),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        Image(
 | 
			
		||||
            painter = painterResource(id = R.drawable.art_clip_1),
 | 
			
		||||
            contentScale = ContentScale.FillWidth,
 | 
			
		||||
            alignment = Alignment.Center,
 | 
			
		||||
            colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface),
 | 
			
		||||
            contentDescription = null,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalMaterialApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, heightDp = 2000)
 | 
			
		||||
| 
						 | 
				
			
			@ -747,185 +360,176 @@ private fun CharacterScreenPreview() {
 | 
			
		|||
                armorClass = LabelPointUio(
 | 
			
		||||
                    label = R.string.character_sheet_title_ca,
 | 
			
		||||
                    value = "15",
 | 
			
		||||
                    max = null,
 | 
			
		||||
                ),
 | 
			
		||||
                hitPoint = LabelPointUio(
 | 
			
		||||
                    label = R.string.character_sheet_title_hp,
 | 
			
		||||
                    value = "13",
 | 
			
		||||
                    max = "15",
 | 
			
		||||
                    value = "125",
 | 
			
		||||
                    max = "/ 150",
 | 
			
		||||
                ),
 | 
			
		||||
                speed = LabelPointUio(
 | 
			
		||||
                    label = R.string.character_sheet_title_speed,
 | 
			
		||||
                    value = "30",
 | 
			
		||||
                    max = "m",
 | 
			
		||||
                ),
 | 
			
		||||
                initiative = LabelPointUio(
 | 
			
		||||
                    label = R.string.character_sheet_title_initiative,
 | 
			
		||||
                    value = "+2",
 | 
			
		||||
                    max = null,
 | 
			
		||||
                ),
 | 
			
		||||
                strength = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_strength,
 | 
			
		||||
                    value = 16,
 | 
			
		||||
                    modifier = 3,
 | 
			
		||||
                stats = listOf(
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.STRENGTH,
 | 
			
		||||
                        value = 16,
 | 
			
		||||
                        modifier = 3,
 | 
			
		||||
                    ),
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.DEXTERITY,
 | 
			
		||||
                        value = 10,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.CONSTITUTION,
 | 
			
		||||
                        value = 16,
 | 
			
		||||
                        modifier = 3,
 | 
			
		||||
                    ),
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.INTELLIGENCE,
 | 
			
		||||
                        value = 8,
 | 
			
		||||
                        modifier = 1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.WISDOM,
 | 
			
		||||
                        value = 14,
 | 
			
		||||
                        modifier = 2,
 | 
			
		||||
                    ),
 | 
			
		||||
                    StatUio(
 | 
			
		||||
                        id = StatUio.ID.CHARISMA,
 | 
			
		||||
                        value = 10,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                dexterity = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
                    value = 10,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                savingThrows = listOf(
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.STRENGTH_SAVING_THROW,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 5,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.DEXTERITY_SAVING_THROW,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.CONSTITUTION_SAVING_THROW,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = +5,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.INTELLIGENCE_SAVING_THROW,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.WISDOM_SAVING_THROW,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = +2,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.CHARISMA_SAVING_THROW,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = +0,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                constitution = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
                    value = 16,
 | 
			
		||||
                    modifier = 3,
 | 
			
		||||
                ),
 | 
			
		||||
                intelligence = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
                    value = 8,
 | 
			
		||||
                    modifier = 1,
 | 
			
		||||
                ),
 | 
			
		||||
                wisdom = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_wisdom,
 | 
			
		||||
                    value = 14,
 | 
			
		||||
                    modifier = 2,
 | 
			
		||||
                ),
 | 
			
		||||
                charisma = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
                    value = 10,
 | 
			
		||||
                    modifier = 0
 | 
			
		||||
                ),
 | 
			
		||||
                strengthSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_strength,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 5,
 | 
			
		||||
                ),
 | 
			
		||||
                dexteritySavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                constitutionSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = +5,
 | 
			
		||||
                ),
 | 
			
		||||
                intelligenceSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                wisdomSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_wisdom,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = +2,
 | 
			
		||||
                ),
 | 
			
		||||
                charismaSavingThrows = SavingsThrowsUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = +0,
 | 
			
		||||
                ),
 | 
			
		||||
                acrobatics = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_acrobatics,
 | 
			
		||||
                    related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = +0,
 | 
			
		||||
                ),
 | 
			
		||||
                animalHandling = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_animal_handling,
 | 
			
		||||
                    related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 2,
 | 
			
		||||
                ),
 | 
			
		||||
                arcana = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_arcana,
 | 
			
		||||
                    related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                athletics = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_athletics,
 | 
			
		||||
                    related = R.string.character_sheet_stat_strength_short,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 5,
 | 
			
		||||
                ),
 | 
			
		||||
                deception = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_deception,
 | 
			
		||||
                    related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                history = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_history,
 | 
			
		||||
                    related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                insight = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_insight,
 | 
			
		||||
                    related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 4,
 | 
			
		||||
                ),
 | 
			
		||||
                intimidation = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_intimidation,
 | 
			
		||||
                    related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 2,
 | 
			
		||||
                ),
 | 
			
		||||
                investigation = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_investigation,
 | 
			
		||||
                    related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                medicine = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_medicine,
 | 
			
		||||
                    related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 2,
 | 
			
		||||
                ),
 | 
			
		||||
                nature = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_nature,
 | 
			
		||||
                    related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                perception = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_perception,
 | 
			
		||||
                    related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 4,
 | 
			
		||||
                ),
 | 
			
		||||
                performance = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_performance,
 | 
			
		||||
                    related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                persuasion = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_persuasion,
 | 
			
		||||
                    related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                religion = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_religion,
 | 
			
		||||
                    related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = -1,
 | 
			
		||||
                ),
 | 
			
		||||
                sleightOfHand = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_sleight_of_hand,
 | 
			
		||||
                    related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                stealth = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_stealth,
 | 
			
		||||
                    related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
                    multiplier = 0,
 | 
			
		||||
                    modifier = 0,
 | 
			
		||||
                ),
 | 
			
		||||
                survival = ProficiencyUio(
 | 
			
		||||
                    label = R.string.character_sheet_proficiency_survival,
 | 
			
		||||
                    related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
                    multiplier = 1,
 | 
			
		||||
                    modifier = 4,
 | 
			
		||||
                proficiencies = listOf(
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.ACROBATICS,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = +0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.ANIMAL_HANDLING,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 2,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.ARCANA,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.ATHLETICS,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 5,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.DECEPTION,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.HISTORY,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.INSIGHT,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 4,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.INTIMIDATION,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 2,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.INVESTIGATION,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.MEDICINE,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 2,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.NATURE,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.PERCEPTION,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 4,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.PERFORMANCE,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.PERSUASION,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.RELIGION,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = -1,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.SLEIGHT_OF_HAND,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.STEALTH,
 | 
			
		||||
                        multiplier = 0,
 | 
			
		||||
                        modifier = 0,
 | 
			
		||||
                    ),
 | 
			
		||||
                    ProficiencyUio(
 | 
			
		||||
                        id = ProficiencyUio.ID.SURVIVAL,
 | 
			
		||||
                        multiplier = 1,
 | 
			
		||||
                        modifier = 4,
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -970,36 +574,8 @@ private fun CharacterScreenPreview() {
 | 
			
		|||
                },
 | 
			
		||||
                onBack = { },
 | 
			
		||||
                onInitiative = { },
 | 
			
		||||
                onStrength = { },
 | 
			
		||||
                onDexterity = { },
 | 
			
		||||
                onConstitution = { },
 | 
			
		||||
                onIntelligence = { },
 | 
			
		||||
                onWisdom = { },
 | 
			
		||||
                onCharisma = { },
 | 
			
		||||
                onStrengthSavingThrows = { },
 | 
			
		||||
                onDexteritySavingThrows = { },
 | 
			
		||||
                onConstitutionSavingThrows = { },
 | 
			
		||||
                onIntelligenceSavingThrows = { },
 | 
			
		||||
                onWisdomSavingThrows = { },
 | 
			
		||||
                onCharismaSavingThrows = { },
 | 
			
		||||
                onAcrobatics = { },
 | 
			
		||||
                onAnimalHandling = { },
 | 
			
		||||
                onArcana = { },
 | 
			
		||||
                onAthletics = { },
 | 
			
		||||
                onDeception = { },
 | 
			
		||||
                onHistory = { },
 | 
			
		||||
                onInsight = { },
 | 
			
		||||
                onIntimidation = { },
 | 
			
		||||
                onInvestigation = { },
 | 
			
		||||
                onMedicine = { },
 | 
			
		||||
                onNature = { },
 | 
			
		||||
                onPerception = { },
 | 
			
		||||
                onPerformance = { },
 | 
			
		||||
                onPersuasion = { },
 | 
			
		||||
                onReligion = { },
 | 
			
		||||
                onSleightOfHand = { },
 | 
			
		||||
                onStealth = { },
 | 
			
		||||
                onSurvival = { },
 | 
			
		||||
                onStats = { },
 | 
			
		||||
                onProficiencies = { },
 | 
			
		||||
                onHit = { },
 | 
			
		||||
                onDamage = { },
 | 
			
		||||
            )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,185 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.ColumnScope
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.sizeIn
 | 
			
		||||
import androidx.compose.foundation.shape.CutCornerShape
 | 
			
		||||
import androidx.compose.foundation.shape.RoundedCornerShape
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.graphics.Shape
 | 
			
		||||
import androidx.compose.ui.layout.Layout
 | 
			
		||||
import androidx.compose.ui.layout.Measurable
 | 
			
		||||
import androidx.compose.ui.layout.layoutId
 | 
			
		||||
import androidx.compose.ui.platform.LocalDensity
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.unit.Dp
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.Proficiency
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.ProficiencyUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.Stat
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.StatUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun ProficiencyPage(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    inner: Shape = remember { RoundedCornerShape(size = 8.dp) },
 | 
			
		||||
    outline: Shape = remember { CutCornerShape(size = 16.dp) },
 | 
			
		||||
    sheet: CharacterSheetUio,
 | 
			
		||||
    onInitiative: () -> Unit,
 | 
			
		||||
    onStats: (StatUio) -> Unit,
 | 
			
		||||
    onProficiencies: (ProficiencyUio) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    ProficiencyLayout(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        inner = inner,
 | 
			
		||||
        outline = outline,
 | 
			
		||||
        stats = {
 | 
			
		||||
            Column(
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .sizeIn(minWidth = 100.dp, minHeight = 116.dp)
 | 
			
		||||
                    .ddBorder(outline = outline, inner = inner)
 | 
			
		||||
                    .clickable(onClick = onInitiative)
 | 
			
		||||
                    .padding(all = 8.dp),
 | 
			
		||||
                horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                verticalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
            ) {
 | 
			
		||||
                Text(
 | 
			
		||||
                    style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
                    text = sheet.initiative.label?.let { stringResource(id = it) } ?: ""
 | 
			
		||||
                )
 | 
			
		||||
                Text(
 | 
			
		||||
                    style = MaterialTheme.typography.displayMedium,
 | 
			
		||||
                    text = sheet.initiative.value ?: ""
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            sheet.stats.forEach {
 | 
			
		||||
                Stat(
 | 
			
		||||
                    modifier = Modifier.ddBorder(inner = inner, outline = outline),
 | 
			
		||||
                    stat = it,
 | 
			
		||||
                    onClick = onStats,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        savingThrows = {
 | 
			
		||||
            sheet.savingThrows.forEach {
 | 
			
		||||
                Proficiency(
 | 
			
		||||
                    proficiency = it,
 | 
			
		||||
                    onClick = onProficiencies,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier.padding(vertical = 4.dp),
 | 
			
		||||
                style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
                text = stringResource(id = R.string.character_sheet_title_saving_throws)
 | 
			
		||||
            )
 | 
			
		||||
        },
 | 
			
		||||
        proficiencies = {
 | 
			
		||||
            sheet.proficiencies.forEach {
 | 
			
		||||
                Proficiency(
 | 
			
		||||
                    proficiency = it,
 | 
			
		||||
                    onClick = onProficiencies,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier.padding(vertical = 4.dp),
 | 
			
		||||
                style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
                text = stringResource(id = R.string.character_sheet_title_proficiencies)
 | 
			
		||||
            )
 | 
			
		||||
        },
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun ProficiencyLayout(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    spacing: Dp = 16.dp,
 | 
			
		||||
    inner: Shape,
 | 
			
		||||
    outline: Shape,
 | 
			
		||||
    stats: @Composable ColumnScope.() -> Unit,
 | 
			
		||||
    savingThrows: @Composable ColumnScope.() -> Unit,
 | 
			
		||||
    proficiencies: @Composable ColumnScope.() -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    val density = LocalDensity.current
 | 
			
		||||
    Layout(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        content = {
 | 
			
		||||
            Column(
 | 
			
		||||
                modifier = Modifier.layoutId("StatsId"),
 | 
			
		||||
                content = stats,
 | 
			
		||||
                horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                verticalArrangement = Arrangement.SpaceBetween,
 | 
			
		||||
            )
 | 
			
		||||
            Column(
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .layoutId("SavingThrowsId")
 | 
			
		||||
                    .ddBorder(inner = inner, outline = outline),
 | 
			
		||||
                horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                content = savingThrows,
 | 
			
		||||
            )
 | 
			
		||||
            Column(
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .layoutId("ProficienciesId")
 | 
			
		||||
                    .ddBorder(inner = inner, outline = outline),
 | 
			
		||||
                horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                content = proficiencies,
 | 
			
		||||
            )
 | 
			
		||||
        },
 | 
			
		||||
        measurePolicy = { measurables, constraints ->
 | 
			
		||||
            val spacingPx = with(density) { spacing.toPx().toInt() }
 | 
			
		||||
            val statsWidth = with(density) { 100.dp.toPx().toInt() }
 | 
			
		||||
 | 
			
		||||
            val proficienciesWidth = constraints.maxWidth - statsWidth - spacingPx
 | 
			
		||||
            val savingThrowsMeasure = measurables.savingThrows.measure(
 | 
			
		||||
                constraints.copy(
 | 
			
		||||
                    minWidth = proficienciesWidth,
 | 
			
		||||
                    maxWidth = proficienciesWidth,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            val proficienciesMeasure = measurables.proficiencies.measure(
 | 
			
		||||
                constraints.copy(
 | 
			
		||||
                    minWidth = proficienciesWidth,
 | 
			
		||||
                    maxWidth = proficienciesWidth,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            val statsHeight = savingThrowsMeasure.height + proficienciesMeasure.height + spacingPx
 | 
			
		||||
            val statsMeasure = measurables.stats.measure(
 | 
			
		||||
                constraints.copy(
 | 
			
		||||
                    minWidth = statsWidth,
 | 
			
		||||
                    maxWidth = statsWidth,
 | 
			
		||||
                    minHeight = statsHeight,
 | 
			
		||||
                    maxHeight = statsHeight,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            layout(width = constraints.maxWidth, height = statsMeasure.height) {
 | 
			
		||||
                statsMeasure.place(
 | 
			
		||||
                    x = 0,
 | 
			
		||||
                    y = 0,
 | 
			
		||||
                )
 | 
			
		||||
                savingThrowsMeasure.place(
 | 
			
		||||
                    x = statsWidth + spacingPx,
 | 
			
		||||
                    y = 0,
 | 
			
		||||
                )
 | 
			
		||||
                proficienciesMeasure.place(
 | 
			
		||||
                    x = statsWidth + spacingPx,
 | 
			
		||||
                    y = savingThrowsMeasure.height + spacingPx,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
val List<Measurable>.stats get() = first { it.layoutId == "StatsId" }
 | 
			
		||||
val List<Measurable>.savingThrows get() = first { it.layoutId == "SavingThrowsId" }
 | 
			
		||||
val List<Measurable>.proficiencies get() = first { it.layoutId == "ProficienciesId" }
 | 
			
		||||
| 
						 | 
				
			
			@ -2,22 +2,16 @@ package com.pixelized.rplexicon.ui.screens.character.composable
 | 
			
		|||
 | 
			
		||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
 | 
			
		||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.sizeIn
 | 
			
		||||
import androidx.compose.foundation.layout.width
 | 
			
		||||
import androidx.compose.foundation.shape.CutCornerShape
 | 
			
		||||
import androidx.compose.material3.Divider
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
| 
						 | 
				
			
			@ -26,65 +20,49 @@ import androidx.compose.ui.tooling.preview.Preview
 | 
			
		|||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
class LabelPointUio(
 | 
			
		||||
    val label: Int?,
 | 
			
		||||
    val value: String?,
 | 
			
		||||
    val max: String?,
 | 
			
		||||
    val max: String? = null,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun LabelPoint(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    style: TextStyle = MaterialTheme.typography.displayMedium,
 | 
			
		||||
    hp: LabelPointUio,
 | 
			
		||||
    onClick: (() -> Unit)? = null
 | 
			
		||||
    titleStyle: TextStyle = MaterialTheme.typography.labelSmall,
 | 
			
		||||
    valueStyle: TextStyle = MaterialTheme.typography.headlineMedium,
 | 
			
		||||
    labelStyle: TextStyle = MaterialTheme.typography.titleMedium,
 | 
			
		||||
    label: LabelPointUio,
 | 
			
		||||
) {
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier
 | 
			
		||||
            .sizeIn(minWidth = 96.dp, minHeight = 80.dp)
 | 
			
		||||
            .ddBorder(
 | 
			
		||||
                horizontalSpacing = 4.dp,
 | 
			
		||||
                verticalSpacing = 4.dp,
 | 
			
		||||
                outline = remember {
 | 
			
		||||
                    CutCornerShape(
 | 
			
		||||
                        topStart = 16.dp,
 | 
			
		||||
                        topEnd = 16.dp,
 | 
			
		||||
                        bottomEnd = 38.dp,
 | 
			
		||||
                        bottomStart = 38.dp
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                inner = remember {
 | 
			
		||||
                    CutCornerShape(
 | 
			
		||||
                        topStart = 14.dp,
 | 
			
		||||
                        topEnd = 14.dp,
 | 
			
		||||
                        bottomEnd = 36.dp,
 | 
			
		||||
                        bottomStart = 36.dp
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
            .clickable(enabled = onClick != null) { onClick?.let { it() } }
 | 
			
		||||
            .padding(all = 8.dp),
 | 
			
		||||
        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
        modifier = modifier.padding(all = 8.dp),
 | 
			
		||||
        verticalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
        horizontalAlignment = Alignment.CenterHorizontally
 | 
			
		||||
    ) {
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
            text = hp.label?.let { stringResource(id = it) } ?: ""
 | 
			
		||||
        )
 | 
			
		||||
        Text(
 | 
			
		||||
            style = style,
 | 
			
		||||
            text = hp.value ?: ""
 | 
			
		||||
        )
 | 
			
		||||
        Divider(
 | 
			
		||||
            modifier = Modifier.width(width = 32.dp),
 | 
			
		||||
        )
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
            text = hp.max ?: ""
 | 
			
		||||
        )
 | 
			
		||||
        label.label?.let {
 | 
			
		||||
            Text(
 | 
			
		||||
                style = titleStyle,
 | 
			
		||||
                text = stringResource(id = it)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        Row(
 | 
			
		||||
            horizontalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
        ) {
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                style = valueStyle,
 | 
			
		||||
                text = label.value ?: "0"
 | 
			
		||||
            )
 | 
			
		||||
            label.max?.let {
 | 
			
		||||
                Text(
 | 
			
		||||
                    modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                    style = labelStyle,
 | 
			
		||||
                    text = it,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,26 +78,24 @@ private fun LabelPointPreview() {
 | 
			
		|||
                horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally),
 | 
			
		||||
            ) {
 | 
			
		||||
                LabelPoint(
 | 
			
		||||
                    style = MaterialTheme.typography.displaySmall,
 | 
			
		||||
                    hp = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_hp,
 | 
			
		||||
                    label = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_ca,
 | 
			
		||||
                        value = "15",
 | 
			
		||||
                        max = null
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
                LabelPoint(
 | 
			
		||||
                    hp = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_ca,
 | 
			
		||||
                    label = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_hp,
 | 
			
		||||
                        value = "13",
 | 
			
		||||
                        max = "15"
 | 
			
		||||
                        max = "/ 15"
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
                LabelPoint(
 | 
			
		||||
                    style = MaterialTheme.typography.displaySmall,
 | 
			
		||||
                    hp = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_initiative,
 | 
			
		||||
                        value = "+0",
 | 
			
		||||
                        max = null
 | 
			
		||||
                    label = LabelPointUio(
 | 
			
		||||
                        label = R.string.character_sheet_title_speed,
 | 
			
		||||
                        value = "10",
 | 
			
		||||
                        max = "m"
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
 | 
			
		|||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.unit.Dp
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.dashedBorder
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun MasteryCircle(
 | 
			
		||||
| 
						 | 
				
			
			@ -22,17 +23,22 @@ fun MasteryCircle(
 | 
			
		|||
        0 -> Box(
 | 
			
		||||
            modifier = modifier
 | 
			
		||||
                .size(size = size)
 | 
			
		||||
                .border(
 | 
			
		||||
                .dashedBorder(
 | 
			
		||||
                    width = 1.dp,
 | 
			
		||||
                    color = MaterialTheme.colorScheme.onSurface,
 | 
			
		||||
                    shape = CircleShape
 | 
			
		||||
                    shape = CircleShape,
 | 
			
		||||
                    on = 2.dp,
 | 
			
		||||
                    off = 1.dp
 | 
			
		||||
                )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        1 -> Box(
 | 
			
		||||
            modifier = modifier
 | 
			
		||||
                .size(size = size)
 | 
			
		||||
                .background(color = MaterialTheme.colorScheme.onSurface, shape = CircleShape)
 | 
			
		||||
                .background(
 | 
			
		||||
                    color = MaterialTheme.colorScheme.onSurface,
 | 
			
		||||
                    shape = CircleShape,
 | 
			
		||||
                )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        else -> Box(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Arrangement
 | 
			
		|||
import androidx.compose.foundation.layout.Box
 | 
			
		||||
import androidx.compose.foundation.layout.PaddingValues
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.heightIn
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.size
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +17,7 @@ import androidx.compose.runtime.Stable
 | 
			
		|||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.style.TextOverflow
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
| 
						 | 
				
			
			@ -28,60 +28,162 @@ import com.pixelized.rplexicon.utilitary.extentions.toLabel
 | 
			
		|||
 | 
			
		||||
@Stable
 | 
			
		||||
data class ProficiencyUio(
 | 
			
		||||
    @StringRes val label: Int,              // the proficiency label
 | 
			
		||||
    @StringRes val related: Int,    // the related stat to the proficiency
 | 
			
		||||
    val id: ID,
 | 
			
		||||
    val multiplier: Int,            // the multiplier (use for the circle) 0 -> None 1 -> Mastery 2 -> Expertise
 | 
			
		||||
    val modifier: Int,              // the proficiency value. (stats + mastery)
 | 
			
		||||
)
 | 
			
		||||
) {
 | 
			
		||||
    enum class ID(
 | 
			
		||||
        @StringRes val label: Int,      // the proficiency label
 | 
			
		||||
        @StringRes val related: Int?,   // the related stat to the proficiency
 | 
			
		||||
    ) {
 | 
			
		||||
        STRENGTH_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_strength,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        DEXTERITY_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        CONSTITUTION_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        INTELLIGENCE_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        WISDOM_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_wisdom,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        CHARISMA_SAVING_THROW(
 | 
			
		||||
            label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
            related = null,
 | 
			
		||||
        ),
 | 
			
		||||
        ACROBATICS(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_acrobatics,
 | 
			
		||||
            related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
        ),
 | 
			
		||||
        ANIMAL_HANDLING(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_animal_handling,
 | 
			
		||||
            related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
        ),
 | 
			
		||||
        ARCANA(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_arcana,
 | 
			
		||||
            related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
        ),
 | 
			
		||||
        ATHLETICS(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_athletics,
 | 
			
		||||
            related = R.string.character_sheet_stat_strength_short,
 | 
			
		||||
        ),
 | 
			
		||||
        DECEPTION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_deception,
 | 
			
		||||
            related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
        ),
 | 
			
		||||
        HISTORY(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_history,
 | 
			
		||||
            related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
        ),
 | 
			
		||||
        INSIGHT(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_insight,
 | 
			
		||||
            related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
        ),
 | 
			
		||||
        INTIMIDATION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_intimidation,
 | 
			
		||||
            related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
        ),
 | 
			
		||||
        INVESTIGATION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_investigation,
 | 
			
		||||
            related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
        ),
 | 
			
		||||
        MEDICINE(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_medicine,
 | 
			
		||||
            related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
        ),
 | 
			
		||||
        NATURE(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_nature,
 | 
			
		||||
            related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
        ),
 | 
			
		||||
        PERCEPTION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_perception,
 | 
			
		||||
            related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
        ),
 | 
			
		||||
        PERFORMANCE(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_performance,
 | 
			
		||||
            related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
        ),
 | 
			
		||||
        PERSUASION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_persuasion,
 | 
			
		||||
            related = R.string.character_sheet_stat_charisma_short,
 | 
			
		||||
        ),
 | 
			
		||||
        RELIGION(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_religion,
 | 
			
		||||
            related = R.string.character_sheet_stat_intelligence_short,
 | 
			
		||||
        ),
 | 
			
		||||
        SLEIGHT_OF_HAND(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_sleight_of_hand,
 | 
			
		||||
            related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
        ),
 | 
			
		||||
        STEALTH(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_stealth,
 | 
			
		||||
            related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
        ),
 | 
			
		||||
        SURVIVAL(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_survival,
 | 
			
		||||
            related = R.string.character_sheet_stat_wisdom_short,
 | 
			
		||||
        ),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun Proficiency(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    padding: PaddingValues = PaddingValues(horizontal = 8.dp),
 | 
			
		||||
    padding: PaddingValues = PaddingValues(top = 8.dp, bottom = 8.dp, start = 4.dp, end = 8.dp),
 | 
			
		||||
    proficiency: ProficiencyUio,
 | 
			
		||||
    onClick: () -> Unit,
 | 
			
		||||
    onClick: (ProficiencyUio) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    Box(
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = modifier
 | 
			
		||||
            .heightIn(48.dp)
 | 
			
		||||
            .clickable(onClick = onClick),
 | 
			
		||||
        contentAlignment = Alignment.CenterStart,
 | 
			
		||||
            .clickable { onClick(proficiency) }
 | 
			
		||||
            .padding(paddingValues = padding),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
        horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
 | 
			
		||||
    ) {
 | 
			
		||||
        Row(
 | 
			
		||||
            modifier = Modifier.padding(paddingValues = padding),
 | 
			
		||||
            verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
            horizontalArrangement = Arrangement.spacedBy(16.dp),
 | 
			
		||||
        Box(
 | 
			
		||||
            modifier = Modifier.size(size = 24.dp),
 | 
			
		||||
            contentAlignment = Alignment.Center,
 | 
			
		||||
        ) {
 | 
			
		||||
            Box(
 | 
			
		||||
                modifier = Modifier.size(size = 24.dp),
 | 
			
		||||
                contentAlignment = Alignment.Center,
 | 
			
		||||
            ) {
 | 
			
		||||
                MasteryCircle(
 | 
			
		||||
                    multiplier = proficiency.multiplier,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            MasteryCircle(
 | 
			
		||||
                multiplier = proficiency.multiplier,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            Row(
 | 
			
		||||
                modifier = Modifier.weight(1f),
 | 
			
		||||
                horizontalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
            ) {
 | 
			
		||||
                Text(
 | 
			
		||||
                    modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                    style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                    text = stringResource(id = proficiency.label),
 | 
			
		||||
                )
 | 
			
		||||
        Row(
 | 
			
		||||
            modifier = Modifier.weight(1f),
 | 
			
		||||
            horizontalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
        ) {
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                style = MaterialTheme.typography.bodySmall,
 | 
			
		||||
                overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                maxLines = 1,
 | 
			
		||||
                text = stringResource(id = proficiency.id.label),
 | 
			
		||||
            )
 | 
			
		||||
            proficiency.id.related?.let { res ->
 | 
			
		||||
                Text(
 | 
			
		||||
                    modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                    style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
                    text = "(${stringResource(proficiency.related)})",
 | 
			
		||||
                    overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                    maxLines = 1,
 | 
			
		||||
                    text = "(${stringResource(res)})",
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Text(
 | 
			
		||||
                style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                text = proficiency.modifier.toLabel(),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
            text = proficiency.modifier.toLabel(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,20 +206,17 @@ private fun ProficiencyPreview(
 | 
			
		|||
private class ProficiencyPreviewProvider : PreviewParameterProvider<ProficiencyUio> {
 | 
			
		||||
    override val values: Sequence<ProficiencyUio> = sequenceOf(
 | 
			
		||||
        ProficiencyUio(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_acrobatics,
 | 
			
		||||
            related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
            id = ProficiencyUio.ID.ACROBATICS,
 | 
			
		||||
            multiplier = 0,
 | 
			
		||||
            modifier = -1
 | 
			
		||||
            modifier = -1,
 | 
			
		||||
        ),
 | 
			
		||||
        ProficiencyUio(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_athletics,
 | 
			
		||||
            related = R.string.character_sheet_stat_strength_short,
 | 
			
		||||
            id = ProficiencyUio.ID.ATHLETICS,
 | 
			
		||||
            multiplier = 1,
 | 
			
		||||
            modifier = 5,
 | 
			
		||||
        ),
 | 
			
		||||
        ProficiencyUio(
 | 
			
		||||
            label = R.string.character_sheet_proficiency_sleight_of_hand,
 | 
			
		||||
            related = R.string.character_sheet_stat_dexterity_short,
 | 
			
		||||
            id = ProficiencyUio.ID.SLEIGHT_OF_HAND,
 | 
			
		||||
            multiplier = 2,
 | 
			
		||||
            modifier = 8,
 | 
			
		||||
        ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,123 +0,0 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character.composable
 | 
			
		||||
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Box
 | 
			
		||||
import androidx.compose.foundation.layout.PaddingValues
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.size
 | 
			
		||||
import androidx.compose.foundation.shape.CutCornerShape
 | 
			
		||||
import androidx.compose.foundation.shape.RoundedCornerShape
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.style.TextOverflow
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.toLabel
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
data class SavingsThrowsUio(
 | 
			
		||||
    @StringRes val label: Int,  // the proficiency label
 | 
			
		||||
    val multiplier: Int,        // the multiplier (use for the circle) 0 -> None 1 -> Mastery 2 -> Expertise
 | 
			
		||||
    val modifier: Int,          // the proficiency value. (stats + mastery)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SavingsThrows(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    padding: PaddingValues = PaddingValues(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 8.dp),
 | 
			
		||||
    savingsThrows: SavingsThrowsUio,
 | 
			
		||||
    onClick: () -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = modifier
 | 
			
		||||
            .ddBorder(
 | 
			
		||||
                horizontalSpacing = 3.dp,
 | 
			
		||||
                outline = remember { CutCornerShape(size = 24.dp) },
 | 
			
		||||
                inner = remember { RoundedCornerShape(size = 24.dp) },
 | 
			
		||||
            )
 | 
			
		||||
            .clickable(onClick = onClick)
 | 
			
		||||
            .padding(paddingValues = padding),
 | 
			
		||||
        horizontalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
    ) {
 | 
			
		||||
        Box(
 | 
			
		||||
            modifier = Modifier.size(size = 24.dp),
 | 
			
		||||
            contentAlignment = Alignment.Center,
 | 
			
		||||
        ) {
 | 
			
		||||
            MasteryCircle(
 | 
			
		||||
                multiplier = savingsThrows.multiplier,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Text(
 | 
			
		||||
            modifier = Modifier.weight(weight = 1f, fill = true),
 | 
			
		||||
            style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
            maxLines = 1,
 | 
			
		||||
            overflow = TextOverflow.Ellipsis,
 | 
			
		||||
            text = stringResource(id = savingsThrows.label),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
            text = savingsThrows.modifier.toLabel(),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
 | 
			
		||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 | 
			
		||||
fun SavingsThrowsPreview(
 | 
			
		||||
    @PreviewParameter(SavingsThrowsPreviewProvider::class) preview: SavingsThrowsUio,
 | 
			
		||||
) {
 | 
			
		||||
    LexiconTheme {
 | 
			
		||||
        Surface {
 | 
			
		||||
            SavingsThrows(
 | 
			
		||||
                modifier = Modifier.padding(all = 8.dp),
 | 
			
		||||
                savingsThrows = preview,
 | 
			
		||||
                onClick = { },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private class SavingsThrowsPreviewProvider : PreviewParameterProvider<SavingsThrowsUio> {
 | 
			
		||||
    override val values: Sequence<SavingsThrowsUio> = sequenceOf(
 | 
			
		||||
        SavingsThrowsUio(
 | 
			
		||||
            label = R.string.character_sheet_stat_strength,
 | 
			
		||||
            multiplier = 0,
 | 
			
		||||
            modifier = 0,
 | 
			
		||||
        ),
 | 
			
		||||
        SavingsThrowsUio(
 | 
			
		||||
            label = R.string.character_sheet_stat_intelligence,
 | 
			
		||||
            multiplier = 1,
 | 
			
		||||
            modifier = 5,
 | 
			
		||||
        ),
 | 
			
		||||
        SavingsThrowsUio(
 | 
			
		||||
            label = R.string.character_sheet_stat_dexterity,
 | 
			
		||||
            multiplier = 2,
 | 
			
		||||
            modifier = 8,
 | 
			
		||||
        ),
 | 
			
		||||
        SavingsThrowsUio(
 | 
			
		||||
            label = R.string.character_sheet_stat_charisma,
 | 
			
		||||
            multiplier = 0,
 | 
			
		||||
            modifier = -1,
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import androidx.compose.foundation.clickable
 | 
			
		|||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.sizeIn
 | 
			
		||||
import androidx.compose.foundation.layout.width
 | 
			
		||||
import androidx.compose.foundation.shape.CutCornerShape
 | 
			
		||||
import androidx.compose.foundation.shape.RoundedCornerShape
 | 
			
		||||
| 
						 | 
				
			
			@ -29,31 +30,39 @@ import com.pixelized.rplexicon.utilitary.extentions.toLabel
 | 
			
		|||
 | 
			
		||||
@Stable
 | 
			
		||||
data class StatUio(
 | 
			
		||||
    @StringRes val label: Int,
 | 
			
		||||
    val id: ID,
 | 
			
		||||
    val value: Int,
 | 
			
		||||
    val modifier: Int,
 | 
			
		||||
)
 | 
			
		||||
) {
 | 
			
		||||
    enum class ID(
 | 
			
		||||
        @StringRes val label: Int,
 | 
			
		||||
    ) {
 | 
			
		||||
        STRENGTH(label = R.string.character_sheet_stat_strength),
 | 
			
		||||
        DEXTERITY(label = R.string.character_sheet_stat_dexterity),
 | 
			
		||||
        CONSTITUTION(label = R.string.character_sheet_stat_constitution),
 | 
			
		||||
        INTELLIGENCE(label = R.string.character_sheet_stat_intelligence),
 | 
			
		||||
        WISDOM(label = R.string.character_sheet_stat_wisdom),
 | 
			
		||||
        CHARISMA(label = R.string.character_sheet_stat_charisma),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun Stat(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    stat: StatUio,
 | 
			
		||||
    onClick: () -> Unit
 | 
			
		||||
    onClick: (StatUio) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier
 | 
			
		||||
            .ddBorder(
 | 
			
		||||
                inner = remember { RoundedCornerShape(size = 8.dp) },
 | 
			
		||||
                outline = remember { CutCornerShape(size = 16.dp) },
 | 
			
		||||
            )
 | 
			
		||||
            .clickable(onClick = onClick)
 | 
			
		||||
            .sizeIn(minWidth = 100.dp, minHeight = 130.dp)
 | 
			
		||||
            .clickable { onClick(stat) }
 | 
			
		||||
            .padding(all = 8.dp),
 | 
			
		||||
        horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
        verticalArrangement = Arrangement.spacedBy(4.dp),
 | 
			
		||||
        verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
 | 
			
		||||
    ) {
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.labelSmall,
 | 
			
		||||
            text = stringResource(id = stat.label),
 | 
			
		||||
            text = stringResource(id = stat.id.label),
 | 
			
		||||
        )
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.displayMedium,
 | 
			
		||||
| 
						 | 
				
			
			@ -76,9 +85,14 @@ private fun StatPreview() {
 | 
			
		|||
    LexiconTheme {
 | 
			
		||||
        Surface {
 | 
			
		||||
            Stat(
 | 
			
		||||
                modifier = Modifier.padding(all = 8.dp),
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .padding(all = 8.dp)
 | 
			
		||||
                    .ddBorder(
 | 
			
		||||
                        inner = remember { RoundedCornerShape(size = 8.dp) },
 | 
			
		||||
                        outline = remember { CutCornerShape(size = 16.dp) },
 | 
			
		||||
                    ),
 | 
			
		||||
                stat = StatUio(
 | 
			
		||||
                    label = R.string.character_sheet_stat_constitution,
 | 
			
		||||
                    id = StatUio.ID.CONSTITUTION,
 | 
			
		||||
                    value = 16,
 | 
			
		||||
                    modifier = 3,
 | 
			
		||||
                ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ class LexiconColors(
 | 
			
		|||
    val status: Color,
 | 
			
		||||
    val navigation: Color,
 | 
			
		||||
    val handle: Color,
 | 
			
		||||
    val rollOverlayBrush: Brush,
 | 
			
		||||
    val rollOverlayBrush: Color,
 | 
			
		||||
    val dice: Dice,
 | 
			
		||||
    val characterSheet: CharacterSheet,
 | 
			
		||||
) {
 | 
			
		||||
| 
						 | 
				
			
			@ -82,12 +82,7 @@ fun colorScheme(
 | 
			
		|||
    shadow: Color = ShadowPalette.shadow,
 | 
			
		||||
    status: Color = Color.Transparent,
 | 
			
		||||
    navigation: Color = Color.Transparent,
 | 
			
		||||
    rollOverlayBrush: Brush = Brush.radialGradient(
 | 
			
		||||
        colors = listOf(
 | 
			
		||||
            base.surface.copy(alpha = 0.75f),
 | 
			
		||||
            base.surface.copy(alpha = 0.25f),
 | 
			
		||||
        ),
 | 
			
		||||
    ),
 | 
			
		||||
    rollOverlayBrush: Color = base.surface.copy(alpha = 0.5f),
 | 
			
		||||
    dice: LexiconColors.Dice = LexiconColors.Dice(
 | 
			
		||||
        tint = base.primary,
 | 
			
		||||
        value = base.onSurface,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ import androidx.compose.runtime.remember
 | 
			
		|||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.composed
 | 
			
		||||
import androidx.compose.ui.draw.clip
 | 
			
		||||
import androidx.compose.ui.draw.shadow
 | 
			
		||||
import androidx.compose.ui.graphics.Color
 | 
			
		||||
import androidx.compose.ui.graphics.Shape
 | 
			
		||||
import androidx.compose.ui.platform.LocalDensity
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,195 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2020 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.pixelized.rplexicon.utilitary.extentions
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.BorderStroke
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.draw.drawWithCache
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
import androidx.compose.ui.geometry.Size
 | 
			
		||||
import androidx.compose.ui.geometry.isSimple
 | 
			
		||||
import androidx.compose.ui.graphics.*
 | 
			
		||||
import androidx.compose.ui.graphics.drawscope.Stroke
 | 
			
		||||
import androidx.compose.ui.graphics.drawscope.withTransform
 | 
			
		||||
import androidx.compose.ui.unit.Dp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Modify element to add border with appearance specified with a [border] and a [shape], pad the
 | 
			
		||||
 * content by the [BorderStroke.width] and clip it.
 | 
			
		||||
 *
 | 
			
		||||
 * @sample androidx.compose.foundation.samples.BorderSample()
 | 
			
		||||
 *
 | 
			
		||||
 * @param border [BorderStroke] class that specifies border appearance, such as size and color
 | 
			
		||||
 * @param shape shape of the border
 | 
			
		||||
 */
 | 
			
		||||
fun Modifier.dashedBorder(border: BorderStroke, shape: Shape = RectangleShape, on: Dp, off: Dp) =
 | 
			
		||||
    dashedBorder(width = border.width, brush = border.brush, shape = shape, on, off)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a [Modifier] that adds border with appearance specified with [width], [color] and a
 | 
			
		||||
 * [shape], pads the content by the [width] and clips it.
 | 
			
		||||
 *
 | 
			
		||||
 * @sample androidx.compose.foundation.samples.BorderSampleWithDataClass()
 | 
			
		||||
 *
 | 
			
		||||
 * @param width width of the border. Use [Dp.Hairline] for a hairline border.
 | 
			
		||||
 * @param color color to paint the border with
 | 
			
		||||
 * @param shape shape of the border
 | 
			
		||||
 * @param on the size of the solid part of the dashes
 | 
			
		||||
 * @param off the size of the space between dashes
 | 
			
		||||
 */
 | 
			
		||||
fun Modifier.dashedBorder(width: Dp, color: Color, shape: Shape = RectangleShape, on: Dp, off: Dp) =
 | 
			
		||||
    dashedBorder(width, SolidColor(color), shape, on, off)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a [Modifier] that adds border with appearance specified with [width], [brush] and a
 | 
			
		||||
 * [shape], pads the content by the [width] and clips it.
 | 
			
		||||
 *
 | 
			
		||||
 * @sample androidx.compose.foundation.samples.BorderSampleWithBrush()
 | 
			
		||||
 *
 | 
			
		||||
 * @param width width of the border. Use [Dp.Hairline] for a hairline border.
 | 
			
		||||
 * @param brush brush to paint the border with
 | 
			
		||||
 * @param shape shape of the border
 | 
			
		||||
 */
 | 
			
		||||
fun Modifier.dashedBorder(width: Dp, brush: Brush, shape: Shape, on: Dp, off: Dp): Modifier =
 | 
			
		||||
    this.then(
 | 
			
		||||
        Modifier.drawWithCache {
 | 
			
		||||
            val outline: Outline = shape.createOutline(size, layoutDirection, this)
 | 
			
		||||
            val borderSize = if (width == Dp.Hairline) 1f else width.toPx()
 | 
			
		||||
 | 
			
		||||
            var insetOutline: Outline? = null // outline used for roundrect/generic shapes
 | 
			
		||||
            var stroke: Stroke? = null // stroke to draw border for all outline types
 | 
			
		||||
            var pathClip: Path? = null // path to clip roundrect/generic shapes
 | 
			
		||||
            var inset = 0f // inset to translate before drawing the inset outline
 | 
			
		||||
            // path to draw generic shapes or roundrects with different corner radii
 | 
			
		||||
            var insetPath: Path? = null
 | 
			
		||||
            if (borderSize > 0 && size.minDimension > 0f) {
 | 
			
		||||
                if (outline is Outline.Rectangle) {
 | 
			
		||||
                    stroke = Stroke(
 | 
			
		||||
                        borderSize, pathEffect = PathEffect.dashPathEffect(
 | 
			
		||||
                            floatArrayOf(on.toPx(), off.toPx())
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Multiplier to apply to the border size to get a stroke width that is
 | 
			
		||||
                    // large enough to cover the corners while not being too large to overly
 | 
			
		||||
                    // square off the internal shape. The resultant shape will be
 | 
			
		||||
                    // clipped to the desired shape. Any value lower will show artifacts in
 | 
			
		||||
                    // the corners of shapes. A value too large will always square off
 | 
			
		||||
                    // the internal shape corners. For example, for a rounded rect border
 | 
			
		||||
                    // a large multiplier will always have squared off edges within the
 | 
			
		||||
                    // inner section of the stroke, however, having a smaller multiplier
 | 
			
		||||
                    // will still keep the rounded effect for the inner section of the
 | 
			
		||||
                    // border
 | 
			
		||||
                    val strokeWidth = 1.2f * borderSize
 | 
			
		||||
                    inset = borderSize - strokeWidth / 2
 | 
			
		||||
                    val insetSize = Size(
 | 
			
		||||
                        size.width - inset * 2,
 | 
			
		||||
                        size.height - inset * 2
 | 
			
		||||
                    )
 | 
			
		||||
                    insetOutline = shape.createOutline(insetSize, layoutDirection, this)
 | 
			
		||||
                    stroke = Stroke(
 | 
			
		||||
                        strokeWidth, pathEffect = PathEffect.dashPathEffect(
 | 
			
		||||
                            floatArrayOf(on.toPx(), off.toPx())
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                    pathClip = when (outline) {
 | 
			
		||||
                        is Outline.Rounded -> {
 | 
			
		||||
                            Path().apply { addRoundRect(outline.roundRect) }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        is Outline.Generic -> {
 | 
			
		||||
                            outline.path
 | 
			
		||||
                        }
 | 
			
		||||
                        // should not get here because we check for Outline.Rectangle above
 | 
			
		||||
                        else -> {
 | 
			
		||||
                            null
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    insetPath = when {
 | 
			
		||||
                        // Rounded rect with non equal corner radii needs a path to be pre-translated
 | 
			
		||||
                        insetOutline is Outline.Rounded && !insetOutline.roundRect.isSimple -> {
 | 
			
		||||
                            Path().apply {
 | 
			
		||||
                                addRoundRect(insetOutline.roundRect)
 | 
			
		||||
                                translate(Offset(inset, inset))
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        // Generic paths must be created and pre-translated
 | 
			
		||||
                        insetOutline is Outline.Generic -> {
 | 
			
		||||
 | 
			
		||||
                            Path().apply {
 | 
			
		||||
                                addPath(insetOutline.path, Offset(inset, inset))
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        // Drawing a round rect with equal corner radii without usage of a path
 | 
			
		||||
                        else -> {
 | 
			
		||||
                            null
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            onDrawWithContent {
 | 
			
		||||
                drawContent()
 | 
			
		||||
                // Only draw the border if a have a valid stroke parameter. If we have
 | 
			
		||||
                // an invalid border size we will just draw the content
 | 
			
		||||
                if (stroke != null) {
 | 
			
		||||
                    if (insetOutline != null && pathClip != null) {
 | 
			
		||||
                        val isSimpleRoundRect =
 | 
			
		||||
                            insetOutline is Outline.Rounded && insetOutline.roundRect.isSimple
 | 
			
		||||
                        withTransform({
 | 
			
		||||
                            clipPath(pathClip)
 | 
			
		||||
                            // we are drawing the round rect not as a path so we must
 | 
			
		||||
                            // translate ourselves othe
 | 
			
		||||
                            if (isSimpleRoundRect) {
 | 
			
		||||
                                translate(inset, inset)
 | 
			
		||||
                            }
 | 
			
		||||
                        }) {
 | 
			
		||||
                            if (isSimpleRoundRect) {
 | 
			
		||||
                                // If we don't have an insetPath then we are drawing
 | 
			
		||||
                                // a simple round rect with the corner radii all identical
 | 
			
		||||
                                val rrect = (insetOutline as Outline.Rounded).roundRect
 | 
			
		||||
                                drawRoundRect(
 | 
			
		||||
                                    brush = brush,
 | 
			
		||||
                                    topLeft = Offset(rrect.left, rrect.top),
 | 
			
		||||
                                    size = Size(rrect.width, rrect.height),
 | 
			
		||||
                                    cornerRadius = rrect.topLeftCornerRadius,
 | 
			
		||||
                                    style = stroke
 | 
			
		||||
                                )
 | 
			
		||||
                            } else if (insetPath != null) {
 | 
			
		||||
                                drawPath(insetPath, brush, style = stroke)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // Rectangular border fast path
 | 
			
		||||
                        val strokeWidth = stroke.width
 | 
			
		||||
                        val halfStrokeWidth = strokeWidth / 2
 | 
			
		||||
                        drawRect(
 | 
			
		||||
                            brush = brush,
 | 
			
		||||
                            topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
 | 
			
		||||
                            size = Size(
 | 
			
		||||
                                size.width - strokeWidth,
 | 
			
		||||
                                size.height - strokeWidth
 | 
			
		||||
                            ),
 | 
			
		||||
                            style = stroke
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue