All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.io.nacular.doodle.theme.native.NativeTheme.kt Maven / Gradle / Ivy

There is a newer version: 0.10.4
Show newest version
package io.nacular.doodle.theme.native

import io.nacular.doodle.controls.buttons.Button
import io.nacular.doodle.controls.buttons.CheckBox
import io.nacular.doodle.controls.buttons.HyperLink
import io.nacular.doodle.controls.buttons.RadioButton
import io.nacular.doodle.controls.buttons.Switch
import io.nacular.doodle.controls.files.FileSelector
import io.nacular.doodle.controls.panels.ScrollPanel
import io.nacular.doodle.controls.range.Slider
import io.nacular.doodle.controls.text.TextField
import io.nacular.doodle.core.Behavior
import io.nacular.doodle.core.View
import io.nacular.doodle.core.WindowGroupImpl
import io.nacular.doodle.drawing.GraphicsDevice
import io.nacular.doodle.drawing.impl.RealGraphicsSurface
import io.nacular.doodle.system.impl.NativeScrollHandlerFinder
import io.nacular.doodle.theme.Modules
import io.nacular.doodle.theme.Modules.Companion.ThemeModule
import io.nacular.doodle.theme.Modules.Companion.bindBehavior
import io.nacular.doodle.theme.Scene
import io.nacular.doodle.theme.adhoc.DynamicTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.swing.Swing
import org.jetbrains.skia.Canvas
import org.kodein.di.DI.Module
import org.kodein.di.bindInstance
import org.kodein.di.bindSingleton
import org.kodein.di.erasedSet
import org.kodein.di.instance
import org.kodein.di.instanceOrNull
import java.awt.GraphicsEnvironment
import javax.swing.FocusManager
import javax.swing.JPanel

private typealias NTheme = NativeTheme

/**
 * Theme incorporates [Behavior]s that style Views using the underlying platform so they look as close to native as
 * possible.
 */
public class NativeTheme internal constructor(behaviors: Iterable): DynamicTheme(behaviors.filter { it.theme == NTheme::class }) {
    private lateinit var scene: Scene

    override fun toString(): String = this::class.simpleName ?: ""

    override fun install(scene: Scene) {
        super.install(scene)
        this.scene = scene
    }

    internal class WindowDiscovery(private val windowGroup: WindowGroupImpl) {
        fun frameFor (view: View): JPanel?                              = windowGroup.owner(view)?.skiaLayer
        fun deviceFor(view: View): GraphicsDevice? = windowGroup.owner(view)?.graphicsDevice
    }

    @Suppress("MemberVisibilityCanBePrivate")
    public companion object {
        private val CommonNativeModule = Module(allowSilentOverride = true, name = "CommonNativeModule") {
            bindInstance { GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration }
            bindSingleton {
                object: SwingGraphicsFactory {
                    override fun invoke(skiaCanvas: Canvas): SkiaGraphics2D {
                        return SkiaGraphics2D(
                            canvas         = skiaCanvas,
                            defaultFont    = instance(),
                            textMetrics    = instance(),
                            fontCollection = instance()
                        )
                    }
                }
            }

            bindSingleton { WindowDiscovery(instance()) }
        }

        /**
         * Module for injecting the [NativeTheme].
         */
        public val NativeTheme: Module = Module(name = "NativeTheme") {
            importOnce(ThemeModule, allowOverride = true)

            bindSingleton { NativeTheme(Instance(erasedSet())) }
        }

        /**
         * Module that provides [Behavior]s for [Button]s that are styled by the underlying platform to look as close to native as
         * possible.
         */
        public fun nativeButtonBehavior(): Module = Module(name = "NativeButtonBehavior") {
            importOnce(CommonNativeModule, allowOverride = true)

            bindBehavior




© 2015 - 2024 Weber Informatics LLC | Privacy Policy