diff --git a/backends/x/entity.go b/backends/x/entity.go index 3f3af47..c15a797 100644 --- a/backends/x/entity.go +++ b/backends/x/entity.go @@ -30,8 +30,10 @@ func (backend *Backend) NewEntity (owner tomo.Element) tomo.Entity { func (ent *entity) unlink () { ent.propagate (func (child *entity) bool { + if child.window != nil { + delete(ent.window.system.drawingInvalid, child) + } child.window = nil - delete(ent.window.system.drawingInvalid, child) return true }) @@ -61,17 +63,19 @@ func (ent *entity) setWindow (window *window) { }) } -func (entity *entity) propagate (callback func (*entity) bool) { +func (entity *entity) propagate (callback func (*entity) bool) bool { for _, child := range entity.children { - if !callback(child) { break } - child.propagate(callback) + if !child.propagate(callback) { + return false + } } + return callback(entity) } func (entity *entity) childAt (point image.Point) *entity { for _, child := range entity.children { if point.In(child.bounds) { - return child + return child.childAt(point) } } return entity @@ -190,12 +194,7 @@ func (entity *entity) Focused () bool { func (entity *entity) Focus () { if entity.window == nil { return } - previous := entity.window.focused - entity.window.focused = entity - if previous != nil { - previous.element.(tomo.Focusable).HandleFocusChange() - } - entity.element.(tomo.Focusable).HandleFocusChange() + entity.window.system.focus(entity) } func (entity *entity) FocusNext () { diff --git a/backends/x/system.go b/backends/x/system.go index a9c7187..50b598f 100644 --- a/backends/x/system.go +++ b/backends/x/system.go @@ -62,12 +62,55 @@ func (system *system) SetConfig (config tomo.Config) { }) } +func (system *system) focus (entity *entity) { + previous := system.focused + system.focused = entity + if previous != nil { + previous.element.(tomo.Focusable).HandleFocusChange() + } + if entity != nil { + entity.element.(tomo.Focusable).HandleFocusChange() + } +} + func (system *system) focusNext () { - // TODO + found := system.focused == nil + focused := false + system.propagate (func (entity *entity) bool { + if found { + // looking for the next element to select + child, ok := entity.element.(tomo.Focusable) + if ok && child.Enabled() { + // found it + entity.Focus() + focused = true + return false + } + } else { + // looking for the current focused element + if entity == system.focused { + // found it + found = true + } + } + return true + }) + + if !focused { system.focus(nil) } } func (system *system) focusPrevious () { - // TODO + var behind *entity + system.propagate (func (entity *entity) bool { + if entity == system.focused { + return false + } + + child, ok := entity.element.(tomo.Focusable) + if ok && child.Enabled() { behind = entity } + return true + }) + system.focus(behind) } func (system *system) propagate (callback func (*entity) bool) { diff --git a/element.go b/element.go index 3b4a132..e91f57f 100644 --- a/element.go +++ b/element.go @@ -37,6 +37,9 @@ type Container interface { type Focusable interface { Element + // Enabled returns whether or not the element can currently accept focus. + Enabled () bool + // HandleFocusChange is called when the element is focused or unfocused. HandleFocusChange () }