Application.kt 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (c) Milan Jurkulák 2024.
  3. * Contact:
  4. * e: mimoccc@gmail.com
  5. * e: mj@mjdev.org
  6. * w: https://mjdev.org
  7. */
  8. package eu.mjdev.desktop.helpers.application
  9. import androidx.compose.runtime.*
  10. import androidx.compose.ui.ExperimentalComposeUiApi
  11. import androidx.compose.ui.configureSwingGlobalsForCompose
  12. import androidx.compose.ui.platform.LocalDensity
  13. import androidx.compose.ui.platform.LocalLayoutDirection
  14. import androidx.compose.ui.platform.LocalLocalization
  15. import eu.mjdev.desktop.helpers.application.base.GlobalDensity
  16. import eu.mjdev.desktop.helpers.application.base.GlobalLayoutDirection
  17. import eu.mjdev.desktop.helpers.application.base.GlobalSnapshotManager
  18. import eu.mjdev.desktop.helpers.application.base.YieldFrameClock
  19. import eu.mjdev.desktop.helpers.application.l10n.defaultPlatformLocalization
  20. import eu.mjdev.desktop.provider.DesktopProvider.Companion.LocalDesktop
  21. import eu.mjdev.desktop.provider.DesktopProvider.Companion.rememberDesktopProvider
  22. import kotlinx.coroutines.launch
  23. import kotlinx.coroutines.runBlocking
  24. import kotlinx.coroutines.withContext
  25. import org.jetbrains.skiko.MainUIDispatcher
  26. import kotlin.system.exitProcess
  27. @OptIn(ExperimentalComposeUiApi::class)
  28. fun application(
  29. args: List<String> = emptyList(),
  30. exitProcessOnExit: Boolean = true,
  31. content: @Composable ApplicationScope.() -> Unit
  32. ) {
  33. if (System.getProperty("compose.application.configure.swing.globals") == "true") {
  34. configureSwingGlobalsForCompose()
  35. }
  36. runBlocking {
  37. awaitApplication(args) {
  38. content()
  39. }
  40. }
  41. if (exitProcessOnExit) {
  42. exitProcess(0)
  43. }
  44. }
  45. @OptIn(ExperimentalComposeUiApi::class)
  46. suspend fun awaitApplication(
  47. args: List<String> = emptyList(),
  48. content: @Composable ApplicationScope.() -> Unit
  49. ) {
  50. val applicationScope = object : ApplicationScope(args) {
  51. override fun exitApplication() {
  52. isOpen = false
  53. }
  54. }
  55. if (System.getProperty("compose.application.configure.swing.globals") == "true") {
  56. configureSwingGlobalsForCompose()
  57. }
  58. withContext(MainUIDispatcher) {
  59. withContext(YieldFrameClock) {
  60. GlobalSnapshotManager.ensureStarted()
  61. val recomposer = Recomposer(coroutineContext)
  62. launch {
  63. recomposer.runRecomposeAndApplyChanges()
  64. }
  65. launch {
  66. val applier = ApplicationApplier()
  67. val composition = Composition(applier, recomposer)
  68. try {
  69. composition.setContent {
  70. if (applicationScope.isOpen) {
  71. CompositionLocalProvider(
  72. LocalDensity provides GlobalDensity,
  73. LocalLayoutDirection provides GlobalLayoutDirection,
  74. LocalLocalization providesDefault defaultPlatformLocalization(),
  75. LocalDesktop provides rememberDesktopProvider()
  76. ) {
  77. applicationScope.content()
  78. }
  79. }
  80. }
  81. recomposer.close()
  82. recomposer.join()
  83. } finally {
  84. composition.dispose()
  85. }
  86. }
  87. }
  88. }
  89. }