summaryrefslogtreecommitdiff
path: root/internal/tui/theme.go
blob: 862f193d20111649bb852456f4f0d3dedf6ae08c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package tui

import (
	"math/rand/v2"
	"strconv"
)

// Theme defines the shared color palette used across the TUI.
type Theme struct {
	HeaderFG   string
	SelectedFG string
	SelectedBG string
	RowFG      string
	RowBG      string
	StatusFG   string
	StatusBG   string
	SearchFG   string
	SearchBG   string
}

// DefaultTheme returns the baseline theme inspired by Task Samurai.
func DefaultTheme() Theme {
	return Theme{
		HeaderFG:   "205",
		SelectedFG: "229",
		SelectedBG: "57",
		RowFG:      "15",
		RowBG:      "236",
		StatusFG:   "229",
		StatusBG:   "57",
		SearchFG:   "21",
		SearchBG:   "226",
	}
}

// RandomTheme returns a randomized high-contrast palette for disco mode.
func RandomTheme() Theme {
	theme := Theme{
		HeaderFG:   randomColor(),
		SelectedBG: randomColor(),
		RowBG:      randomColor(),
		StatusBG:   randomColor(),
		SearchBG:   randomColor(),
	}

	theme.SelectedFG = contrastColor(theme.SelectedBG)
	theme.RowFG = contrastColor(theme.RowBG)
	theme.StatusFG = contrastColor(theme.StatusBG)
	theme.SearchFG = contrastColor(theme.SearchBG)
	return theme
}

func randomColor() string {
	return strconv.Itoa(rand.IntN(256))
}

func contrastColor(background string) string {
	value, err := strconv.Atoi(background)
	if err != nil {
		return "15"
	}

	if xtermBrightness(value) > 128 {
		return "0"
	}
	return "15"
}

func xtermBrightness(index int) float64 {
	red, green, blue := xtermRGB(index)
	return 0.299*float64(red) + 0.587*float64(green) + 0.114*float64(blue)
}

func xtermRGB(index int) (int, int, int) {
	if index < 0 {
		index = 0
	}
	if index > 255 {
		index = 255
	}

	if index < 16 {
		table := [16][3]int{
			{0, 0, 0}, {205, 0, 0}, {0, 205, 0}, {205, 205, 0},
			{0, 0, 238}, {205, 0, 205}, {0, 205, 205}, {229, 229, 229},
			{127, 127, 127}, {255, 0, 0}, {0, 255, 0}, {255, 255, 0},
			{92, 92, 255}, {255, 0, 255}, {0, 255, 255}, {255, 255, 255},
		}
		rgb := table[index]
		return rgb[0], rgb[1], rgb[2]
	}

	if index <= 231 {
		index -= 16
		red := (index / 36) * 51
		green := (index % 36 / 6) * 51
		blue := (index % 6) * 51
		return red, green, blue
	}

	gray := (index-232)*10 + 8
	return gray, gray, gray
}