List now has keynav support

This commit is contained in:
Sasha Koshka 2023-04-20 15:09:51 -04:00
parent 53f78cb0e7
commit 399dda75bd

View File

@ -10,12 +10,14 @@ import "git.tebibyte.media/sashakoshka/tomo/default/theme"
type listEntity interface { type listEntity interface {
tomo.ContainerEntity tomo.ContainerEntity
tomo.ScrollableEntity tomo.ScrollableEntity
tomo.FocusableEntity
} }
type List struct { type List struct {
container container
entity listEntity entity listEntity
enabled bool
scroll image.Point scroll image.Point
contentBounds image.Rectangle contentBounds image.Rectangle
selected int selected int
@ -29,7 +31,10 @@ type List struct {
} }
func NewList (children ...tomo.Element) (element *List) { func NewList (children ...tomo.Element) (element *List) {
element = &List { selected: -1 } element = &List {
selected: -1,
enabled: true,
}
element.theme.Case = tomo.C("tomo", "list") element.theme.Case = tomo.C("tomo", "list")
element.entity = tomo.NewEntity(element).(listEntity) element.entity = tomo.NewEntity(element).(listEntity)
element.container.entity = element.entity element.container.entity = element.entity
@ -45,7 +50,7 @@ func (element *List) Draw (destination canvas.Canvas) {
rocks[index] = element.entity.Child(index).Entity().Bounds() rocks[index] = element.entity.Child(index).Entity().Bounds()
} }
pattern := element.theme.Pattern(tomo.PatternSunken, tomo.State { }) pattern := element.theme.Pattern(tomo.PatternSunken, element.state())
artist.DrawShatter(destination, pattern, element.entity.Bounds(), rocks...) artist.DrawShatter(destination, pattern, element.entity.Bounds(), rocks...)
} }
@ -87,18 +92,52 @@ func (element *List) Layout () {
} }
} }
func (element *List) Enabled () bool {
return element.enabled
}
func (element *List) SetEnabled (enabled bool) {
if element.enabled == enabled { return }
element.enabled = enabled
element.entity.Invalidate()
}
func (element *List) Focus () {
element.entity.Focus()
}
func (element *List) HandleFocusChange () {
element.entity.Invalidate()
}
func (element *List) HandleMouseDown (
position image.Point,
button input.Button,
modifiers input.Modifiers,
) {
if !element.enabled { return }
element.Focus()
element.selectNone()
}
func (element *List) HandleMouseUp (
position image.Point,
button input.Button,
modifiers input.Modifiers,
) { }
func (element *List) HandleChildMouseDown ( func (element *List) HandleChildMouseDown (
position image.Point, position image.Point,
button input.Button, button input.Button,
modifiers input.Modifiers, modifiers input.Modifiers,
child tomo.Element, child tomo.Element,
) { ) {
if !element.enabled { return }
element.Focus()
if child, ok := child.(tomo.Selectable); ok { if child, ok := child.(tomo.Selectable); ok {
index := element.entity.IndexOf(child) index := element.entity.IndexOf(child)
if element.selected == index { return } if element.selected == index { return }
if element.selected >= 0 { element.selectNone()
element.entity.SelectChild(element.selected, false)
}
element.selected = index element.selected = index
element.entity.SelectChild(index, true) element.entity.SelectChild(index, true)
} }
@ -117,6 +156,24 @@ func (element *List) HandleChildFlexibleHeightChange (child tomo.Flexible) {
element.entity.InvalidateLayout() element.entity.InvalidateLayout()
} }
func (element *List) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
if !element.Enabled() { return }
index := -1
switch key {
case input.KeyUp, input.KeyLeft:
index = element.selected - 1
case input.KeyDown, input.KeyRight:
index = element.selected + 1
}
if index >= 0 && index < element.entity.CountChildren() {
element.selectNone()
element.selected = index
element.entity.SelectChild(index, true)
}
}
func (element *List) HandleKeyUp(key input.Key, modifiers input.Modifiers) { }
func (element *List) DrawBackground (destination canvas.Canvas) { func (element *List) DrawBackground (destination canvas.Canvas) {
element.entity.DrawBackground(destination) element.entity.DrawBackground(destination)
} }
@ -191,6 +248,23 @@ func (element *List) ScrollAxes () (horizontal, vertical bool) {
return false, true return false, true
} }
func (element *List) selectNone () {
if element.selected >= 0 {
element.entity.SelectChild(element.selected, false)
}
}
func (element *List) setSelected (child tomo.Element) {
}
func (element *List) state () tomo.State {
return tomo.State {
Focused: element.entity.Focused(),
Disabled: !element.enabled,
}
}
func (element *List) maxScrollHeight () (height int) { func (element *List) maxScrollHeight () (height int) {
padding := element.theme.Padding(tomo.PatternSunken) padding := element.theme.Padding(tomo.PatternSunken)
viewportHeight := element.entity.Bounds().Dy() - padding.Vertical() viewportHeight := element.entity.Bounds().Dy() - padding.Vertical()