1package main
2
3import (
4	"github.com/nsf/termbox-go"
5)
6
7var curCol = 0
8var curRune = 0
9var backbuf []termbox.Cell
10var bbw, bbh int
11
12var runes = []rune{' ', '░', '▒', '▓', '█'}
13var colors = []termbox.Attribute{
14	termbox.ColorBlack,
15	termbox.ColorRed,
16	termbox.ColorGreen,
17	termbox.ColorYellow,
18	termbox.ColorBlue,
19	termbox.ColorMagenta,
20	termbox.ColorCyan,
21	termbox.ColorWhite,
22}
23
24type attrFunc func(int) (rune, termbox.Attribute, termbox.Attribute)
25
26func updateAndDrawButtons(current *int, x, y int, mx, my int, n int, attrf attrFunc) {
27	lx, ly := x, y
28	for i := 0; i < n; i++ {
29		if lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1 {
30			*current = i
31		}
32		r, fg, bg := attrf(i)
33		termbox.SetCell(lx+0, ly+0, r, fg, bg)
34		termbox.SetCell(lx+1, ly+0, r, fg, bg)
35		termbox.SetCell(lx+2, ly+0, r, fg, bg)
36		termbox.SetCell(lx+3, ly+0, r, fg, bg)
37		termbox.SetCell(lx+0, ly+1, r, fg, bg)
38		termbox.SetCell(lx+1, ly+1, r, fg, bg)
39		termbox.SetCell(lx+2, ly+1, r, fg, bg)
40		termbox.SetCell(lx+3, ly+1, r, fg, bg)
41		lx += 4
42	}
43	lx, ly = x, y
44	for i := 0; i < n; i++ {
45		if *current == i {
46			fg := termbox.ColorRed | termbox.AttrBold
47			bg := termbox.ColorDefault
48			termbox.SetCell(lx+0, ly+2, '^', fg, bg)
49			termbox.SetCell(lx+1, ly+2, '^', fg, bg)
50			termbox.SetCell(lx+2, ly+2, '^', fg, bg)
51			termbox.SetCell(lx+3, ly+2, '^', fg, bg)
52		}
53		lx += 4
54	}
55}
56
57func update_and_redraw_all(mx, my int) {
58	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
59	if mx != -1 && my != -1 {
60		backbuf[bbw*my+mx] = termbox.Cell{Ch: runes[curRune], Fg: colors[curCol]}
61	}
62	copy(termbox.CellBuffer(), backbuf)
63	_, h := termbox.Size()
64	updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
65		return runes[i], termbox.ColorDefault, termbox.ColorDefault
66	})
67	updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), func(i int) (rune, termbox.Attribute, termbox.Attribute) {
68		return ' ', termbox.ColorDefault, colors[i]
69	})
70	termbox.Flush()
71}
72
73func reallocBackBuffer(w, h int) {
74	bbw, bbh = w, h
75	backbuf = make([]termbox.Cell, w*h)
76}
77
78func main() {
79	err := termbox.Init()
80	if err != nil {
81		panic(err)
82	}
83	defer termbox.Close()
84	termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
85	reallocBackBuffer(termbox.Size())
86	update_and_redraw_all(-1, -1)
87
88mainloop:
89	for {
90		mx, my := -1, -1
91		switch ev := termbox.PollEvent(); ev.Type {
92		case termbox.EventKey:
93			if ev.Key == termbox.KeyEsc {
94				break mainloop
95			}
96		case termbox.EventMouse:
97			if ev.Key == termbox.MouseLeft {
98				mx, my = ev.MouseX, ev.MouseY
99			}
100		case termbox.EventResize:
101			reallocBackBuffer(ev.Width, ev.Height)
102		}
103		update_and_redraw_all(mx, my)
104	}
105}
106