0

So I have the concept of a popup menu...

@Composable
expect fun PopupMenu(
    menuItems: List<String>,
    onClickCallbacks: List<() -> Unit>,
    showMenu: Boolean,
    onDismiss: () -> Unit,
    toggle: @Composable () -> Unit,
)

And I have a popup menu implementation for desktop...

@Composable
actual fun PopupMenu(
    menuItems: List<String>,
    onClickCallbacks: List<() -> Unit>,
    showMenu: Boolean,
    onDismiss: () -> Unit,
    toggle: @Composable () -> Unit,
) {
    DropdownMenu(
        expanded = showMenu,
        onDismissRequest = { onDismiss() },
    ) {
        menuItems.forEachIndexed { index, item ->
            DropdownMenuItem(onClick = {
                onDismiss()
                onClickCallbacks[index]
            }) {
                Text(text = item)
            }
        }
    }
}

What I'm trying to figure out is, how do I display this around here?

@Composable
fun OneCard(content: MutableState<TextFieldValue>, onValueChange: (TextFieldValue) -> Unit ) {
    Card(modifier = Modifier.draggable(DraggableState {  }, Orientation.Vertical)
        .then(Modifier.padding(16.dp))) {
        OutlinedTextField(
            value = content.value,
            onValueChange = onValueChange,
            placeholder = { TextFieldValue(text = "Your thoughts?") },
            modifier = Modifier.selectable(
                selected = false,
                onClick = {
                    // TODO: How to show popup menu on right click, or perhaps after a delay,
                    //       somewhere near the selected text?
                }
            )
        )
    }
}
Hakanai
  • 12,010
  • 10
  • 62
  • 132
  • @PhilipDukhov I'm not sure. I think it puts the popup menu below the entire component, but I'd really want it near the selected text? Or at the position of the mouse click? – Hakanai Oct 03 '21 at 12:16
  • You should update your question with more details of the expected behaviour. You haven't mentioned that you need to show it near the selected text. I don't think that `DropdownMenu` will work for you, because accrding to [documentation](https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#DropdownMenu(kotlin.Boolean,kotlin.Function0,androidx.compose.ui.Modifier,androidx.compose.ui.unit.DpOffset,androidx.compose.ui.window.PopupProperties,kotlin.Function1)) it's really meant to be displayed under the calling element, not on some specified position. – Phil Dukhov Oct 03 '21 at 12:48
  • @PhilipDukhov the question did say "somewhere near the selected text", not sure how much more clear I could have been on that? Besides, where else would I want to show a popup menu on a right click? – Hakanai Oct 03 '21 at 21:18

1 Answers1

2

CursorDropdownMenu can be used in this case, for example here's how you can show it on mouse right clicks:

var expanded by remember { mutableStateOf(false) }
Box(
    Modifier
        .fillMaxSize()
        .mouseClickable {
            if (buttons.isSecondaryPressed) {
                expanded = true
            }
        }
)
// tmp fix for https://github.com/JetBrains/compose-jb/issues/2012
var renderCount by remember { mutableStateOf(0) }
listOf(renderCount, renderCount - 1).forEach { renderId ->
    val isActive = renderId == renderCount
    key(renderId) {
        CursorDropdownMenu(
            expanded = expanded && isActive,
            onDismissRequest = {
                if (isActive) {
                    renderCount += 1
                    expanded = false
                }
            },
        ) {
            DropdownMenuItem({}) {
                Text("First item")
            }
            DropdownMenuItem({}) {
                Text("Second item")
            }
        }
    }
}
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220