Skip to content

Instantly share code, notes, and snippets.

@MatkovIvan
Created June 7, 2024 08:48
Show Gist options
  • Save MatkovIvan/11e08183b80f3a31b218a093a4ce2a9d to your computer and use it in GitHub Desktop.
Save MatkovIvan/11e08183b80f3a31b218a093a4ce2a9d to your computer and use it in GitHub Desktop.
import androidx.compose.foundation.ContextMenuArea
import androidx.compose.foundation.ContextMenuItem
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.SwingPanel
import androidx.compose.ui.window.singleWindowApplication
import java.awt.BorderLayout
import java.awt.Component
import java.awt.Dimension
import java.awt.event.MouseEvent
import java.awt.event.MouseListener
import java.awt.event.MouseMotionListener
import java.awt.event.MouseWheelEvent
import java.awt.event.MouseWheelListener
import javax.swing.JPanel
import javax.swing.JTextField
fun main() {
System.setProperty("compose.interop.blending", "true")
singleWindowApplication {
App()
}
}
@Composable
private fun App() {
ContextMenuArea(
items = {
listOf(
ContextMenuItem("User-defined Action") { },
ContextMenuItem("Another user-defined action") { }
)
}) {
SwingPanel(
modifier = Modifier.fillMaxSize(),
factory = {
InteropPanel().also { panel ->
panel.layout = BorderLayout()
val jTextField = JTextField()
jTextField.preferredSize = Dimension(400, 200)
panel.add(jTextField, BorderLayout.CENTER)
panel.subscribeToMouseEvents(jTextField)
}
}
)
}
}
// Workaround from https://github.com/JetBrains/compose-multiplatform-core/pull/915#issuecomment-1954155894
private class InteropPanel : JPanel(), MouseListener, MouseWheelListener, MouseMotionListener {
override fun mouseClicked(e: MouseEvent) = dispatchToCompose(e)
override fun mousePressed(e: MouseEvent) = dispatchToCompose(e)
override fun mouseReleased(e: MouseEvent) = dispatchToCompose(e)
override fun mouseEntered(e: MouseEvent) = dispatchToCompose(e)
override fun mouseExited(e: MouseEvent) = dispatchToCompose(e)
override fun mouseDragged(e: MouseEvent) = dispatchToCompose(e)
override fun mouseMoved(e: MouseEvent) = dispatchToCompose(e)
override fun mouseWheelMoved(e: MouseWheelEvent) = dispatchToCompose(e)
fun subscribeToMouseEvents(component: Component) {
component.addMouseListener(this)
component.addMouseMotionListener(this)
component.addMouseWheelListener(this)
}
fun unsubscribeFromMouseEvents(component: Component) {
component.removeMouseListener(this)
component.removeMouseMotionListener(this)
component.removeMouseWheelListener(this)
}
private fun dispatchToCompose(e: MouseEvent) {
when (e.id) {
MouseEvent.MOUSE_ENTERED, MouseEvent.MOUSE_EXITED -> return
}
// WARNING: it depends on implementation details that might be changed in the future without notice
parent.dispatchEvent(e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment