Keynav moment

This commit is contained in:
Sasha Koshka 2023-01-11 22:30:14 -05:00
parent 80c0a6be71
commit 519e0b9c6b
9 changed files with 98 additions and 18 deletions

View File

@ -20,6 +20,7 @@ var buttonCodeTable = map[xproto.Keysym] tomo.Key {
0xFF7F: tomo.KeyNumLock, 0xFF7F: tomo.KeyNumLock,
0xFF08: tomo.KeyBackspace, 0xFF08: tomo.KeyBackspace,
0xFF09: tomo.KeyTab, 0xFF09: tomo.KeyTab,
0xFE20: tomo.KeyTab,
0xFF0D: tomo.KeyEnter, 0xFF0D: tomo.KeyEnter,
0xFF1B: tomo.KeyEscape, 0xFF1B: tomo.KeyEscape,

View File

@ -82,7 +82,7 @@ func (window *Window) handleKeyPress (
window.advanceSelectionInChild(direction) window.advanceSelectionInChild(direction)
} }
} else { } else {
window.child.Handle(event) window.child.Handle(keyDownEvent)
} }
} }

View File

@ -243,8 +243,9 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) {
} }
} }
func (window *Window) childSelectionRequestCallback () { func (window *Window) childSelectionRequestCallback () (granted bool) {
window.child.Handle(tomo.EventSelect { }) window.child.Handle(tomo.EventSelect { })
return true
} }
func (window *Window) pushRegion (region image.Rectangle) { func (window *Window) pushRegion (region image.Rectangle) {

View File

@ -78,7 +78,7 @@ func (element *Button) Handle (event tomo.Event) {
case tomo.EventKeyUp: case tomo.EventKeyUp:
keyDownEvent := event.(tomo.EventKeyUp) keyDownEvent := event.(tomo.EventKeyUp)
if keyDownEvent.Key == tomo.KeyEnter { if keyDownEvent.Key == tomo.KeyEnter && element.pressed {
element.pressed = false element.pressed = false
if element.core.HasImage() { if element.core.HasImage() {
element.draw() element.draw()
@ -91,9 +91,17 @@ func (element *Button) Handle (event tomo.Event) {
case tomo.EventSelect: case tomo.EventSelect:
element.core.SetSelected(true) element.core.SetSelected(true)
if element.core.HasImage() {
element.draw()
element.core.PushAll()
}
case tomo.EventDeselect: case tomo.EventDeselect:
element.core.SetSelected(false) element.core.SetSelected(false)
if element.core.HasImage() {
element.draw()
element.core.PushAll()
}
} }
return return
} }

View File

@ -12,8 +12,6 @@ type Container struct {
layout tomo.Layout layout tomo.Layout
children []tomo.LayoutEntry children []tomo.LayoutEntry
selectable bool
selected bool
drags [10]tomo.Element drags [10]tomo.Element
} }
@ -42,6 +40,16 @@ func (element *Container) Adopt (child tomo.Element, expand bool) {
SelectabilityChange: func (bool) { SelectabilityChange: func (bool) {
element.updateSelectable() element.updateSelectable()
}, },
SelectionRequest: func () (granted bool) {
if !child.Selectable() { return }
if element.core.Select() {
element.propogateToSelected(tomo.EventDeselect { })
child.Handle(tomo.EventSelect { })
return true
}
return
},
Draw: func (region tomo.Image) { Draw: func (region tomo.Image) {
element.drawChildRegion(child, region) element.drawChildRegion(child, region)
}, },
@ -189,27 +197,83 @@ func (element *Container) Handle (event tomo.Event) {
if !element.Selectable() { break } if !element.Selectable() { break }
element.core.SetSelected(true) element.core.SetSelected(true)
// select the first selectable element
for _, entry := range element.children {
if entry.Selectable() {
entry.Handle(event)
break
}
}
case tomo.EventDeselect: case tomo.EventDeselect:
element.core.SetSelected(false) element.core.SetSelected(false)
// TODO: propogate deselect event to all children who report element.propogateToSelected(event)
// themselves as selected.
default:
// other events are just directly sent to the selected child.
element.propogateToSelected(event)
} }
return return
} }
func (element *Container) propogateToSelected (event tomo.Event) {
for _, entry := range element.children {
if entry.Selected() {
entry.Handle(event)
}
}
}
func (element *Container) AdvanceSelection (direction int) (ok bool) { func (element *Container) AdvanceSelection (direction int) (ok bool) {
// TODO: if !element.Selectable() { return }
firstSelected := element.firstSelected()
if firstSelected < 0 {
for _, entry := range element.children {
if entry.Selectable() {
entry.Handle(tomo.EventSelect { })
return true
}
}
} else {
nextSelectable := -1
step := 1
if direction < 0 { step = - 1 }
for index := firstSelected + step;
index < len(element.children) && index > 0;
index += step {
if element.children[index].Selectable() {
nextSelectable = index
break
}
}
if nextSelectable > 0 {
element.children[firstSelected ].Handle(tomo.EventDeselect { })
element.children[nextSelectable].Handle(tomo.EventSelect { })
return true
}
}
return return
} }
func (element *Container) firstSelected () (index int) {
for currentIndex, entry := range element.children {
if entry.Selected() {
return currentIndex
}
}
return -1
}
func (element *Container) updateSelectable () { func (element *Container) updateSelectable () {
selectable := false selectable := false
for _, entry := range element.children { for _, entry := range element.children {
if entry.Selectable() { selectable = true } if entry.Selectable() { selectable = true }
} }
element.core.SetSelectable(selectable) element.core.SetSelectable(selectable)
if !selectable { element.selected = false }
} }
func (element *Container) updateMinimumSize () { func (element *Container) updateMinimumSize () {

View File

@ -81,8 +81,8 @@ func (control CoreControl) HasImage () (has bool) {
return return
} }
func (control CoreControl) Select () { func (control CoreControl) Select () (granted bool) {
control.core.hooks.RunSelectionRequest() return control.core.hooks.RunSelectionRequest()
} }
func (control CoreControl) SetSelected (selected bool) { func (control CoreControl) SetSelected (selected bool) {

View File

@ -20,7 +20,9 @@ func run () {
cancel := basic.NewButton("Cancel") cancel := basic.NewButton("Cancel")
cancel.SetEnabled(false) cancel.SetEnabled(false)
container.Adopt(cancel, false) container.Adopt(cancel, false)
container.Adopt(basic.NewButton("OK"), false) okButton := basic.NewButton("OK")
container.Adopt(okButton, false)
okButton.Select()
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

View File

@ -24,12 +24,14 @@ func run () {
container.Adopt(basic.NewLabel("Draw here:", false), false) container.Adopt(basic.NewLabel("Draw here:", false), false)
container.Adopt(basic.NewTest(), true) container.Adopt(basic.NewTest(), true)
container.Adopt(okButton, false) container.Adopt(okButton, false)
okButton.Select()
}) })
okButton.OnClick(tomo.Stop) okButton.OnClick(tomo.Stop)
container.Adopt(label, true) container.Adopt(label, true)
container.Adopt(button, false) container.Adopt(button, false)
container.Adopt(okButton, false) container.Adopt(okButton, false)
okButton.Select()
window.OnClose(tomo.Stop) window.OnClose(tomo.Stop)
window.Show() window.Show()

10
tomo.go
View File

@ -43,8 +43,9 @@ type ParentHooks struct {
// SelectionRequest is called when the child element element wants // SelectionRequest is called when the child element element wants
// itself to be selected. If the parent element chooses to grant the // itself to be selected. If the parent element chooses to grant the
// request, it must send the child element a selection event. // request, it must send the child element a selection event and return
SelectionRequest func () // true.
SelectionRequest func () (granted bool)
} }
// RunDraw runs the Draw hook if it is not nil. If it is nil, it does nothing. // RunDraw runs the Draw hook if it is not nil. If it is nil, it does nothing.
@ -64,10 +65,11 @@ func (hooks ParentHooks) RunMinimumSizeChange (width, height int) {
// RunSelectionRequest runs the SelectionRequest hook if it is not nil. If it is // RunSelectionRequest runs the SelectionRequest hook if it is not nil. If it is
// nil, it does nothing. // nil, it does nothing.
func (hooks ParentHooks) RunSelectionRequest () { func (hooks ParentHooks) RunSelectionRequest () (granted bool) {
if hooks.SelectionRequest != nil { if hooks.SelectionRequest != nil {
hooks.SelectionRequest() granted = hooks.SelectionRequest()
} }
return
} }
// RunSelectabilityChange runs the SelectionRequest hook if it is not nil. If it // RunSelectabilityChange runs the SelectionRequest hook if it is not nil. If it