ChromeWindow.kt 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package eu.mjdev.desktop.windows
  2. import androidx.compose.animation.*
  3. import androidx.compose.desktop.ui.tooling.preview.Preview
  4. import androidx.compose.runtime.Composable
  5. import androidx.compose.ui.Alignment
  6. import androidx.compose.ui.input.key.KeyEvent
  7. import androidx.compose.ui.unit.Dp
  8. import androidx.compose.ui.unit.DpSize
  9. import androidx.compose.ui.window.WindowPosition
  10. import eu.mjdev.desktop.provider.DesktopScope.Companion.withDesktopScope
  11. import eu.mjdev.desktop.windows.ChromeWindowScope.Companion.withChromeWindowScope
  12. import eu.mjdev.desktop.windows.ChromeWindowState.Companion.rememberAnimState
  13. import eu.mjdev.desktop.windows.ChromeWindowState.Companion.rememberChromeWindowState
  14. import eu.mjdev.desktop.windows.ChromeWindowState.Companion.rememberWnState
  15. import eu.mjdev.desktop.windows.ChromeWindowState.Companion.updateAnimState
  16. import eu.mjdev.desktop.windows.ChromeWindowState.Companion.updateWindowState
  17. @Suppress("FunctionName", "unused")
  18. @Preview
  19. @Composable
  20. fun ChromeWindow(
  21. size: DpSize = DpSize(Dp.Unspecified, Dp.Unspecified),
  22. position: WindowPosition = WindowPosition.Aligned(Alignment.Center),
  23. windowState: ChromeWindowState = rememberChromeWindowState(position = position, size = size),
  24. visible: Boolean = true,
  25. transparent: Boolean = true,
  26. resizable: Boolean = false,
  27. enabled: Boolean = true,
  28. focusable: Boolean = true,
  29. alwaysOnTop: Boolean = true,
  30. // alwaysOnBottom: Boolean = false,
  31. enterAnimation: EnterTransition = fadeIn() + slideInVertically(initialOffsetY = { it }),
  32. exitAnimation: ExitTransition = slideOutVertically(targetOffsetY = { it }) + fadeOut(),
  33. onCreate: ChromeWindowState.() -> Unit = {},
  34. onCloseRequest: () -> Unit = {},
  35. onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
  36. onKeyEvent: (KeyEvent) -> Boolean = { false },
  37. onFocusChange: ChromeWindowState.(Boolean) -> Unit = {},
  38. onOpened: ChromeWindowState.() -> Unit = {},
  39. onClosed: ChromeWindowState.() -> Unit = {},
  40. content: @Composable () -> Unit = {}
  41. ) = ChromeWindow(
  42. windowState = windowState,
  43. visible = visible,
  44. transparent = transparent,
  45. resizable = resizable,
  46. enabled = enabled,
  47. focusable = focusable,
  48. alwaysOnTop = alwaysOnTop,
  49. // alwaysOnBottom = alwaysOnBottom,
  50. enterAnimation = enterAnimation,
  51. exitAnimation = exitAnimation,
  52. onCreate = onCreate,
  53. onCloseRequest = onCloseRequest,
  54. onPreviewKeyEvent = onPreviewKeyEvent,
  55. onKeyEvent = onKeyEvent,
  56. onFocusChange = onFocusChange,
  57. onOpened = onOpened,
  58. onClosed = onClosed,
  59. content = content
  60. )
  61. @Suppress("unused", "FunctionName")
  62. @Preview
  63. @Composable
  64. fun ChromeWindow(
  65. position: WindowPosition = WindowPosition.Aligned(Alignment.Center),
  66. windowState: ChromeWindowState = rememberChromeWindowState(position = position),
  67. visible: Boolean = true,
  68. transparent: Boolean = true,
  69. resizable: Boolean = false,
  70. enabled: Boolean = true,
  71. focusable: Boolean = true,
  72. alwaysOnTop: Boolean = true,
  73. // alwaysOnBottom: Boolean = false,
  74. enterAnimation: EnterTransition = fadeIn() + slideInVertically(initialOffsetY = { it }),
  75. exitAnimation: ExitTransition = slideOutVertically(targetOffsetY = { it }) + fadeOut(),
  76. onCreate: ChromeWindowState.() -> Unit = {},
  77. onCloseRequest: () -> Unit = {},
  78. onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
  79. onKeyEvent: (KeyEvent) -> Boolean = { false },
  80. onFocusChange: ChromeWindowState.(Boolean) -> Unit = {},
  81. onOpened: ChromeWindowState.() -> Unit = {},
  82. onClosed: ChromeWindowState.() -> Unit = {},
  83. content: @Composable () -> Unit = {}
  84. ) = ChromeWindow(
  85. windowState = windowState,
  86. visible = visible,
  87. transparent = transparent,
  88. resizable = resizable,
  89. enabled = enabled,
  90. focusable = focusable,
  91. alwaysOnTop = alwaysOnTop,
  92. // alwaysOnBottom = alwaysOnBottom,
  93. enterAnimation = enterAnimation,
  94. exitAnimation = exitAnimation,
  95. onCreate = onCreate,
  96. onCloseRequest = onCloseRequest,
  97. onPreviewKeyEvent = onPreviewKeyEvent,
  98. onKeyEvent = onKeyEvent,
  99. onFocusChange = onFocusChange,
  100. onOpened = onOpened,
  101. onClosed = onClosed,
  102. content = content
  103. )
  104. @Suppress("FunctionName")
  105. @Preview
  106. @Composable
  107. fun ChromeWindow(
  108. windowState: ChromeWindowState = rememberChromeWindowState(),
  109. visible: Boolean = true,
  110. transparent: Boolean = true,
  111. resizable: Boolean = false,
  112. enabled: Boolean = true,
  113. focusable: Boolean = true,
  114. alwaysOnTop: Boolean = true,
  115. // alwaysOnBottom: Boolean = false,
  116. enterAnimation: EnterTransition = fadeIn() + slideInVertically(initialOffsetY = { it }),
  117. exitAnimation: ExitTransition = slideOutVertically(targetOffsetY = { it }) + fadeOut(),
  118. onCloseRequest: () -> Unit = {},
  119. onCreate: ChromeWindowState.() -> Unit = {},
  120. onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
  121. onKeyEvent: (KeyEvent) -> Boolean = { false },
  122. onFocusChange: ChromeWindowState.(Boolean) -> Unit = {},
  123. onOpened: ChromeWindowState.() -> Unit = {},
  124. onClosed: ChromeWindowState.() -> Unit = {},
  125. content: @Composable () -> Unit = {}
  126. ) = withDesktopScope {
  127. if (isDebug) {
  128. content()
  129. } else {
  130. val animState = rememberAnimState(visible)
  131. val wnState = rememberWnState()
  132. windowState.onOpened.add {
  133. // if (alwaysOnBottom) {
  134. // todo
  135. // val focusOwner = window?.mostRecentFocusOwner
  136. // window?.toBack()
  137. // focusOwner?.requestFocus()
  138. // }
  139. // else if (alwaysOnTop) {
  140. // windowState.requestFocus()
  141. // }
  142. windowState.updatePositionAndSize()
  143. if (visible) {
  144. animState.value.targetState = true
  145. }
  146. onOpened(windowState)
  147. }
  148. windowState.onClosed.add(onClosed)
  149. windowState.onFocusChange.add(onFocusChange)
  150. WindowEx(
  151. onCreate = { window ->
  152. windowState.window = window
  153. onCreate(windowState)
  154. },
  155. // onOpen = {
  156. // onOpened(windowState)
  157. // },
  158. onCloseRequest,
  159. windowState,
  160. wnState.value,
  161. "",
  162. null,
  163. true,
  164. transparent,
  165. resizable,
  166. enabled,
  167. focusable,
  168. alwaysOnTop,
  169. // alwaysOnBottom,
  170. onPreviewKeyEvent,
  171. onKeyEvent,
  172. stateHelper = windowState.stateHelper,
  173. focusHelper = windowState.focusHelper,
  174. content = {
  175. withChromeWindowScope(
  176. windowState,
  177. animState,
  178. wnState
  179. ) {
  180. AnimatedVisibility(
  181. animState.value,
  182. enter = enterAnimation,
  183. exit = exitAnimation
  184. ) {
  185. content()
  186. }
  187. }
  188. }
  189. )
  190. updateAnimState(visible, animState, wnState)
  191. updateWindowState(visible, animState, wnState, windowState)
  192. }
  193. }