DesktopPanel.kt 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package eu.mjdev.desktop.components.desktoppanel
  2. import androidx.compose.animation.*
  3. import androidx.compose.foundation.ExperimentalFoundationApi
  4. import androidx.compose.foundation.TooltipArea
  5. import androidx.compose.foundation.TooltipPlacement
  6. import androidx.compose.foundation.background
  7. import androidx.compose.foundation.gestures.Orientation.Vertical
  8. import androidx.compose.foundation.layout.*
  9. import androidx.compose.material.Divider
  10. import androidx.compose.runtime.Composable
  11. import androidx.compose.runtime.MutableState
  12. import androidx.compose.runtime.mutableStateOf
  13. import androidx.compose.ui.Alignment
  14. import androidx.compose.ui.Modifier
  15. import androidx.compose.ui.graphics.Brush
  16. import androidx.compose.ui.graphics.Color
  17. import androidx.compose.ui.layout.onPlaced
  18. import androidx.compose.ui.unit.Dp
  19. import androidx.compose.ui.unit.DpOffset
  20. import androidx.compose.ui.unit.DpSize
  21. import androidx.compose.ui.unit.dp
  22. import androidx.compose.ui.window.WindowPosition
  23. import eu.mjdev.desktop.components.desktoppanel.applets.DesktopMenuIcon
  24. import eu.mjdev.desktop.components.desktoppanel.applets.DesktopPanelFavoriteApps
  25. import eu.mjdev.desktop.components.desktoppanel.applets.DesktopPanelLanguage
  26. import eu.mjdev.desktop.components.shadow.TopShadow
  27. import eu.mjdev.desktop.components.sliding.SlidingMenu
  28. import eu.mjdev.desktop.components.sliding.VisibilityState
  29. import eu.mjdev.desktop.components.sliding.VisibilityState.Companion.rememberVisibilityState
  30. import eu.mjdev.desktop.extensions.Compose.height
  31. import eu.mjdev.desktop.helpers.DpBounds.Companion.toDpBounds
  32. import eu.mjdev.desktop.provider.DesktopProvider
  33. import eu.mjdev.desktop.provider.DesktopProvider.Companion.LocalDesktop
  34. import eu.mjdev.desktop.provider.data.App
  35. import eu.mjdev.desktop.windows.ChromeWindow
  36. @OptIn(ExperimentalFoundationApi::class)
  37. @Suppress("FunctionName")
  38. @Composable
  39. fun DesktopPanel(
  40. api: DesktopProvider = LocalDesktop.current,
  41. backgroundColor: Color = api.currentUser.theme.backgroundColor,
  42. shadowColor: Color = backgroundColor,
  43. iconColor: Color = Color.Black,
  44. iconBackgroundColor: Color = Color.White,
  45. dividerWidth: Dp = 4.dp,
  46. iconSize: DpSize = DpSize(56.dp, 56.dp),
  47. iconPadding: PaddingValues = PaddingValues(4.dp),
  48. iconOuterPadding: PaddingValues = PaddingValues(2.dp),
  49. panelAlpha: Float = 0.7f,
  50. showMenuIcon: Boolean = true,
  51. panelState: VisibilityState = rememberVisibilityState(),
  52. enterAnimation: EnterTransition = fadeIn() + slideInVertically(initialOffsetY = { it }),
  53. exitAnimation: ExitTransition = slideOutVertically(targetOffsetY = { it }) + fadeOut(),
  54. menuState: VisibilityState = rememberVisibilityState(),
  55. tooltipData: MutableState<Any?> = mutableStateOf(null),
  56. onTooltip: (item: Any?) -> Unit = { item -> tooltipData.value = item },
  57. panelHeight: (visible: Boolean) -> Dp = { visible ->
  58. if (visible) iconSize.height + iconOuterPadding.height else dividerWidth
  59. },
  60. onMenuIconClicked: () -> Unit = {},
  61. ) = ChromeWindow(
  62. visible = true,
  63. enterAnimation = enterAnimation,
  64. exitAnimation = exitAnimation,
  65. position = WindowPosition.Aligned(Alignment.BottomCenter),
  66. size = DpSize(
  67. api.containerSize.width,
  68. panelHeight(panelState.isVisible)
  69. ),
  70. onFocusChange = { focus -> if (!focus && !menuState.isVisible) panelState.hide() }
  71. ) {
  72. SlidingMenu(
  73. modifier = Modifier.fillMaxWidth(),
  74. orientation = Vertical,
  75. state = panelState,
  76. ) { isVisible ->
  77. if (!isVisible) {
  78. Divider(
  79. modifier = Modifier
  80. .fillMaxWidth()
  81. .height(dividerWidth),
  82. color = Color.Transparent,
  83. thickness = dividerWidth
  84. )
  85. } else {
  86. TooltipArea(
  87. modifier = Modifier.fillMaxWidth().wrapContentHeight(),
  88. tooltip = {
  89. // todo more types
  90. when (tooltipData.value) {
  91. is App -> DesktopPanelAppTooltip(tooltipData.value as App)
  92. else -> {}
  93. }
  94. },
  95. tooltipPlacement = TooltipPlacement.CursorPoint(
  96. alignment = Alignment.TopEnd,
  97. offset = DpOffset(32.dp, 32.dp)
  98. )
  99. ) {
  100. TopShadow(
  101. modifier = Modifier.fillMaxWidth().wrapContentHeight().onPlaced {
  102. panelState.bounds = it.toDpBounds()
  103. },
  104. color = shadowColor,
  105. contentBackgroundColor = backgroundColor.copy(alpha = panelAlpha)
  106. ) {
  107. Box(
  108. modifier = Modifier.fillMaxWidth().wrapContentHeight().background(
  109. brush = Brush.verticalGradient(
  110. colors = listOf(
  111. backgroundColor.copy(alpha = 0.3f),
  112. backgroundColor.copy(alpha = 0.7f),
  113. backgroundColor.copy(alpha = 0.3f),
  114. )
  115. )
  116. )
  117. ) {
  118. if (showMenuIcon) {
  119. DesktopMenuIcon(
  120. modifier = Modifier.align(Alignment.CenterStart),
  121. iconColor = iconColor,
  122. iconBackgroundColor = iconBackgroundColor,
  123. iconSize = iconSize,
  124. iconPadding = iconPadding,
  125. iconOuterPadding = iconOuterPadding,
  126. onTooltip = onTooltip,
  127. onClick = onMenuIconClicked
  128. )
  129. }
  130. DesktopPanelFavoriteApps(
  131. modifier = Modifier.align(Alignment.Center),
  132. iconColor = iconColor,
  133. iconBackgroundColor = iconBackgroundColor,
  134. iconSize = iconSize,
  135. iconPadding = iconPadding,
  136. iconOuterPadding = iconOuterPadding,
  137. onTooltip = onTooltip
  138. )
  139. DesktopPanelLanguage(
  140. modifier = Modifier.align(Alignment.CenterEnd),
  141. onTooltip = onTooltip,
  142. onClick = {
  143. // todo
  144. }
  145. )
  146. }
  147. }
  148. }
  149. }
  150. }
  151. }