Add clickable tabs

This introduces a new interface `Clickable`. I'd imagine this would be
implemented for most widgets eventually and would allow for programs run
in the terminal to also have their mouse events forwarded to them.

For the tabs it was relatively simple to check that the position of the
click is within the boxes for the tabs. For other components I'd imagine
that some state representing their currently drawn bounding box would be
useful.
This commit is contained in:
Jeffas 2019-07-11 23:15:15 +01:00 committed by Drew DeVault
parent 4c7f81d20d
commit 3b09c07e7a
4 changed files with 38 additions and 0 deletions

View file

@ -40,3 +40,10 @@ type Container interface {
// recurse into your grandchildren).
Children() []Drawable
}
// A drawable that can be clicked
type Clickable interface {
Drawable
MouseEvent(event tcell.Event)
}

View file

@ -126,6 +126,19 @@ func (tabs *Tabs) removeHistory(index int) {
tabs.history = newHist
}
func (tabs *Tabs) MouseEvent(event tcell.Event) {
switch event := event.(type) {
case *tcell.EventMouse:
if event.Buttons()&tcell.Button1 != 0 {
x, y := event.Position()
selectedTab, ok := tabs.TabStrip.Clicked(x, y)
if ok {
tabs.Select(selectedTab)
}
}
}
}
// TODO: Color repository
func (strip *TabStrip) Draw(ctx *Context) {
x := 0
@ -151,6 +164,21 @@ func (strip *TabStrip) OnInvalidate(onInvalidate func(d Drawable)) {
strip.onInvalidateStrip = onInvalidate
}
func (strip *TabStrip) Clicked(mouseX int, mouseY int) (int, bool) {
x := 0
if mouseY == 0 {
for i, tab := range strip.Tabs {
trunc := runewidth.Truncate(tab.Name, 32, "…")
length := len(trunc) + 2
if x <= mouseX && mouseX < x+length {
return i, true
}
x += length
}
}
return 0, false
}
func (content *TabContent) Children() []Drawable {
children := make([]Drawable, len(content.Tabs))
for i, tab := range content.Tabs {

View file

@ -32,6 +32,7 @@ func Initialize(conf *config.AercConfig,
screen.Clear()
screen.HideCursor()
screen.EnableMouse()
width, height := screen.Size()

View file

@ -190,6 +190,8 @@ func (aerc *Aerc) Event(event tcell.Event) bool {
}
return false
}
case *tcell.EventMouse:
aerc.tabs.MouseEvent(event)
}
return false
}