From 604ec4bec0514dbd3186c7898efaaca174941e71 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Sat, 18 Nov 2023 04:06:12 +0800 Subject: [PATCH] refactor: use properties to share data in DropdownList --- .../flexiui/component/Dropdown.android.kt | 23 ++++++-- .../highcapable/flexiui/component/Dropdown.kt | 59 ++++++++++--------- .../flexiui/component/Dropdown.desktop.kt | 29 ++++++--- .../flexiui/component/Dropdown.ios.kt | 29 ++++++--- 4 files changed, 94 insertions(+), 46 deletions(-) diff --git a/flexiui-core/src/androidMain/kotlin/com/highcapable/flexiui/component/Dropdown.android.kt b/flexiui-core/src/androidMain/kotlin/com/highcapable/flexiui/component/Dropdown.android.kt index fdf9252..564c1b1 100644 --- a/flexiui-core/src/androidMain/kotlin/com/highcapable/flexiui/component/Dropdown.android.kt +++ b/flexiui-core/src/androidMain/kotlin/com/highcapable/flexiui/component/Dropdown.android.kt @@ -38,21 +38,36 @@ import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.node.Ref import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.semantics.Role +import com.highcapable.flexiui.interaction.rippleClickable import kotlin.math.max @Composable internal actual fun DropdownListBox( + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, modifier: Modifier, + properties: DropdownListProperties, menuHeightPx: (Int) -> Unit, content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit ) { val view = LocalView.current val coordinates = remember { Ref() } BoxWithConstraints( - modifier = modifier.onGloballyPositioned { - coordinates.value = it - updateHeight(view.rootView, coordinates.value) { newHeight -> menuHeightPx(newHeight) } - }, + modifier = Modifier.dropdownList( + properties = properties, + modifier = modifier.rippleClickable( + enabled = properties.enabled, + role = Role.DropdownList, + interactionSource = properties.interactionSource + ) { + properties.focusRequester.requestFocus() + onExpandedChange(!expanded) + }.onGloballyPositioned { + coordinates.value = it + updateHeight(view.rootView, coordinates.value) { newHeight -> menuHeightPx(newHeight) } + } + ), content = content ) DisposableEffect(view) { diff --git a/flexiui-core/src/commonMain/kotlin/com/highcapable/flexiui/component/Dropdown.kt b/flexiui-core/src/commonMain/kotlin/com/highcapable/flexiui/component/Dropdown.kt index a25b2d2..d210f4c 100644 --- a/flexiui-core/src/commonMain/kotlin/com/highcapable/flexiui/component/Dropdown.kt +++ b/flexiui-core/src/commonMain/kotlin/com/highcapable/flexiui/component/Dropdown.kt @@ -183,21 +183,16 @@ fun DropdownList( else -> style.borderInactive }.copy(animatedBorderWidth, SolidColor(animatedBorderColor)) DropdownListBox( - modifier = modifier.dropdownList( + expanded = expanded, + onExpandedChange = onExpandedChange, + modifier = modifier, + properties = DropdownListProperties( colors = colors, style = style, border = border, enabled = enabled, focusRequester = focusRequester, - interactionSource = interactionSource, - modifier = modifier.rippleClickable( - enabled = enabled, - role = Role.DropdownList, - interactionSource = interactionSource - ) { - focusRequester.requestFocus() - onExpandedChange(!expanded) - } + interactionSource = interactionSource ), menuHeightPx = { menuHeightPx = it } ) { @@ -366,34 +361,42 @@ private fun DropdownMenuContent( @Composable internal expect fun DropdownListBox( + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, modifier: Modifier, + properties: DropdownListProperties, menuHeightPx: (Int) -> Unit, content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit ) -private fun Modifier.dropdownList( - colors: DropdownListColors, - style: DropdownListStyle, - border: BorderStroke, - enabled: Boolean, - focusRequester: FocusRequester, - interactionSource: MutableInteractionSource, +internal fun Modifier.dropdownList( + properties: DropdownListProperties, modifier: Modifier -) = status(enabled) - .focusRequester(focusRequester) - .focusable(enabled, interactionSource) - .hoverable(interactionSource, enabled) - .clip(style.shape) - .background(colors.backgroundColor, style.shape) - .borderOrNot(border, style.shape) +) = status(properties.enabled) + .focusRequester(properties.focusRequester) + .focusable(properties.enabled, properties.interactionSource) + .hoverable(properties.interactionSource, properties.enabled) + .clip(properties.style.shape) + .background(properties.colors.backgroundColor, properties.style.shape) + .borderOrNot(properties.border, properties.style.shape) .then(modifier) .padding( - top = style.topPadding.orElse() ?: style.padding, - start = style.startPadding.orElse() ?: style.padding, - bottom = style.bottomPadding.orElse() ?: style.padding, - end = style.endPadding.orElse() ?: style.padding + top = properties.style.topPadding.orElse() ?: properties.style.padding, + start = properties.style.startPadding.orElse() ?: properties.style.padding, + bottom = properties.style.bottomPadding.orElse() ?: properties.style.padding, + end = properties.style.endPadding.orElse() ?: properties.style.padding ) +@Immutable +internal data class DropdownListProperties( + val colors: DropdownListColors, + val style: DropdownListStyle, + val border: BorderStroke, + val enabled: Boolean, + val focusRequester: FocusRequester, + val interactionSource: MutableInteractionSource +) + private fun calculateTransformOrigin(parentBounds: IntRect, menuBounds: IntRect): TransformOrigin { val pivotX = when { menuBounds.left >= parentBounds.right -> 0f diff --git a/flexiui-core/src/desktopMain/kotlin/com/highcapable/flexiui/component/Dropdown.desktop.kt b/flexiui-core/src/desktopMain/kotlin/com/highcapable/flexiui/component/Dropdown.desktop.kt index 5cdd9d4..f04b48d 100644 --- a/flexiui-core/src/desktopMain/kotlin/com/highcapable/flexiui/component/Dropdown.desktop.kt +++ b/flexiui-core/src/desktopMain/kotlin/com/highcapable/flexiui/component/Dropdown.desktop.kt @@ -31,24 +31,39 @@ import androidx.compose.ui.UiComposable import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.toIntRect +import com.highcapable.flexiui.interaction.rippleClickable import kotlin.math.max @Composable internal actual fun DropdownListBox( + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, modifier: Modifier, + properties: DropdownListProperties, menuHeightPx: (Int) -> Unit, content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit ) { val windowInfo = LocalWindowInfo.current BoxWithConstraints( - modifier = modifier.onGloballyPositioned { - val boundsInWindow = it.boundsInWindow() - val visibleWindowBounds = windowInfo.containerSize.toIntRect() - val heightAbove = boundsInWindow.top - visibleWindowBounds.top - val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom - menuHeightPx(max(heightAbove, heightBelow).toInt()) - }, + modifier = Modifier.dropdownList( + properties = properties, + modifier = modifier.rippleClickable( + enabled = properties.enabled, + role = Role.DropdownList, + interactionSource = properties.interactionSource + ) { + properties.focusRequester.requestFocus() + onExpandedChange(!expanded) + }.onGloballyPositioned { + val boundsInWindow = it.boundsInWindow() + val visibleWindowBounds = windowInfo.containerSize.toIntRect() + val heightAbove = boundsInWindow.top - visibleWindowBounds.top + val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom + menuHeightPx(max(heightAbove, heightBelow).toInt()) + } + ), content = content ) } \ No newline at end of file diff --git a/flexiui-core/src/iosMain/kotlin/com/highcapable/flexiui/component/Dropdown.ios.kt b/flexiui-core/src/iosMain/kotlin/com/highcapable/flexiui/component/Dropdown.ios.kt index 5cdd9d4..f04b48d 100644 --- a/flexiui-core/src/iosMain/kotlin/com/highcapable/flexiui/component/Dropdown.ios.kt +++ b/flexiui-core/src/iosMain/kotlin/com/highcapable/flexiui/component/Dropdown.ios.kt @@ -31,24 +31,39 @@ import androidx.compose.ui.UiComposable import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.toIntRect +import com.highcapable.flexiui.interaction.rippleClickable import kotlin.math.max @Composable internal actual fun DropdownListBox( + expanded: Boolean, + onExpandedChange: (Boolean) -> Unit, modifier: Modifier, + properties: DropdownListProperties, menuHeightPx: (Int) -> Unit, content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit ) { val windowInfo = LocalWindowInfo.current BoxWithConstraints( - modifier = modifier.onGloballyPositioned { - val boundsInWindow = it.boundsInWindow() - val visibleWindowBounds = windowInfo.containerSize.toIntRect() - val heightAbove = boundsInWindow.top - visibleWindowBounds.top - val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom - menuHeightPx(max(heightAbove, heightBelow).toInt()) - }, + modifier = Modifier.dropdownList( + properties = properties, + modifier = modifier.rippleClickable( + enabled = properties.enabled, + role = Role.DropdownList, + interactionSource = properties.interactionSource + ) { + properties.focusRequester.requestFocus() + onExpandedChange(!expanded) + }.onGloballyPositioned { + val boundsInWindow = it.boundsInWindow() + val visibleWindowBounds = windowInfo.containerSize.toIntRect() + val heightAbove = boundsInWindow.top - visibleWindowBounds.top + val heightBelow = visibleWindowBounds.height - boundsInWindow.bottom + menuHeightPx(max(heightAbove, heightBelow).toInt()) + } + ), content = content ) } \ No newline at end of file