Skip to content

Instantly share code, notes, and snippets.

@AlexGladkov
Created July 7, 2022 11:11
Show Gist options
  • Save AlexGladkov/bb935e43406ee4c6b40036cca01b1c0b to your computer and use it in GitHub Desktop.
Save AlexGladkov/bb935e43406ee4c6b40036cca01b1c0b to your computer and use it in GitHub Desktop.
Desktop Web View
plugins {
kotlin("multiplatform")
id("org.openjfx.javafxplugin") version "0.0.10"
}
kotlin {
jvm("desktop") {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
withJava()
}
}
sourceSets {
val desktopMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
//Optional other deps
implementation(compose.uiTooling)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.animation)
implementation(compose.animationGraphics)
}
}
}
}
javafx {
version = "17"
modules = listOf("javafx.controls", "javafx.swing", "javafx.web", "javafx.graphics")
}
@Composable
fun DesktopWebView() {
val finishListener = object : PlatformImpl.FinishListener {
override fun idle(implicitExit: Boolean) {}
override fun exitCalled() {}
}
PlatformImpl.addListener(finishListener)
println("Desktop Web View start")
Window(
title = "Web View Test",
resizable = false,
state = WindowState(
placement = WindowPlacement.Floating,
size = DpSize(400.dp, 400.dp)
),
onCloseRequest = {
PlatformImpl.removeListener(finishListener)
},
content = {
val jfxPanel = remember { JFXPanel() }
Box(modifier = Modifier.fillMaxSize()) {
ComposeJFXPanel(
composeWindow = window,
jfxPanel = jfxPanel,
onCreate = {
Platform.runLater {
val root = WebView()
val engine = root.engine
val scene = Scene(root)
engine.loadWorker.stateProperty().addListener { _, _, newState ->
if (newState === Worker.State.SUCCEEDED) {
println("State ${newState.name}")
}
}
engine.loadWorker.exceptionProperty().addListener { _, _, newError ->
println("page load error : $newError")
}
jfxPanel.scene = scene
engine.load("http://google.com") // can be a html document from resources ..
engine.setOnError { error -> println("onError : $error") }
}
}, onDestroy = {
Platform.runLater {
}
}
)
}
}
)
}
@Composable
fun ComposeJFXPanel(
composeWindow: ComposeWindow,
jfxPanel: JFXPanel,
onCreate: () -> Unit,
onDestroy: () -> Unit = {}
) {
val jPanel = remember { JPanel() }
val density = LocalDensity.current.density
Layout(
content = {},
modifier = Modifier.onGloballyPositioned { childCoordinates ->
childCoordinates.parentCoordinates?.let { layoutCoordinates ->
val location = layoutCoordinates.localToWindow(Offset.Zero).round()
val size = layoutCoordinates.size
jPanel.setBounds(
(location.x / density).toInt(),
(location.y / density).toInt(),
(size.width / density).toInt(),
(size.height / density).toInt()
)
jPanel.validate()
jPanel.repaint()
}
},
measurePolicy = { _, _ -> layout(0,0) {} }
)
DisposableEffect(jPanel) {
composeWindow.add(jPanel)
jPanel.layout = BorderLayout(0, 0)
jPanel.add(jfxPanel)
onCreate()
onDispose {
onDestroy()
composeWindow.remove(jPanel)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment