Add method for controlling focus

This commit is contained in:
Trevor Slocum 2023-10-21 15:30:09 -07:00
parent 416660e4c9
commit 5a3db3e94e
7 changed files with 68 additions and 16 deletions

10
box.go
View file

@ -10,6 +10,8 @@ type Box struct {
children []Widget
focus bool
sync.Mutex
}
@ -31,6 +33,14 @@ func (b *Box) SetRect(r image.Rectangle) {
b.rect = r
}
func (b *Box) SetFocus(focus bool) {
b.focus = focus
}
func (b *Box) Focus() bool {
return b.focus
}
func (b *Box) Children() []Widget {
b.Lock()
defer b.Unlock()

View file

@ -34,16 +34,13 @@ func main() {
w := etk.NewWindow()
// Input demo.
buffer := etk.NewText("Press enter to append input below to this buffer.")
onselected := func(text string) (handled bool) {
buffer.Write([]byte("\nInput: " + text))
return true
}
input := etk.NewInput(">", "", onselected)
{
buffer := etk.NewText("Press enter to append input below to this buffer.")
onselected := func(text string) (handled bool) {
buffer.Write([]byte("\nInput: " + text))
return true
}
input := etk.NewInput(">", "", onselected)
inputDemo := etk.NewFlex()
inputDemo.SetVertical(true)
@ -85,6 +82,7 @@ func main() {
}
etk.SetRoot(w)
etk.SetFocus(input)
err := ebiten.RunGame(g)
if err != nil {

30
game.go
View file

@ -17,6 +17,8 @@ var (
lastX, lastY = -math.MaxInt, -math.MaxInt
touchIDs []ebiten.TouchID
focusedWidget Widget
)
func SetRoot(w Widget) {
@ -24,6 +26,17 @@ func SetRoot(w Widget) {
if lastWidth != 0 || lastHeight != 0 {
root.SetRect(image.Rect(0, 0, lastWidth, lastHeight))
}
SetFocus(root)
}
func SetFocus(w Widget) {
if focusedWidget != nil {
focusedWidget.SetFocus(false)
}
focusedWidget = w
if w != nil {
w.SetFocus(true)
}
}
func Layout(outsideWidth, outsideHeight int) {
@ -88,6 +101,21 @@ func Update() error {
return err
}
func getWidgetAt(w Widget, cursor image.Point) Widget {
if !cursor.In(w.Rect()) {
return nil
}
for _, child := range w.Children() {
if cursor.In(child.Rect()) {
result := getWidgetAt(child, cursor)
if result != nil {
return result
}
}
}
return w
}
func update(w Widget, cursor image.Point, pressed bool, clicked bool, mouseHandled bool, keyboardHandled bool) (bool, bool, error) {
var err error
children := w.Children()
@ -105,7 +133,7 @@ func update(w Widget, cursor image.Point, pressed bool, clicked bool, mouseHandl
return false, false, fmt.Errorf("failed to handle widget mouse input: %s", err)
}
}
if !keyboardHandled {
if !keyboardHandled && w == focusedWidget {
keyboardHandled, err = w.HandleKeyboard()
if err != nil {
return false, false, fmt.Errorf("failed to handle widget keyboard input: %s", err)

View file

@ -3,14 +3,14 @@ package etk
import (
"image"
"github.com/hajimehoshi/ebiten/v2"
"code.rocketnine.space/tslocum/messeji"
"github.com/hajimehoshi/ebiten/v2"
)
type Input struct {
*Box
Field *messeji.InputField
Field *messeji.InputField
Cursor string
}
func NewInput(prefix string, text string, onSelected func(text string) (handled bool)) *Input {
@ -30,8 +30,9 @@ func NewInput(prefix string, text string, onSelected func(text string) (handled
})
return &Input{
Box: NewBox(),
Field: i,
Box: NewBox(),
Field: i,
Cursor: "_",
}
}
@ -55,6 +56,16 @@ func (i *Input) SetRect(r image.Rectangle) {
i.Field.SetRect(r)
}
func (i *Input) SetFocus(focus bool) {
i.focus = focus
cursor := i.Cursor
if !focus {
cursor = ""
}
i.Field.SetSuffix(cursor)
}
func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
return false, nil
}

View file

@ -27,6 +27,10 @@ func NewText(text string) *Text {
}
}
func (t *Text) SetFocus(focus bool) {
// Do nothing.
}
func (t *Text) Children() []Widget {
t.Lock()
defer t.Unlock()

View file

@ -9,6 +9,7 @@ import (
type Widget interface {
Rect() image.Rectangle
SetRect(r image.Rectangle)
SetFocus(focus bool)
HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error)
HandleKeyboard() (handled bool, err error)
Draw(screen *ebiten.Image) error

View file

@ -66,7 +66,7 @@ func (w *Window) AddChildWithLabel(wgt Widget, label string) {
if label != "" {
w.hasLabel = true
}
w.childrenUpdated()
}