diff --git a/backends/x/window.go b/backends/x/window.go index aeffb03..56110b6 100644 --- a/backends/x/window.go +++ b/backends/x/window.go @@ -261,6 +261,20 @@ func (window *Window) childSelectionRequestCallback () (granted bool) { return true } +func (window *Window) childSelectionMotionRequestCallback ( + direction tomo.SelectionDirection, +) ( + granted bool, +) { + if child, ok := window.child.(tomo.Selectable); ok { + if !child.HandleSelection(direction) { + child.HandleDeselection() + } + return true + } + return true +} + func (window *Window) pushRegion (region image.Rectangle) { if window.xCanvas == nil { panic("whoopsie!!!!!!!!!!!!!!") } image, ok := window.xCanvas.SubImage(region).(*xgraphics.Image) diff --git a/element.go b/element.go index 61a4b1f..bf6be5a 100644 --- a/element.go +++ b/element.go @@ -3,7 +3,8 @@ package tomo // ParentHooks is a struct that contains callbacks that let child elements send // information to their parent element without the child element knowing // anything about the parent element or containing any reference to it. When a -// parent element adopts a child element, it must set these callbacks. +// parent element adopts a child element, it must set these callbacks. They are +// allowed to be nil. type ParentHooks struct { // Draw is called when a part of the child element's surface is updated. // The updated region will be passed to the callback as a sub-image. @@ -20,6 +21,10 @@ type ParentHooks struct { // request, it must send the child element a selection event and return // true. SelectionRequest func () (granted bool) + + // SelectionMotionRequest is called when the child element wants the + // parent element to select the previous/next element in relation to it. + SelectionMotionRequest func (direction SelectionDirection) (granted bool) } // RunDraw runs the Draw hook if it is not nil. If it is nil, it does nothing. @@ -46,6 +51,19 @@ func (hooks ParentHooks) RunSelectionRequest () (granted bool) { return } +// RunSelectionMotionRequest runs the SelectionMotionRequest hook if it is not +// nil. If it is nil, it does nothing. +func (hooks ParentHooks) RunSelectionMotionRequest ( + direction SelectionDirection, +) ( + granted bool, +) { + if hooks.SelectionMotionRequest != nil { + granted = hooks.SelectionMotionRequest(direction) + } + return +} + // Element represents a basic on-screen object. type Element interface { // Element must implement the Canvas interface. Elements should start diff --git a/elements/basic/button.go b/elements/basic/button.go index bb03733..9bfe0ed 100644 --- a/elements/basic/button.go +++ b/elements/basic/button.go @@ -103,6 +103,7 @@ func (element *Button) HandleSelection ( ) ( accepted bool, ) { + direction = direction.Canon() if !element.enabled { return false } if element.selected && direction != tomo.SelectionDirectionNeutral { return false diff --git a/elements/basic/container.go b/elements/basic/container.go index e8d58c9..1597ac5 100644 --- a/elements/basic/container.go +++ b/elements/basic/container.go @@ -43,6 +43,9 @@ func (element *Container) SetLayout (layout tomo.Layout) { // whatever way is defined by the current layout. func (element *Container) Adopt (child tomo.Element, expand bool) { child.SetParentHooks (tomo.ParentHooks { + Draw: func (region tomo.Canvas) { + element.drawChildRegion(child, region) + }, MinimumSizeChange: func (int, int) { element.updateMinimumSize() }, @@ -51,8 +54,12 @@ func (element *Container) Adopt (child tomo.Element, expand bool) { if !selectable { return } return element.childSelectionRequestCallback(child) }, - Draw: func (region tomo.Canvas) { - element.drawChildRegion(child, region) + SelectionMotionRequest: func ( + direction tomo.SelectionDirection, + ) ( + granted bool, + ) { + return element.core.RequestSelectionMotion(direction) }, }) element.children = append (element.children, tomo.LayoutEntry { diff --git a/elements/core/core.go b/elements/core/core.go index 9f0fd3e..e88cacb 100644 --- a/elements/core/core.go +++ b/elements/core/core.go @@ -80,6 +80,18 @@ func (control CoreControl) RequestSelection () (granted bool) { return control.core.hooks.RunSelectionRequest() } +// RequestSelectionMotion requests that the element's parent deselect this +// element and select the one to the left or right of it, depending on the +// direction. If the requests was granted, it returns true. If it was denied, it +// returns false. +func (control CoreControl) RequestSelectionMotion ( + direction tomo.SelectionDirection, +) ( + granted bool, +) { + return control.core.hooks.RunSelectionMotionRequest(direction) +} + // HasImage returns true if the core has an allocated image buffer, and false if // it doesn't. func (control CoreControl) HasImage () (has bool) {