commit 17006ee

Lauri Tirkkonen  ·  2024-11-14 12:14:42 +0000 UTC
parent 207463e
extended color scheme: use rgb colors

Also detect background color & vary lightness.
3 files changed,  +89, -64
M app.go
M app.go
+8, -8
 1@@ -532,6 +532,8 @@ func (app *App) handleUIEvent(ev interface{}) bool {
 2 		app.win.SetFocused(true)
 3 	case vaxis.FocusOut:
 4 		app.win.SetFocused(false)
 5+	case vaxis.ColorThemeUpdate:
 6+		app.win.SetColorTheme(ev.Mode)
 7 	case *ui.NotifyEvent:
 8 		app.win.JumpBufferNetwork(ev.NetID, ev.Buffer)
 9 	case statusLine:
10@@ -2049,12 +2051,12 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
11 	if isAction || isNotice {
12 		head = "*"
13 	} else {
14-		headColor = ui.IdentColor(app.cfg.Colors.Nicks, head, isFromSelf)
15+		headColor = app.win.IdentColor(app.cfg.Colors.Nicks, head, isFromSelf)
16 	}
17 
18 	var body ui.StyledStringBuilder
19 	if isNotice {
20-		color := ui.IdentColor(app.cfg.Colors.Nicks, ev.User, isFromSelf)
21+		color := app.win.IdentColor(app.cfg.Colors.Nicks, ev.User, isFromSelf)
22 		body.SetStyle(vaxis.Style{
23 			Foreground: color,
24 		})
25@@ -2063,7 +2065,7 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
26 		body.WriteString(": ")
27 		body.WriteStyledString(ui.IRCString(content))
28 	} else if isAction {
29-		color := ui.IdentColor(app.cfg.Colors.Nicks, ev.User, isFromSelf)
30+		color := app.win.IdentColor(app.cfg.Colors.Nicks, ev.User, isFromSelf)
31 		body.SetStyle(vaxis.Style{
32 			Foreground: color,
33 		})
34@@ -2250,15 +2252,13 @@ func (app *App) updatePrompt() {
35 	if buffer == "" || command {
36 		prompt = ui.Styled(">", vaxis.Style{
37 			Foreground: app.cfg.Colors.Prompt,
38-		},
39-		)
40+		})
41 	} else if s == nil {
42 		prompt = ui.Styled("<offline>", vaxis.Style{
43 			Foreground: ui.ColorRed,
44-		},
45-		)
46+		})
47 	} else {
48-		prompt = ui.IdentString(app.cfg.Colors.Nicks, s.Nick(), true)
49+		prompt = app.win.IdentString(app.cfg.Colors.Nicks, s.Nick(), true)
50 	}
51 	app.win.SetPrompt(prompt)
52 }
+64, -55
  1@@ -2,6 +2,7 @@ package ui
  2 
  3 import (
  4 	"hash/fnv"
  5+	"math"
  6 
  7 	"git.sr.ht/~rockorager/vaxis"
  8 )
  9@@ -23,74 +24,82 @@ const (
 10 	ColorSchemeFixed
 11 )
 12 
 13-var colors = map[ColorSchemeType][]vaxis.Color{
 14+var baseColors = []vaxis.Color{
 15 	// base 16 colors, excluding grayscale colors.
 16-	ColorSchemeBase: {
 17-		vaxis.IndexColor(1),
 18-		vaxis.IndexColor(2),
 19-		vaxis.IndexColor(3),
 20-		vaxis.IndexColor(4),
 21-		vaxis.IndexColor(5),
 22-		vaxis.IndexColor(6),
 23-		vaxis.IndexColor(7),
 24-		vaxis.IndexColor(9),
 25-		vaxis.IndexColor(10),
 26-		vaxis.IndexColor(11),
 27-		vaxis.IndexColor(12),
 28-		vaxis.IndexColor(13),
 29-		vaxis.IndexColor(14),
 30-	},
 31-	// all XTerm extended colors with HSL saturation=1, light=0.5
 32-	ColorSchemeExtended: {
 33-		vaxis.IndexColor(196), // HSL hue: 0°
 34-		vaxis.IndexColor(202), // HSL hue: 22°
 35-		vaxis.IndexColor(208), // HSL hue: 32°
 36-		vaxis.IndexColor(214), // HSL hue: 41°
 37-		vaxis.IndexColor(220), // HSL hue: 51°
 38-		vaxis.IndexColor(226), // HSL hue: 60°
 39-		vaxis.IndexColor(190), // HSL hue: 69°
 40-		vaxis.IndexColor(154), // HSL hue: 79°
 41-		vaxis.IndexColor(118), // HSL hue: 88°
 42-		vaxis.IndexColor(82),  // HSL hue: 98°
 43-		vaxis.IndexColor(46),  // HSL hue: 120°
 44-		vaxis.IndexColor(47),  // HSL hue: 142°
 45-		vaxis.IndexColor(48),  // HSL hue: 152°
 46-		vaxis.IndexColor(49),  // HSL hue: 161°
 47-		vaxis.IndexColor(50),  // HSL hue: 171°
 48-		vaxis.IndexColor(51),  // HSL hue: 180°
 49-		vaxis.IndexColor(45),  // HSL hue: 189°
 50-		vaxis.IndexColor(39),  // HSL hue: 199°
 51-		vaxis.IndexColor(33),  // HSL hue: 208°
 52-		vaxis.IndexColor(27),  // HSL hue: 218°
 53-		vaxis.IndexColor(21),  // HSL hue: 240°
 54-		vaxis.IndexColor(57),  // HSL hue: 262°
 55-		vaxis.IndexColor(93),  // HSL hue: 272°
 56-		vaxis.IndexColor(129), // HSL hue: 281°
 57-		vaxis.IndexColor(165), // HSL hue: 291°
 58-		vaxis.IndexColor(201), // HSL hue: 300°
 59-		vaxis.IndexColor(200), // HSL hue: 309°
 60-		vaxis.IndexColor(199), // HSL hue: 319°
 61-		vaxis.IndexColor(198), // HSL hue: 328°
 62-		vaxis.IndexColor(197), // HSL hue: 338°
 63-	},
 64+	vaxis.IndexColor(1),
 65+	vaxis.IndexColor(2),
 66+	vaxis.IndexColor(3),
 67+	vaxis.IndexColor(4),
 68+	vaxis.IndexColor(5),
 69+	vaxis.IndexColor(6),
 70+	vaxis.IndexColor(7),
 71+	vaxis.IndexColor(9),
 72+	vaxis.IndexColor(10),
 73+	vaxis.IndexColor(11),
 74+	vaxis.IndexColor(12),
 75+	vaxis.IndexColor(13),
 76+	vaxis.IndexColor(14),
 77 }
 78 
 79-func IdentColor(scheme ColorScheme, ident string, self bool) vaxis.Color {
 80+func hslToRGB(hue, sat, light float64) (r, g, b uint8) {
 81+	var r1, g1, b1 float64
 82+	chroma := (1 - math.Abs(2*light-1)) * sat
 83+	h6 := hue / 60
 84+	x := chroma * (1 - math.Abs(math.Mod(h6, 2)-1))
 85+	if h6 < 1 {
 86+		r1, g1, b1 = chroma, x, 0
 87+	} else if h6 < 2 {
 88+		r1, g1, b1 = x, chroma, 0
 89+	} else if h6 < 3 {
 90+		r1, g1, b1 = 0, chroma, x
 91+	} else if h6 < 4 {
 92+		r1, g1, b1 = 0, x, chroma
 93+	} else if h6 < 5 {
 94+		r1, g1, b1 = x, 0, chroma
 95+	} else {
 96+		r1, g1, b1 = chroma, 0, x
 97+	}
 98+	m := light - chroma/2
 99+	r = uint8(math.MaxUint8 * (r1 + m))
100+	g = uint8(math.MaxUint8 * (g1 + m))
101+	b = uint8(math.MaxUint8 * (b1 + m))
102+	return r, g, b
103+}
104+
105+func (ui *UI) IdentColor(scheme ColorScheme, ident string, self bool) vaxis.Color {
106 	h := fnv.New32()
107 	_, _ = h.Write([]byte(ident))
108-	if scheme.Type == ColorSchemeFixed {
109+	switch scheme.Type {
110+	case ColorSchemeFixed:
111 		if self {
112 			return scheme.Self
113 		} else {
114 			return scheme.Others
115 		}
116+	case ColorSchemeBase:
117+		return baseColors[int(h.Sum32()%uint32(len(baseColors)))]
118+	case ColorSchemeExtended:
119+		sum := h.Sum32()
120+		lo := int(sum & 0xFFFF)
121+		hi := int((sum >> 16) & 0xFFFF)
122+		hue := float64(lo) / float64(math.MaxUint16) * 360
123+		sat := 1.0
124+		var lightMin, lightMax float64
125+		switch ui.colorThemeMode {
126+		case vaxis.DarkMode:
127+			lightMin, lightMax = 0.5, 0.7
128+		case vaxis.LightMode:
129+			lightMin, lightMax = 0.2, 0.4
130+		}
131+		light := lightMin + float64(hi)/float64(math.MaxUint16)*(lightMax-lightMin)
132+		return vaxis.RGBColor(hslToRGB(hue, sat, light))
133+	default:
134+		panic("invalid color scheme setting")
135 	}
136-	c := colors[scheme.Type]
137-	return c[int(h.Sum32()%uint32(len(c)))]
138 }
139 
140-func IdentString(scheme ColorScheme, ident string, self bool) StyledString {
141-	color := IdentColor(scheme, ident, self)
142+func (ui *UI) IdentString(scheme ColorScheme, ident string, self bool) StyledString {
143+	color := ui.IdentColor(scheme, ident, self)
144 	style := vaxis.Style{
145 		Foreground: color,
146 	}
+17, -1
 1@@ -75,6 +75,8 @@ type UI struct {
 2 	image vaxis.Image
 3 
 4 	mouseLinks bool
 5+
 6+	colorThemeMode vaxis.ColorThemeMode
 7 }
 8 
 9 func New(config Config) (ui *UI, err error) {
10@@ -102,6 +104,16 @@ func New(config Config) (ui *UI, err error) {
11 		window: vx.Window(),
12 	}
13 
14+	if bg := ui.vx.QueryBackground().Params(); len(bg) == 3 {
15+		if (int(bg[0])+int(bg[1])+int(bg[2]))/3 > 127 {
16+			ui.colorThemeMode = vaxis.LightMode
17+		} else {
18+			ui.colorThemeMode = vaxis.DarkMode
19+		}
20+	} else {
21+		ui.colorThemeMode = vaxis.DarkMode
22+	}
23+
24 	ui.vx.SetTitle("senpai")
25 	ui.vx.SetAppID("senpai")
26 
27@@ -518,6 +530,10 @@ func (ui *UI) SetMouseShape(shape vaxis.MouseShape) {
28 	ui.vx.SetMouseShape(shape)
29 }
30 
31+func (ui *UI) SetColorTheme(mode vaxis.ColorThemeMode) {
32+	ui.colorThemeMode = mode
33+}
34+
35 // InputContent result must not be modified.
36 func (ui *UI) InputContent() []rune {
37 	return ui.e.Content()
38@@ -894,7 +910,7 @@ func (ui *UI) drawVerticalMemberList(vx *Vaxis, x0, y0, width, height int, b *bu
39 				Attribute:  attr,
40 			})
41 		} else {
42-			color := IdentColor(ui.config.Colors.Nicks, m.Name.Name, m.Self)
43+			color := ui.IdentColor(ui.config.Colors.Nicks, m.Name.Name, m.Self)
44 			name = Styled(nameText, vaxis.Style{
45 				Foreground: color,
46 				Attribute:  attr,