Christian Babsek
08/07/2021, 4:34 PMmouseClickable
on the Modifier. Is it possible, to register it multiple times? It currently consumes the event and just the last "registration" takes effect. I tried to create some convenient extensions, but just the last of it seems to be called:
@Composable
fun Modifier.onLeftClickOnly(action: () -> Unit) = mouseClickable {
println("left")
if (buttons.isPrimaryPressed && !buttons.isSecondaryPressed && !buttons.isTertiaryPressed) {
action()
}
}
@Composable
fun Modifier.onMiddleClickOnly(action: () -> Unit) = mouseClickable {
if (!buttons.isPrimaryPressed && !buttons.isSecondaryPressed && buttons.isTertiaryPressed) {
action()
}
}
@Composable
fun Modifier.onRightClickOnly(action: () -> Unit) = mouseClickable {
println("right")
if (!buttons.isPrimaryPressed && buttons.isSecondaryPressed && !buttons.isTertiaryPressed) {
action()
}
}
dbaelz
08/07/2021, 5:57 PMmouseClickable
calls the same code (SemanticsActions.OnClick) as onClick
or the clickable.onClick
You could introduce a clickhandler class that receives the click (read: the callback) and then distributes the information to registered subscriber. Might not be a good idea from architecture and declarative stand point, but would say it depends on the use caseAlexander Kurasov[JB]
08/09/2021, 9:26 AMChristian Babsek
08/15/2021, 1:43 PMAlexander Kurasov[JB]
08/16/2021, 8:42 AMdbaelz
08/16/2021, 9:47 AM@ExperimentalDesktopApi
fun MouseClickScope.onPrimaryClicked(onClick: () -> Unit) {
if (buttons.isPrimaryPressed) onClick()
}
@ExperimentalDesktopApi
@Composable
fun SomeComposable() {
TextWithPrimary {
onPrimaryClicked {
println("Primary clicked")
}
}
}
@ExperimentalDesktopApi
@Composable
fun TextWithPrimary(mouseClickScope: MouseClickScope.() -> Unit) {
Text(
text = "Click me!",
modifier = Modifier.mouseClickable(onClick = mouseClickScope)
)
}
@ExperimentalDesktopApi
@Composable
fun MultipleOnClickSubscriberExample(clickManager: ClickManager) {
var text by remember { mutableStateOf("") }
var count by remember { mutableStateOf(0) }
clickManager.register("1", ClickEvent(onClick = { text += "#" }))
clickManager.register("2", ClickEvent(onClick = { count++ }))
clickManager.register("removed", ClickEvent(onClick = { text = "REMOVED" }))
clickManager.register("3", ClickEvent(onClick = { count++ }))
clickManager.unregister("removed")
// Reset text when SECONDARY button + SHIFT
clickManager.register(
"4",
ClickEvent(
ClickEvent.Button.SECONDARY,
ClickEvent.KeyboardModifier.SHIFT,
onClick = { text = "" })
)
// Reset count when SECONDARY button + CTRL
clickManager.register(
"5",
ClickEvent(
ClickEvent.Button.SECONDARY,
ClickEvent.KeyboardModifier.CTRL,
onClick = { count = 0 })
)
Column(
Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Click me!",
modifier = Modifier
.width(200.dp)
.height(50.dp)
.border(4.dp, MaterialTheme.colors.primary, RectangleShape)
.padding(8.dp)
.mouseClickable(onClick = clickManager.clickHandler()),
textAlign = TextAlign.Center
)
Spacer(Modifier.height(8.dp))
Text(
text = "No, click me!",
modifier = Modifier
.width(200.dp)
.height(50.dp)
.border(4.dp, MaterialTheme.colors.primary, RectangleShape)
.padding(8.dp)
.mouseClickable(onClick = clickManager.clickHandler()),
textAlign = TextAlign.Center
)
Spacer(Modifier.height(16.dp))
Text("Text (Button2 + SHIFT to clear): $text")
Text("Counter (Button2 + CTRL to clear): $count")
}
}
/**
* Quick and dirty implementation just to showcase it
*/
@ExperimentalDesktopApi
class ClickManager {
private val clickSubscriber = mutableMapOf<String, ClickEvent>()
fun register(id: String, clickEvent: ClickEvent) {
clickSubscriber[id] = clickEvent
}
fun unregister(id: String) {
clickSubscriber.remove(id)
}
fun clickHandler(): MouseClickScope.() -> Unit = {
clickSubscriber.forEach { (_, event) ->
if ((buttons.isPrimaryPressed && event.button == ClickEvent.Button.PRIMARY)
|| (buttons.isSecondaryPressed && event.button == ClickEvent.Button.SECONDARY)
|| (buttons.isTertiaryPressed && event.button == ClickEvent.Button.TERTIARY)
) {
if (event.keyModifier == ClickEvent.KeyboardModifier.NONE
|| (keyboardModifiers.isAltPressed && event.keyModifier == ClickEvent.KeyboardModifier.ALT)
|| (keyboardModifiers.isCtrlPressed && event.keyModifier == ClickEvent.KeyboardModifier.CTRL)
|| (keyboardModifiers.isShiftPressed && event.keyModifier == ClickEvent.KeyboardModifier.SHIFT)
|| (keyboardModifiers.isMetaPressed && event.keyModifier == ClickEvent.KeyboardModifier.META)
) {
event.onClick()
}
}
}
}
}
data class ClickEvent(
val button: Button = Button.PRIMARY,
val keyModifier: KeyboardModifier = KeyboardModifier.NONE,
val onClick: () -> Unit
) {
enum class Button { PRIMARY, SECONDARY, TERTIARY }
enum class KeyboardModifier { NONE, ALT, CTRL, SHIFT, META }
}