1package widgets
2
3import (
4	"github.com/ambientsound/visp/api"
5	"github.com/ambientsound/visp/log"
6	"github.com/ambientsound/visp/multibar"
7	"github.com/ambientsound/visp/style"
8	"github.com/gdamore/tcell/v2"
9	"github.com/gdamore/tcell/v2/views"
10)
11
12type widgets struct {
13	layout   *views.BoxLayout
14	Topbar   *Topbar
15	multibar *Multibar
16	table    *Table
17}
18
19type Application struct {
20	api     api.API
21	events  chan tcell.Event
22	screen  tcell.Screen
23	Widgets widgets
24	style.Styled
25}
26
27var _ tcell.EventHandler = &Application{}
28
29var _ api.UI = &Application{}
30
31func NewApplication(a api.API) (*Application, error) {
32	screen, err := tcell.NewScreen()
33	if err != nil {
34		return nil, err
35	}
36
37	err = screen.Init()
38	if err != nil {
39		return nil, err
40	}
41
42	screen.Clear()
43	screen.Show()
44
45	return &Application{
46		api:    a,
47		events: make(chan tcell.Event, 1024),
48		screen: screen,
49	}, nil
50}
51
52func (app *Application) Init() {
53	app.Widgets.Topbar = NewTopbar(app.api)
54	app.Widgets.table = NewTable(app.api)
55	app.Widgets.multibar = NewMultibarWidget(app.api)
56	app.Resize()
57}
58
59func (app *Application) Resize() {
60	app.Widgets.layout = views.NewBoxLayout(views.Vertical)
61	app.Widgets.layout.AddWidget(app.Widgets.Topbar, 0)
62	app.Widgets.layout.AddWidget(app.Widgets.table, 1)
63	app.Widgets.layout.AddWidget(app.Widgets.multibar, 0)
64	app.Widgets.layout.SetView(app.screen)
65}
66
67func (app *Application) HandleEvent(ev tcell.Event) bool {
68	switch e := ev.(type) {
69	case *tcell.EventResize:
70		cols, rows := e.Size()
71		log.Debugf("Terminal resize: %dx%d", cols, rows)
72		app.screen.Sync()
73		app.Resize()
74		return true
75	case *tcell.EventKey:
76		return false
77	default:
78		log.Debugf("unrecognized input event: %T %+v", e, e)
79		app.Widgets.layout.HandleEvent(ev)
80		return false
81	}
82}
83
84func (app *Application) Draw() {
85	app.Widgets.layout.Draw()
86	app.updateCursor()
87	app.screen.Show()
88}
89
90func (app *Application) Poll() {
91	for {
92		app.events <- app.screen.PollEvent()
93	}
94}
95
96func (app *Application) Events() <-chan tcell.Event {
97	return app.events
98}
99
100func (app *Application) Finish() {
101	app.screen.Fini()
102}
103
104func (app *Application) Refresh() {
105	app.screen.Sync()
106}
107
108func (app *Application) TableWidget() api.TableWidget {
109	return app.Widgets.table
110}
111
112func (app *Application) updateCursor() {
113	switch app.api.Multibar().Mode() {
114	case multibar.ModeInput, multibar.ModeSearch:
115		_, ymax := app.screen.Size()
116		x := app.api.Multibar().Cursor() + 1
117		app.screen.ShowCursor(x, ymax-1)
118	default:
119		app.screen.HideCursor()
120	}
121}
122