GtkThemeHelper.kt 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package eu.mjdev.desktop.theme.gtk
  2. import androidx.compose.ui.graphics.Color
  3. import eu.mjdev.desktop.data.DesktopFile
  4. import eu.mjdev.desktop.data.DesktopFile.Companion.desktopFile
  5. import eu.mjdev.desktop.extensions.Compose.SuperDarkGray
  6. import eu.mjdev.desktop.extensions.Compose.rgbToHex
  7. import eu.mjdev.desktop.helpers.internal.Palette
  8. import eu.mjdev.desktop.managers.GnomeManager.Companion.THEME_ADWAITA_DARK
  9. import eu.mjdev.desktop.managers.GnomeManager.Companion.THEME_MJDEV
  10. import eu.mjdev.desktop.provider.DesktopProvider
  11. import java.io.File
  12. @Suppress("unused", "MemberVisibilityCanBePrivate")
  13. class GtkThemeHelper(
  14. private val api: DesktopProvider,
  15. private val palette: Palette = api.palette,
  16. private val themeName: String = THEME_MJDEV,
  17. private val themesDir: File = File(api.homeDir, ".themes"),
  18. private val themeDir: File = File(themesDir, themeName),
  19. private val themeDesktopFile: File = File(themeDir, "index.theme"),
  20. private val gtk2ThemeDir: File = File(themeDir, "gtk-2.0"),
  21. private val gtk3ThemeDir: File = File(themeDir, "gtk-3.0"),
  22. private val gtk4ThemeDir: File = File(themeDir, "gtk-4.0"),
  23. private val gtk3CssFile: File = File(gtk3ThemeDir, "gtk.css"),
  24. private val gtk4CssFile: File = File(gtk4ThemeDir, "gtk.css"),
  25. ) {
  26. fun createFromPalette() {
  27. createDesktopFile()
  28. createCssFile(gtk3CssFile)
  29. createCssFile(gtk4CssFile)
  30. }
  31. private fun createDesktopFile() {
  32. desktopFile(themeDesktopFile) {
  33. mkDirs()
  34. deleteFile()
  35. desktopSection {
  36. Type = DesktopFile.DesktopFileType.Theme
  37. Name = THEME_MJDEV
  38. Comment = "dynamic system theme"
  39. Encoding = "UTF-8" // todo
  40. }
  41. themeSection {
  42. GtkTheme = THEME_MJDEV
  43. MetacityTheme = THEME_ADWAITA_DARK
  44. IconTheme = THEME_ADWAITA_DARK
  45. CursorTheme = "DMZ-White" // todo
  46. ButtonLayout = "close,minimize,maximize:"
  47. UseOverlayScrollbars = true
  48. }
  49. write()
  50. }
  51. }
  52. private fun createCssFile(file: File) = theme(file) {
  53. bgColor = palette.backgroundColor
  54. fgColor = palette.textColor
  55. baseColor = palette.baseColor
  56. textColor = palette.textColor
  57. selectedBgColor = palette.selectedBgColor
  58. selectedFgColor = palette.selectedFgColor
  59. tooltipBgColor = palette.tooltipBgColor
  60. tooltipFgColor = palette.tooltipFgColor
  61. write()
  62. }
  63. class Theme(val file: File) {
  64. var bgColor: Color = Color.SuperDarkGray
  65. var fgColor: Color = Color.SuperDarkGray
  66. var baseColor: Color = Color.SuperDarkGray
  67. var textColor: Color = Color.SuperDarkGray
  68. var borderColor: Color = Color.SuperDarkGray
  69. var selectedBgColor: Color = Color.SuperDarkGray
  70. var selectedFgColor: Color = Color.SuperDarkGray
  71. var tooltipBgColor: Color = Color.SuperDarkGray
  72. var tooltipFgColor: Color = Color.SuperDarkGray
  73. var errorFgColor: Color = Color.White
  74. var errorBgColor: Color = Color.Red
  75. var successFgColor: Color = Color.White
  76. var successBgColor: Color = Color.Red
  77. var questionFgColor: Color = Color.White
  78. var questionBgColor: Color = Color.Yellow
  79. var warningFgColor: Color = Color.White
  80. var warningBgColor: Color = Color.Magenta
  81. var infoFgColor: Color = Color.Black
  82. var infoBgColor: Color = Color.White
  83. var osdFgColor: Color = Color.Black
  84. var osdBgColor: Color = Color.SuperDarkGray
  85. override fun toString() = """
  86. @define-color bg_color ${bgColor.rgbToHex()};
  87. @define-color fg_color ${fgColor.rgbToHex()};
  88. @define-color base_color ${baseColor.rgbToHex()};
  89. @define-color text_color ${textColor.rgbToHex()};
  90. @define-color selected_bg_color ${selectedBgColor.rgbToHex()};
  91. @define-color selected_fg_color ${selectedFgColor.rgbToHex()};
  92. @define-color tooltip_bg_color ${tooltipBgColor.rgbToHex()};
  93. @define-color tooltip_fg_color ${tooltipFgColor.rgbToHex()};
  94. @define-color info_fg_color ${infoFgColor.rgbToHex()};
  95. @define-color info_bg_color ${infoBgColor.rgbToHex()};
  96. @define-color warning_fg_color ${warningFgColor.rgbToHex()};
  97. @define-color warning_bg_color ${warningBgColor.rgbToHex()};
  98. @define-color question_fg_color ${questionFgColor.rgbToHex()};
  99. @define-color question_bg_color ${questionBgColor.rgbToHex()};
  100. @define-color error_fg_color ${errorFgColor.rgbToHex()};
  101. @define-color error_bg_color ${errorBgColor.rgbToHex()};
  102. @define-color success_color ${successBgColor.rgbToHex()};
  103. @define-color error_color ${errorBgColor.rgbToHex()};
  104. @define-color dark_bg_color${bgColor.rgbToHex()};
  105. @define-color dark_fg_color ${fgColor.rgbToHex()};
  106. @define-color osd_fg_color ${osdFgColor.rgbToHex()};
  107. @define-color osd_bg_color ${osdBgColor.rgbToHex()};
  108. @define-color osd_border_color ${borderColor.rgbToHex()};
  109. @define-color link_color @selected_bg_color;
  110. @define-color button_bg_color shade (@bg_color, 1.02);
  111. @define-color notebook_button_bg_color shade (@bg_color, 1.02);
  112. @define-color button_insensitive_bg_color mix (@button_bg_color, @bg_color, 0.6);
  113. @define-color backdrop_fg_color mix (@bg_color, @fg_color, 0.8);
  114. @define-color backdrop_text_color mix (@base_color, @text_color, 0.8);
  115. @define-color backdrop_dark_fg_color mix (@dark_bg_color, @dark_fg_color, 0.75);
  116. @define-color backdrop_dark_bg_color mix (@dark_bg_color, @dark_fg_color, 0.75);
  117. @define-color backdrop_selected_bg_color shade (@bg_color, 0.92);
  118. @define-color backdrop_selected_fg_color @fg_color;
  119. @define-color focus_color alpha (@selected_bg_color, 0.5);
  120. @define-color focus_bg_color alpha (@selected_bg_color, 0.1);
  121. @define-color shadow_color alpha(black, 0.5);
  122. window {
  123. background-color: ${bgColor.rgbToHex()};
  124. border-radius: 8px;
  125. border-bottom-left-radius: 8px;
  126. border-bottom-right-radius: 8px;
  127. box-shadow: 0px 0px 0px 1px ${textColor.rgbToHex()};
  128. border: 1px solid ${textColor.rgbToHex()};
  129. border-top: none;
  130. }
  131. decoration {
  132. background-color: ${bgColor.rgbToHex()};
  133. border-radius: 8px;
  134. border-bottom-left-radius: 8px;
  135. border-bottom-right-radius: 8px;
  136. box-shadow: 0px 0px 0px 1px ${textColor.rgbToHex()};
  137. border: 1px solid ${textColor.rgbToHex()};
  138. border-top: none;
  139. }
  140. headerbar {
  141. background-color: ${bgColor.rgbToHex()};
  142. border-bottom: 1px solid ${textColor.rgbToHex()};
  143. box-shadow: 0px 1px 0px 0px ${textColor.rgbToHex()};
  144. border-top: 1px solid ${textColor.rgbToHex()};
  145. }
  146. """.trimIndent()
  147. }
  148. companion object {
  149. fun theme(
  150. file: File,
  151. block: Theme.() -> Unit
  152. ) = Theme(file).apply(block)
  153. fun Theme.write() {
  154. toString().also { data ->
  155. file.apply {
  156. parentFile.mkdirs()
  157. delete()
  158. createNewFile()
  159. }.writeText(data)
  160. }
  161. }
  162. }
  163. }