feat: add local context menu style

This commit is contained in:
2023-11-09 15:56:32 +08:00
parent 0e166f6f84
commit 01cd400b90
2 changed files with 54 additions and 21 deletions

View File

@@ -26,9 +26,17 @@ package com.highcapable.flexiui
import androidx.compose.foundation.LocalContextMenuRepresentation import androidx.compose.foundation.LocalContextMenuRepresentation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import com.highcapable.flexiui.component.defaultFlexiContextMenuRepresentation import com.highcapable.flexiui.component.DesktopContextMenu
import com.highcapable.flexiui.component.DesktopContextMenuRepresentation
import com.highcapable.flexiui.component.LocalContextMenuStyle
import com.highcapable.flexiui.component.defaultContextMenuStyle
@Composable @Composable
internal actual fun FlexiThemeContent(content: @Composable () -> Unit) { internal actual fun FlexiThemeContent(content: @Composable () -> Unit) {
CompositionLocalProvider(LocalContextMenuRepresentation provides defaultFlexiContextMenuRepresentation(), content = content) CompositionLocalProvider(LocalContextMenuStyle provides defaultContextMenuStyle()) {
CompositionLocalProvider(
LocalContextMenuRepresentation provides DesktopContextMenuRepresentation(DesktopContextMenu.style),
content = content
)
}
} }

View File

@@ -42,7 +42,9 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -74,21 +76,26 @@ import androidx.compose.ui.window.rememberPopupPositionProviderAtPosition
import com.highcapable.flexiui.LocalColors import com.highcapable.flexiui.LocalColors
import com.highcapable.flexiui.LocalShapes import com.highcapable.flexiui.LocalShapes
import com.highcapable.flexiui.LocalSizes import com.highcapable.flexiui.LocalSizes
import com.highcapable.flexiui.utils.orElse
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
internal class FlexiContextMenuRepresentation( @Immutable
private val backgroundColor: Color, data class ContextMenuStyle(
private val fillColor: Color, val backgroundColor: Color,
private val textColor: Color, val fillColor: Color,
private val padding: Dp, val textColor: Color,
private val shadowSize: Dp, val padding: Dp,
private val shape: Shape val shadowSize: Dp,
) : ContextMenuRepresentation { val shape: Shape?
)
internal class DesktopContextMenuRepresentation(private val style: ContextMenuStyle) : ContextMenuRepresentation {
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
override fun Representation(state: ContextMenuState, items: () -> List<ContextMenuItem>) { override fun Representation(state: ContextMenuState, items: () -> List<ContextMenuItem>) {
val status = state.status val status = state.status
if (status is ContextMenuState.Status.Open) { if (status is ContextMenuState.Status.Open) {
val shape = style.shape ?: return
var focusManager: FocusManager? by mutableStateOf(null) var focusManager: FocusManager? by mutableStateOf(null)
var inputModeManager: InputModeManager? by mutableStateOf(null) var inputModeManager: InputModeManager? by mutableStateOf(null)
Popup( Popup(
@@ -115,15 +122,15 @@ internal class FlexiContextMenuRepresentation(
inputModeManager = LocalInputModeManager.current inputModeManager = LocalInputModeManager.current
Column( Column(
modifier = Modifier modifier = Modifier
.shadow(elevation = shadowSize, shape = shape) .shadow(elevation = style.shadowSize, shape = shape)
.background(color = backgroundColor, shape = shape) .background(color = style.backgroundColor, shape = shape)
.padding(padding) .padding(style.padding)
.width(IntrinsicSize.Max) .width(IntrinsicSize.Max)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
items().forEach { item -> items().forEach { item ->
MenuItemContent( MenuItemContent(
fillColor = fillColor, fillColor = style.fillColor,
shape = shape, shape = shape,
onClick = { onClick = {
state.status = ContextMenuState.Status.Closed state.status = ContextMenuState.Status.Closed
@@ -183,13 +190,31 @@ private fun Modifier.onHover(onHover: (Boolean) -> Unit) = pointerInput(Unit) {
} }
} }
object DesktopContextMenu {
val style: ContextMenuStyle
@Composable
@ReadOnlyComposable
get() = LocalContextMenuStyle.current
}
val LocalContextMenuStyle = compositionLocalOf {
ContextMenuStyle(
backgroundColor = Color.Unspecified,
fillColor = Color.Unspecified,
textColor = Color.Unspecified,
padding = Dp.Unspecified,
shadowSize = Dp.Unspecified,
shape = null
)
}
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
internal fun defaultFlexiContextMenuRepresentation() = FlexiContextMenuRepresentation( internal fun defaultContextMenuStyle() = ContextMenuStyle(
backgroundColor = LocalColors.current.foregroundPrimary, backgroundColor = LocalContextMenuStyle.current.backgroundColor.orElse() ?: LocalColors.current.foregroundPrimary,
fillColor = LocalColors.current.themeSecondary, fillColor = LocalContextMenuStyle.current.fillColor.orElse() ?: LocalColors.current.themeSecondary,
textColor = LocalColors.current.textPrimary, textColor = LocalContextMenuStyle.current.textColor.orElse() ?: LocalColors.current.textPrimary,
padding = LocalSizes.current.spacingTertiary, padding = LocalContextMenuStyle.current.padding.orElse() ?: LocalSizes.current.spacingTertiary,
shadowSize = LocalSizes.current.zoomSizeTertiary, shadowSize = LocalContextMenuStyle.current.shadowSize.orElse() ?: LocalSizes.current.zoomSizeTertiary,
shape = LocalShapes.current.primary shape = LocalContextMenuStyle.current.shape ?: LocalShapes.current.primary
) )