Worked Propagator into basic.Container
This commit is contained in:
parent
56e11ae1de
commit
165d0835bf
@ -14,11 +14,11 @@ import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
// them in a layout.
|
||||
type Container struct {
|
||||
*core.Core
|
||||
*core.Propagator
|
||||
core core.CoreControl
|
||||
|
||||
layout layouts.Layout
|
||||
children []layouts.LayoutEntry
|
||||
drags [10]elements.MouseTarget
|
||||
warping bool
|
||||
focused bool
|
||||
focusable bool
|
||||
@ -27,9 +27,9 @@ type Container struct {
|
||||
config config.Wrapped
|
||||
theme theme.Wrapped
|
||||
|
||||
onFlexibleHeightChange func ()
|
||||
onFocusRequest func () (granted bool)
|
||||
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
||||
onFlexibleHeightChange func ()
|
||||
}
|
||||
|
||||
// NewContainer creates a new container.
|
||||
@ -241,11 +241,7 @@ func (element *Container) redoAll () {
|
||||
func (element *Container) SetTheme (new theme.Theme) {
|
||||
if new == element.theme.Theme { return }
|
||||
element.theme.Theme = new
|
||||
for _, child := range element.children {
|
||||
if child0, ok := child.Element.(elements.Themeable); ok {
|
||||
child0.SetTheme(element.theme.Theme)
|
||||
}
|
||||
}
|
||||
element.Propagator.SetTheme(new)
|
||||
element.updateMinimumSize()
|
||||
element.redoAll()
|
||||
}
|
||||
@ -253,188 +249,34 @@ func (element *Container) SetTheme (new theme.Theme) {
|
||||
// SetConfig sets the element's configuration.
|
||||
func (element *Container) SetConfig (new config.Config) {
|
||||
if new == element.config.Config { return }
|
||||
element.config.Config = new
|
||||
for _, child := range element.children {
|
||||
if child0, ok := child.Element.(elements.Configurable); ok {
|
||||
child0.SetConfig(element.config)
|
||||
}
|
||||
}
|
||||
element.Propagator.SetConfig(new)
|
||||
element.updateMinimumSize()
|
||||
element.redoAll()
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseDown (x, y int, button input.Button) {
|
||||
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(elements.MouseTarget)
|
||||
if !handlesMouse { return }
|
||||
element.drags[button] = child
|
||||
child.HandleMouseDown(x, y, button)
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseUp (x, y int, button input.Button) {
|
||||
child := element.drags[button]
|
||||
if child == nil { return }
|
||||
element.drags[button] = nil
|
||||
child.HandleMouseUp(x, y, button)
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseMove (x, y int) {
|
||||
for _, child := range element.drags {
|
||||
if child == nil { continue }
|
||||
child.HandleMouseMove(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) HandleMouseScroll (x, y int, deltaX, deltaY float64) {
|
||||
child, handlesMouse := element.ChildAt(image.Pt(x, y)).(elements.MouseTarget)
|
||||
if !handlesMouse { return }
|
||||
child.HandleMouseScroll(x, y, deltaX, deltaY)
|
||||
}
|
||||
|
||||
func (element *Container) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||
element.forFocused (func (child elements.Focusable) bool {
|
||||
child0, handlesKeyboard := child.(elements.KeyboardTarget)
|
||||
if handlesKeyboard {
|
||||
child0.HandleKeyDown(key, modifiers)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) HandleKeyUp (key input.Key, modifiers input.Modifiers) {
|
||||
element.forFocused (func (child elements.Focusable) bool {
|
||||
child0, handlesKeyboard := child.(elements.KeyboardTarget)
|
||||
if handlesKeyboard {
|
||||
child0.HandleKeyUp(key, modifiers)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) FlexibleHeightFor (width int) (height int) {
|
||||
margin := element.theme.Margin(theme.PatternBackground)
|
||||
// TODO: have layouts take in x and y margins
|
||||
margin := element.theme.Margin(theme.PatternBackground)
|
||||
padding := element.theme.Padding(theme.PatternBackground)
|
||||
// TODO: have layouts take in entire margins/padding
|
||||
return element.layout.FlexibleHeightFor (
|
||||
element.children,
|
||||
margin.X, width)
|
||||
margin.X, padding.Horizontal(), width)
|
||||
}
|
||||
|
||||
func (element *Container) OnFlexibleHeightChange (callback func ()) {
|
||||
element.onFlexibleHeightChange = callback
|
||||
}
|
||||
|
||||
func (element *Container) Focused () (focused bool) {
|
||||
return element.focused
|
||||
}
|
||||
|
||||
func (element *Container) Focus () {
|
||||
if element.onFocusRequest != nil {
|
||||
element.onFocusRequest()
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Container) HandleFocus (direction input.KeynavDirection) (ok bool) {
|
||||
if !element.focusable { return false }
|
||||
direction = direction.Canon()
|
||||
|
||||
firstFocused := element.firstFocused()
|
||||
if firstFocused < 0 {
|
||||
// no element is currently focused, so we need to focus either
|
||||
// the first or last focusable element depending on the
|
||||
// direction.
|
||||
switch direction {
|
||||
case input.KeynavDirectionNeutral, input.KeynavDirectionForward:
|
||||
// if we recieve a neutral or forward direction, focus
|
||||
// the first focusable element.
|
||||
return element.focusFirstFocusableElement(direction)
|
||||
|
||||
case input.KeynavDirectionBackward:
|
||||
// if we recieve a backward direction, focus the last
|
||||
// focusable element.
|
||||
return element.focusLastFocusableElement(direction)
|
||||
}
|
||||
} else {
|
||||
// an element is currently focused, so we need to move the
|
||||
// focus in the specified direction
|
||||
firstFocusedChild :=
|
||||
element.children[firstFocused].Element.(elements.Focusable)
|
||||
|
||||
// before we move the focus, the currently focused child
|
||||
// may also be able to move its focus. if the child is able
|
||||
// to do that, we will let it and not move ours.
|
||||
if firstFocusedChild.HandleFocus(direction) {
|
||||
return true
|
||||
}
|
||||
|
||||
// find the previous/next focusable element relative to the
|
||||
// currently focused element, if it exists.
|
||||
for index := firstFocused + int(direction);
|
||||
index < len(element.children) && index >= 0;
|
||||
index += int(direction) {
|
||||
|
||||
child, focusable :=
|
||||
element.children[index].
|
||||
Element.(elements.Focusable)
|
||||
if focusable && child.HandleFocus(direction) {
|
||||
// we have found one, so we now actually move
|
||||
// the focus.
|
||||
firstFocusedChild.HandleUnfocus()
|
||||
element.focused = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (element *Container) focusFirstFocusableElement (
|
||||
direction input.KeynavDirection,
|
||||
) (
|
||||
ok bool,
|
||||
) {
|
||||
element.forFocusable (func (child elements.Focusable) bool {
|
||||
if child.HandleFocus(direction) {
|
||||
element.focused = true
|
||||
ok = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Container) focusLastFocusableElement (
|
||||
direction input.KeynavDirection,
|
||||
) (
|
||||
ok bool,
|
||||
) {
|
||||
element.forFocusableBackward (func (child elements.Focusable) bool {
|
||||
if child.HandleFocus(direction) {
|
||||
element.focused = true
|
||||
ok = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Container) HandleUnfocus () {
|
||||
element.focused = false
|
||||
element.forFocused (func (child elements.Focusable) bool {
|
||||
child.HandleUnfocus()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (element *Container) OnFocusRequest (callback func () (granted bool)) {
|
||||
element.onFocusRequest = callback
|
||||
element.Propagator.OnFocusRequest(callback)
|
||||
}
|
||||
|
||||
func (element *Container) OnFocusMotionRequest (
|
||||
callback func (direction input.KeynavDirection) (granted bool),
|
||||
) {
|
||||
element.onFocusMotionRequest = callback
|
||||
element.Propagator.OnFocusMotionRequest(callback)
|
||||
}
|
||||
|
||||
func (element *Container) forFocused (callback func (child elements.Focusable) bool) {
|
||||
@ -517,20 +359,24 @@ func (element *Container) childFocusRequestCallback (
|
||||
}
|
||||
|
||||
func (element *Container) updateMinimumSize () {
|
||||
margin := element.theme.Margin(theme.PatternBackground)
|
||||
// TODO: have layouts take in x and y margins
|
||||
width, height := element.layout.MinimumSize(element.children, margin.X)
|
||||
margin := element.theme.Margin(theme.PatternBackground)
|
||||
padding := element.theme.Padding(theme.PatternBackground)
|
||||
// TODO: have layouts take in entire margins/padding
|
||||
width, height := element.layout.MinimumSize (
|
||||
element.children, margin.X, padding.Horizontal())
|
||||
if element.flexible {
|
||||
height = element.layout.FlexibleHeightFor (
|
||||
element.children,
|
||||
margin.X, width)
|
||||
element.children, margin.X,
|
||||
padding.Horizontal(), width)
|
||||
}
|
||||
element.core.SetMinimumSize(width, height)
|
||||
}
|
||||
|
||||
func (element *Container) doLayout () {
|
||||
margin := element.theme.Margin(theme.PatternBackground)
|
||||
// TODO: have layouts take in x and y margins
|
||||
padding := element.theme.Padding(theme.PatternBackground)
|
||||
// TODO: have layouts take in entire margins/padding
|
||||
element.layout.Arrange (
|
||||
element.children, margin.X, element.Bounds())
|
||||
element.children, margin.X,
|
||||
padding.Horizontal(), element.Bounds())
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ type Propagator struct {
|
||||
focused bool
|
||||
|
||||
onFocusRequest func () (granted bool)
|
||||
onFocusMotionRequest func (input.KeynavDirection) (granted bool)
|
||||
}
|
||||
|
||||
// NewPropagator creates a new event propagator that uses the specified parent
|
||||
@ -137,9 +136,7 @@ func (propagator *Propagator) OnFocusRequest (callback func () (granted bool)) {
|
||||
// was granted, and false if it was not.
|
||||
func (propagator *Propagator) OnFocusMotionRequest (
|
||||
callback func (direction input.KeynavDirection) (granted bool),
|
||||
) {
|
||||
propagator.onFocusMotionRequest = callback
|
||||
}
|
||||
) { }
|
||||
|
||||
// HandleKeyDown propogates the keyboard event to the currently selected child.
|
||||
func (propagator *Propagator) HandleKeyDown (key input.Key, modifiers input.Modifiers) {
|
||||
|
Reference in New Issue
Block a user