Skip to content

Commit a006af4

Browse files
authored
Merge pull request #48 from ForBai/themeing
Themeing
2 parents f80f83d + 6310f46 commit a006af4

34 files changed

Lines changed: 1599 additions & 172 deletions

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ build/
55
run/
66
docs-versions/
77
.vscode/
8+
9+
.project
10+
.classpath
11+
bin
12+
.settings
13+
.sisyphus
14+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.cobalt.api.ui.theme
2+
3+
interface Theme {
4+
5+
val name: String
6+
7+
val background: Int
8+
val panel: Int
9+
val inset: Int
10+
val overlay: Int
11+
12+
val text: Int
13+
val textPrimary: Int
14+
val textSecondary: Int
15+
val textDisabled: Int
16+
val textPlaceholder: Int
17+
val textOnAccent: Int
18+
19+
val accent: Int
20+
val accentPrimary: Int
21+
val accentSecondary: Int
22+
val selection: Int
23+
24+
val controlBg: Int
25+
val controlBorder: Int
26+
val inputBg: Int
27+
val inputBorder: Int
28+
29+
val success: Int
30+
val warning: Int
31+
val error: Int
32+
val info: Int
33+
34+
val scrollbarThumb: Int
35+
val scrollbarTrack: Int
36+
val sliderTrack: Int
37+
val sliderFill: Int
38+
val sliderThumb: Int
39+
40+
val tooltipBackground: Int
41+
val tooltipBorder: Int
42+
val tooltipText: Int
43+
44+
val notificationBackground: Int
45+
val notificationBorder: Int
46+
val notificationText: Int
47+
val notificationTextSecondary: Int
48+
49+
val infoBackground: Int
50+
val infoBorder: Int
51+
val infoIcon: Int
52+
val warningBackground: Int
53+
val warningBorder: Int
54+
val warningIcon: Int
55+
val successBackground: Int
56+
val successBorder: Int
57+
val successIcon: Int
58+
val errorBackground: Int
59+
val errorBorder: Int
60+
val errorIcon: Int
61+
62+
val selectionText: Int
63+
val searchPlaceholderText: Int
64+
val moduleDivider: Int
65+
val selectedOverlay: Int
66+
67+
val white: Int
68+
val black: Int
69+
val transparent: Int
70+
71+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.cobalt.api.ui.theme
2+
3+
import org.cobalt.api.ui.theme.impl.DarkTheme
4+
import org.cobalt.api.ui.theme.impl.LightTheme
5+
6+
object ThemeManager {
7+
8+
private val themes = mutableListOf<Theme>()
9+
var currentTheme: Theme = DarkTheme()
10+
private set
11+
12+
init {
13+
registerTheme(DarkTheme())
14+
registerTheme(LightTheme())
15+
}
16+
17+
fun registerTheme(theme: Theme) {
18+
if (themes.none { it.name == theme.name }) {
19+
themes.add(theme)
20+
}
21+
}
22+
23+
fun setTheme(theme: Theme) {
24+
currentTheme = theme
25+
}
26+
27+
fun getThemes(): List<Theme> {
28+
return themes
29+
}
30+
31+
fun unregisterTheme(theme: Theme): Boolean {
32+
// Prevent deleting built-in themes
33+
if (theme.name == "Dark" || theme.name == "Light") return false
34+
35+
val removed = themes.removeIf { it.name == theme.name }
36+
37+
// If deleted theme was current, switch to DarkTheme
38+
if (removed && currentTheme.name == theme.name) {
39+
currentTheme = themes.first { it.name == "Dark" }
40+
}
41+
42+
return removed
43+
}
44+
45+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package org.cobalt.api.ui.theme
2+
3+
import java.awt.Color
4+
import org.cobalt.api.ui.theme.impl.CustomTheme
5+
6+
/**
7+
* A generalized color palette that can generate a full [CustomTheme].
8+
* This allows users to set a few key colors and derive the rest.
9+
*/
10+
data class ThemePalette(
11+
var primary: Int = Color(61, 94, 149).rgb,
12+
var background: Int = Color(18, 18, 18).rgb,
13+
var surface: Int = Color(24, 24, 24).rgb,
14+
var error: Int = Color(178, 34, 34).rgb,
15+
var text: Int = Color(230, 230, 230).rgb,
16+
var textSecondary: Int = Color(179, 179, 179).rgb
17+
) {
18+
19+
fun applyTo(theme: CustomTheme) {
20+
fun Int.adjust(factor: Float): Int {
21+
val c = Color(this, true)
22+
val r = (c.red * factor).coerceIn(0f, 255f).toInt()
23+
val g = (c.green * factor).coerceIn(0f, 255f).toInt()
24+
val b = (c.blue * factor).coerceIn(0f, 255f).toInt()
25+
return Color(r, g, b, c.alpha).rgb
26+
}
27+
28+
fun Int.alpha(alpha: Int): Int {
29+
val c = Color(this, true)
30+
return Color(c.red, c.green, c.blue, alpha.coerceIn(0, 255)).rgb
31+
}
32+
33+
// Base colors
34+
theme.background = background
35+
theme.panel = surface
36+
theme.inset = background.adjust(1.2f)
37+
theme.overlay = background.alpha(230)
38+
39+
// Text
40+
theme.text = text
41+
theme.textPrimary = text.adjust(1.1f)
42+
theme.textSecondary = textSecondary
43+
theme.textDisabled = text.alpha(100)
44+
theme.textPlaceholder = text.alpha(120)
45+
theme.textOnAccent = text.adjust(1.2f)
46+
47+
// Accent
48+
theme.accent = primary
49+
theme.accentPrimary = primary.adjust(0.9f)
50+
theme.accentSecondary = primary.adjust(1.1f)
51+
theme.selection = primary.alpha(100)
52+
theme.selectedOverlay = primary.alpha(50)
53+
54+
// Controls
55+
theme.controlBg = surface.adjust(1.5f).alpha(50)
56+
theme.controlBorder = surface.adjust(2.0f)
57+
theme.inputBg = surface.adjust(1.5f).alpha(50)
58+
theme.inputBorder = surface.adjust(2.0f)
59+
60+
// Status
61+
theme.success = Color(34, 139, 34).rgb
62+
theme.warning = Color(184, 134, 11).rgb
63+
theme.error = error
64+
theme.info = primary
65+
66+
// Status backgrounds
67+
theme.successBackground = theme.success.alpha(25)
68+
theme.successBorder = theme.success.alpha(150)
69+
theme.successIcon = theme.success
70+
71+
theme.warningBackground = theme.warning.alpha(25)
72+
theme.warningBorder = theme.warning.alpha(150)
73+
theme.warningIcon = theme.warning
74+
75+
theme.errorBackground = error.alpha(25)
76+
theme.errorBorder = error.alpha(150)
77+
theme.errorIcon = error
78+
79+
theme.infoBackground = primary.alpha(25)
80+
theme.infoBorder = primary.alpha(150)
81+
theme.infoIcon = primary
82+
83+
// UI Elements
84+
theme.scrollbarThumb = primary
85+
theme.scrollbarTrack = surface.adjust(1.2f)
86+
theme.sliderTrack = surface.adjust(2.5f)
87+
theme.sliderFill = primary
88+
theme.sliderThumb = primary
89+
90+
theme.tooltipBackground = background.alpha(240)
91+
theme.tooltipBorder = surface.adjust(2.0f)
92+
theme.tooltipText = text
93+
94+
theme.notificationBackground = background
95+
theme.notificationBorder = primary
96+
theme.notificationText = text
97+
theme.notificationTextSecondary = theme.textDisabled
98+
99+
theme.selectionText = text
100+
theme.searchPlaceholderText = text.alpha(128)
101+
theme.moduleDivider = surface.adjust(2.0f)
102+
103+
theme.white = Color.WHITE.rgb
104+
theme.black = Color.BLACK.rgb
105+
theme.transparent = Color(0, 0, 0, 0).rgb
106+
}
107+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.cobalt.api.ui.theme.impl
2+
3+
import org.cobalt.api.ui.theme.Theme
4+
import java.awt.Color
5+
6+
data class CustomTheme(
7+
override var name: String = "Custom",
8+
override var background: Int = Color(18, 18, 18).rgb,
9+
override var panel: Int = Color(24, 24, 24).rgb,
10+
override var inset: Int = Color(30, 30, 30).rgb,
11+
override var overlay: Int = Color(18, 18, 18, 230).rgb,
12+
override var text: Int = Color(230, 230, 230).rgb,
13+
override var textPrimary: Int = Color(245, 245, 245).rgb,
14+
override var textSecondary: Int = Color(179, 179, 179).rgb,
15+
override var textDisabled: Int = Color(120, 120, 120).rgb,
16+
override var textPlaceholder: Int = Color(128, 128, 128).rgb,
17+
override var textOnAccent: Int = Color(245, 245, 245).rgb,
18+
override var accent: Int = Color(61, 94, 149).rgb,
19+
override var accentPrimary: Int = Color(53, 85, 139).rgb,
20+
override var accentSecondary: Int = Color(86, 116, 170).rgb,
21+
override var selection: Int = Color(70, 130, 180, 100).rgb,
22+
override var controlBg: Int = Color(42, 42, 42, 50).rgb,
23+
override var controlBorder: Int = Color(42, 42, 42).rgb,
24+
override var inputBg: Int = Color(42, 42, 42, 50).rgb,
25+
override var inputBorder: Int = Color(42, 42, 42).rgb,
26+
override var success: Int = Color(34, 139, 34).rgb,
27+
override var warning: Int = Color(184, 134, 11).rgb,
28+
override var error: Int = Color(178, 34, 34).rgb,
29+
override var info: Int = Color(61, 94, 149).rgb,
30+
override var scrollbarThumb: Int = Color(61, 94, 149).rgb,
31+
override var scrollbarTrack: Int = Color(32, 32, 32).rgb,
32+
override var sliderTrack: Int = Color(60, 60, 60).rgb,
33+
override var sliderFill: Int = Color(61, 94, 149).rgb,
34+
override var sliderThumb: Int = Color(61, 94, 149).rgb,
35+
override var tooltipBackground: Int = Color(18, 18, 18, 240).rgb,
36+
override var tooltipBorder: Int = Color(42, 42, 42).rgb,
37+
override var tooltipText: Int = Color(230, 230, 230).rgb,
38+
override var notificationBackground: Int = Color(25, 25, 25).rgb,
39+
override var notificationBorder: Int = Color(61, 94, 149).rgb,
40+
override var notificationText: Int = Color(230, 230, 230).rgb,
41+
override var notificationTextSecondary: Int = Color(179, 179, 179).rgb,
42+
override var infoBackground: Int = Color(61, 94, 149, 25).rgb,
43+
override var infoBorder: Int = Color(61, 94, 149, 150).rgb,
44+
override var infoIcon: Int = Color(61, 94, 149, 255).rgb,
45+
override var warningBackground: Int = Color(184, 134, 11, 25).rgb,
46+
override var warningBorder: Int = Color(184, 134, 11, 150).rgb,
47+
override var warningIcon: Int = Color(184, 134, 11, 255).rgb,
48+
override var successBackground: Int = Color(34, 139, 34, 25).rgb,
49+
override var successBorder: Int = Color(34, 139, 34, 150).rgb,
50+
override var successIcon: Int = Color(34, 139, 34, 255).rgb,
51+
override var errorBackground: Int = Color(178, 34, 34, 25).rgb,
52+
override var errorBorder: Int = Color(178, 34, 34, 150).rgb,
53+
override var errorIcon: Int = Color(178, 34, 34, 255).rgb,
54+
override var selectionText: Int = Color(245, 245, 245).rgb,
55+
override var searchPlaceholderText: Int = Color(128, 128, 128).rgb,
56+
override var moduleDivider: Int = Color(42, 42, 42).rgb,
57+
override var selectedOverlay: Int = Color(61, 94, 149, 50).rgb,
58+
override var white: Int = Color(255, 255, 255).rgb,
59+
override var black: Int = Color(0, 0, 0).rgb,
60+
override var transparent: Int = Color(0, 0, 0, 0).rgb
61+
) : Theme
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.cobalt.api.ui.theme.impl
2+
3+
import org.cobalt.api.ui.theme.Theme
4+
import java.awt.Color
5+
6+
class DarkTheme : Theme {
7+
8+
override val name = "Dark"
9+
10+
override val background = Color(18, 18, 18).rgb
11+
override val panel = Color(24, 24, 24).rgb
12+
override val inset = Color(30, 30, 30).rgb
13+
override val overlay = Color(18, 18, 18, 230).rgb
14+
15+
override val text = Color(230, 230, 230).rgb
16+
override val textPrimary = Color(245, 245, 245).rgb
17+
override val textSecondary = Color(179, 179, 179).rgb
18+
override val textDisabled = Color(120, 120, 120).rgb
19+
override val textPlaceholder = Color(128, 128, 128).rgb
20+
override val textOnAccent = Color(245, 245, 245).rgb
21+
22+
override val accent = Color(61, 94, 149).rgb
23+
override val accentPrimary = Color(53, 85, 139).rgb
24+
override val accentSecondary = Color(86, 116, 170).rgb
25+
override val selection = Color(70, 130, 180, 100).rgb
26+
27+
override val controlBg = Color(42, 42, 42, 50).rgb
28+
override val controlBorder = Color(42, 42, 42).rgb
29+
override val inputBg = Color(42, 42, 42, 50).rgb
30+
override val inputBorder = Color(42, 42, 42).rgb
31+
32+
override val success = Color(34, 139, 34).rgb
33+
override val warning = Color(184, 134, 11).rgb
34+
override val error = Color(178, 34, 34).rgb
35+
override val info = Color(61, 94, 149).rgb
36+
37+
override val scrollbarThumb = Color(61, 94, 149).rgb
38+
override val scrollbarTrack = Color(32, 32, 32).rgb
39+
override val sliderTrack = Color(60, 60, 60).rgb
40+
override val sliderFill = Color(61, 94, 149).rgb
41+
override val sliderThumb = Color(61, 94, 149).rgb
42+
43+
override val tooltipBackground = Color(18, 18, 18, 240).rgb
44+
override val tooltipBorder = Color(42, 42, 42).rgb
45+
override val tooltipText = Color(230, 230, 230).rgb
46+
47+
override val notificationBackground = Color(18, 18, 18).rgb
48+
override val notificationBorder = Color(61, 94, 149).rgb
49+
override val notificationText = Color(230, 230, 230).rgb
50+
override val notificationTextSecondary = Color(120, 120, 120).rgb
51+
52+
override val infoBackground = Color(61, 94, 149, 25).rgb
53+
override val infoBorder = Color(61, 94, 149, 150).rgb
54+
override val infoIcon = Color(61, 94, 149, 255).rgb
55+
override val warningBackground = Color(184, 134, 11, 25).rgb
56+
override val warningBorder = Color(184, 134, 11, 150).rgb
57+
override val warningIcon = Color(184, 134, 11, 255).rgb
58+
override val successBackground = Color(34, 139, 34, 25).rgb
59+
override val successBorder = Color(34, 139, 34, 150).rgb
60+
override val successIcon = Color(34, 139, 34, 255).rgb
61+
override val errorBackground = Color(178, 34, 34, 25).rgb
62+
override val errorBorder = Color(178, 34, 34, 150).rgb
63+
override val errorIcon = Color(178, 34, 34, 255).rgb
64+
65+
override val selectionText = Color(245, 245, 245).rgb
66+
override val searchPlaceholderText = Color(128, 128, 128).rgb
67+
override val moduleDivider = Color(42, 42, 42).rgb
68+
override val selectedOverlay = Color(61, 94, 149, 50).rgb
69+
70+
override val white = Color(255, 255, 255).rgb
71+
override val black = Color(0, 0, 0).rgb
72+
override val transparent = Color(0, 0, 0, 0).rgb
73+
74+
}

0 commit comments

Comments
 (0)