jsCommon.io.nacular.doodle.application.ApplicationView.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of browser Show documentation
Show all versions of browser Show documentation
A pure Kotlin, UI framework for the Web and Desktop
package io.nacular.doodle.application
import io.nacular.doodle.core.Internal
import io.nacular.doodle.core.View
import io.nacular.doodle.dom.Event
import io.nacular.doodle.dom.HTMLElement
import io.nacular.doodle.dom.HtmlFactory
import io.nacular.doodle.dom.setHeight
import io.nacular.doodle.dom.setHeightPercent
import io.nacular.doodle.dom.setWidth
import io.nacular.doodle.dom.setWidthPercent
import io.nacular.doodle.drawing.Canvas
import io.nacular.doodle.drawing.impl.NativeCanvas
import io.nacular.doodle.focus.NativeFocusManager
import org.kodein.di.DI.Module
import org.kodein.di.bindProvider
import org.kodein.di.bindings.NoArgBindingDI
import org.kodein.di.instance
import org.kodein.di.instanceOrNull
/**
* Created by Nicholas Eddy on 1/30/20.
*/
public class ApplicationViewFactory private constructor(
public val htmlFactory : Any, // WARNING this is actually an HtmlFactory, but cannot be specified to allow inlining and internal state to work
public val nativeFocusManager: NativeFocusManager?
) {
public inline operator fun invoke(
allowDefaultDarkMode: Boolean = false,
modules : List = emptyList(),
noinline creator : NoArgBindingDI<*>.() -> T
): View = ApplicationView(htmlFactory, nativeFocusManager) { view, root -> nestedApplication(view, root, allowDefaultDarkMode, modules, creator) }
public companion object {
/**
* Module used to get access to [ApplicationViewFactory]
*/
public val AppViewModule: Module = Module(allowSilentOverride = true, name = "ApplicationView") {
// WARNING: This requires an explicit cast since we need to hide the HtmlFactory type
bindProvider { ApplicationViewFactory(instance(), instanceOrNull()) }
}
}
}
/** @suppress */
@Internal
public class ApplicationView(htmlFactory: Any, private val nativeFocusManager: NativeFocusManager?, private val builder: (ApplicationView, Any) -> Application): View() {
private val root = (htmlFactory as HtmlFactory).create().apply {
style.setWidthPercent (100.0)
style.setHeightPercent(100.0)
tabIndex = 0 // FIXME: Move this functionality into custom KeyInputStrategy?
}
private var application = null as Application?
private var initialRender = false
init {
boundsChanged += { _,old,new ->
if (old.size != new.size) {
if (new.width != old.width) {
root.style.setWidth(new.width)
}
if (new.height != old.height) {
root.style.setHeight(new.height)
}
// Send resize message to nested app since onresize won't be called automatically
// in most browsers
root.onresize?.let {
it(Event("onresize"))
}
}
}
focusChanged += { _,_,new ->
when (new) {
true -> if(nativeFocusManager?.hasFocusOwner == false) root.focus()
else -> root.blur ()
}
}
}
override fun addedToDisplay() {
super.addedToDisplay()
initialRender = true
}
override fun removedFromDisplay() {
super.removedFromDisplay()
application?.shutdown()
application = null
}
override fun render(canvas: Canvas) {
if (canvas is NativeCanvas) {
canvas.addData(listOf(root))
if (initialRender) {
application = builder(this, root)
initialRender = false
}
}
}
}