mirror of
https://github.com/BetterAndroid/FlexiUI.git
synced 2025-09-08 11:34:18 +08:00
feat: add local context menu style
This commit is contained in:
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
@@ -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
|
||||||
)
|
)
|
Reference in New Issue
Block a user