Coverage Summary for Class: SubdivisionsChooserKt (com.vsevolodganin.clicktrack.ui.piece)

Class Class, % Method, % Branch, % Line, % Instruction, %
SubdivisionsChooserKt 0% (0/1) 0% (0/44) 0% (0/238) 0% (0/725) 0% (0/4864)


 package com.vsevolodganin.clicktrack.ui.piece
 
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.AnimatedVisibilityScope
 import androidx.compose.animation.expandVertically
 import androidx.compose.animation.fadeIn
 import androidx.compose.animation.fadeOut
 import androidx.compose.animation.shrinkVertically
 import androidx.compose.animation.slideInHorizontally
 import androidx.compose.animation.slideOutHorizontally
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.wrapContentWidth
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.Icon
 import androidx.compose.material.IconButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.unit.dp
 import com.vsevolodganin.clicktrack.generated.resources.MR
 import com.vsevolodganin.clicktrack.model.NotePattern
 import com.vsevolodganin.clicktrack.model.NotePatternGroup
 import com.vsevolodganin.clicktrack.model.TimeSignature
 import com.vsevolodganin.clicktrack.utils.compose.Preview
 import dev.icerock.moko.resources.compose.painterResource
 
 @Composable
 fun SubdivisionsChooser(
     pattern: NotePattern,
     timeSignature: TimeSignature,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier = Modifier,
     alwaysExpanded: Boolean = false,
 ) {
     var expanded by remember { mutableStateOf(false) }
 
     val collapsingOnSubdivisionChoose: (NotePattern) -> Unit = remember {
         {
             expanded = false
             onSubdivisionChoose(it)
         }
     }
 
     Row(
         modifier = modifier,
         horizontalArrangement = Arrangement.spacedBy(8.dp),
     ) {
         val layoutModifier = Modifier.weight(1f)
         val layoutArrangement = Arrangement.spacedBy(4.dp)
         val noteValue = timeSignature.noteValue
         val reallyExpanded = alwaysExpanded || expanded
 
         when (noteValue) {
             1 -> WholeNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement, reallyExpanded)
             in 2..3 -> HalfNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement, reallyExpanded)
             in 4..7 -> QuarterNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement, reallyExpanded)
             in 8..15 -> EighthNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement, reallyExpanded)
             in 16..31 -> SixteenthNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement, reallyExpanded)
             in 32..Int.MAX_VALUE -> ThirtySecondNoteLayout(pattern, collapsingOnSubdivisionChoose, layoutModifier, layoutArrangement)
             else -> error("Non-positive note value")
         }
 
         AnimatedVisibility(
             visible = noteValue < 32 && !alwaysExpanded,
             enter = fadeIn() + slideInHorizontally(initialOffsetX = { it / 2 }),
             exit = fadeOut() + slideOutHorizontally(targetOffsetX = { it / 2 }),
         ) {
             IconButton(modifier = Modifier.wrapContentWidth(unbounded = true), onClick = { expanded = !expanded }) {
                 ExpandableChevron(expanded)
             }
         }
     }
 }
 
 @Composable
 private fun WholeNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
     expanded: Boolean,
 ) {
     Column(
         modifier = modifier,
         verticalArrangement = arrangement,
     ) {
         val rowModifier = Modifier.fillMaxWidth()
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.STRAIGHT) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.whole),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.half),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X32,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.TRIPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.half_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_triplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.QUINTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_quintuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.SEPTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_septuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.DISPLACED) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_half),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_thirty_second),
                 )
             }
         }
     }
 }
 
 @Composable
 private fun HalfNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
     expanded: Boolean,
 ) {
     Column(
         modifier = modifier,
         verticalArrangement = arrangement,
     ) {
         val rowModifier = Modifier.fillMaxWidth()
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.STRAIGHT) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.half),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.TRIPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.half_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_triplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.QUINTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_quintuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.SEPTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_septuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.DISPLACED) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_half),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X16,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_thirty_second),
                 )
             }
         }
     }
 }
 
 @Composable
 private fun QuarterNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
     expanded: Boolean,
 ) {
     Column(
         modifier = modifier,
         verticalArrangement = arrangement,
     ) {
         val rowModifier = Modifier.fillMaxWidth()
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.STRAIGHT) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.TRIPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_triplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.QUINTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_quintuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.SEPTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.quarter_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_septuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.DISPLACED) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_quarter),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X8,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_thirty_second),
                 )
             }
         }
     }
 }
 
 @Composable
 private fun EighthNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
     expanded: Boolean,
 ) {
     Column(
         modifier = modifier,
         verticalArrangement = arrangement,
     ) {
         val rowModifier = Modifier.fillMaxWidth()
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.STRAIGHT) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.TRIPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_triplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.QUINTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_quintuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.SEPTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.eighth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_septuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.DISPLACED) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_eighth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X4,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_thirty_second),
                 )
             }
         }
     }
 }
 
 @Composable
 private fun SixteenthNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
     expanded: Boolean,
 ) {
     Column(
         modifier = modifier,
         verticalArrangement = arrangement,
     ) {
         val rowModifier = Modifier.fillMaxWidth()
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.STRAIGHT) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.STRAIGHT_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.TRIPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_triplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.TRIPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_triplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.QUINTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_quintuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.QUINTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_quintuplet),
                 )
             }
         }
 
         RowAnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.SEPTUPLET) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.sixteenth_septuplet),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.SEPTUPLET_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.thirty_second_septuplet),
                 )
             }
         }
 
         AnimatedVisibility(visible = expanded || pattern.group == NotePatternGroup.DISPLACED) {
             Row(
                 modifier = rowModifier,
                 horizontalArrangement = arrangement,
             ) {
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X1,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_sixteenth),
                 )
                 SubdivisionItem(
                     actualPattern = pattern,
                     expectedPattern = NotePattern.DISPLACED_X2,
                     onSubdivisionChoose = onSubdivisionChoose,
                     iconPainter = painterResource(MR.images.displaced_thirty_second),
                 )
             }
         }
     }
 }
 
 @Composable
 private fun ThirtySecondNoteLayout(
     pattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     modifier: Modifier,
     arrangement: Arrangement.HorizontalOrVertical,
 ) {
     Row(
         modifier = modifier.fillMaxWidth(),
         horizontalArrangement = arrangement,
     ) {
         SubdivisionItem(
             actualPattern = pattern,
             expectedPattern = NotePattern.STRAIGHT_X1,
             onSubdivisionChoose = onSubdivisionChoose,
             iconPainter = painterResource(MR.images.thirty_second),
         )
         SubdivisionItem(
             actualPattern = pattern,
             expectedPattern = NotePattern.TRIPLET_X1,
             onSubdivisionChoose = onSubdivisionChoose,
             iconPainter = painterResource(MR.images.thirty_second_triplet),
         )
         SubdivisionItem(
             actualPattern = pattern,
             expectedPattern = NotePattern.QUINTUPLET_X1,
             onSubdivisionChoose = onSubdivisionChoose,
             iconPainter = painterResource(MR.images.thirty_second_quintuplet),
         )
         SubdivisionItem(
             actualPattern = pattern,
             expectedPattern = NotePattern.SEPTUPLET_X1,
             onSubdivisionChoose = onSubdivisionChoose,
             iconPainter = painterResource(MR.images.thirty_second_septuplet),
         )
         SubdivisionItem(
             actualPattern = pattern,
             expectedPattern = NotePattern.DISPLACED_X1,
             onSubdivisionChoose = onSubdivisionChoose,
             iconPainter = painterResource(MR.images.displaced_thirty_second),
         )
     }
 }
 
 @Composable
 private fun RowScope.SubdivisionItem(
     actualPattern: NotePattern,
     expectedPattern: NotePattern,
     onSubdivisionChoose: (NotePattern) -> Unit,
     iconPainter: Painter,
 ) {
     SubdivisionItem(
         onClick = { onSubdivisionChoose(expectedPattern) },
         isSelected = actualPattern == expectedPattern,
         iconPainter = iconPainter,
     )
 }
 
 @Composable
 private fun RowScope.SubdivisionItem(onClick: () -> Unit, isSelected: Boolean, iconPainter: Painter) {
     Box(
         modifier = Modifier
             .weight(1f)
             .height(50.dp)
             .selectableBorder(isSelected)
             .clickable(onClick = onClick)
             .padding(8.dp),
     ) {
         Icon(
             painter = iconPainter,
             modifier = Modifier.align(Alignment.Center),
             contentDescription = null,
         )
     }
 }
 
 @Composable
 private fun RowAnimatedVisibility(visible: Boolean, content: @Composable AnimatedVisibilityScope.() -> Unit) {
     AnimatedVisibility(
         visible = visible,
         enter = fadeIn() + expandVertically(),
         exit = fadeOut() + shrinkVertically(),
         content = content,
     )
 }
 
 @Preview
 @Composable
 private fun Preview() {
     Column(
         modifier = Modifier
             .fillMaxSize()
             .verticalScroll(rememberScrollState()),
     ) {
         for (noteDuration in arrayOf(1, 2, 4, 8, 16, 32)) {
             var pattern by remember { mutableStateOf(NotePattern.STRAIGHT_X1) }
             SubdivisionsChooser(
                 pattern = pattern,
                 timeSignature = TimeSignature(4, noteDuration),
                 onSubdivisionChoose = { pattern = it },
             )
             Spacer(modifier = Modifier.height(16.dp))
         }
     }
 }