Add Widget.Cursor

Resolves #9.
This commit is contained in:
Trevor Slocum 2024-09-11 22:05:01 -07:00
parent 99a40d1dad
commit 7b35245a5a
12 changed files with 82 additions and 17 deletions

6
box.go
View file

@ -82,6 +82,12 @@ func (b *Box) SetVisible(visible bool) {
b.visible = visible
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (b *Box) Cursor() ebiten.CursorShapeType {
return -1
}
// HandleKeyboard is called when a keyboard event occurs.
func (b *Box) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
return false, nil

View file

@ -158,6 +158,12 @@ func (b *Button) SetVertical(h Alignment) {
b.field.SetVertical(messeji.Alignment(h))
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (b *Button) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapePointer
}
// HandleKeyboard is called when a keyboard event occurs.
func (b *Button) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
return false, nil

View file

@ -87,6 +87,12 @@ func (c *Checkbox) SetSelected(selected bool) {
c.updateImage()
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (c *Checkbox) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapePointer
}
// HandleKeyboard is called when a keyboard event occurs.
func (c *Checkbox) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
return false, nil

29
game.go
View file

@ -48,6 +48,8 @@ var (
pressedWidget Widget
cursorShape ebiten.CursorShapeType
lastBackspaceRepeat time.Time
keyBuffer []ebiten.Key
@ -271,17 +273,19 @@ func Update() error {
pressedWidget = nil
}
_, err := update(root, cursor, pressed, clicked, false)
mouseHandled, err := update(root, cursor, pressed, clicked, false)
if err != nil {
return fmt.Errorf("failed to handle widget mouse input: %s", err)
} else if !mouseHandled && cursorShape != ebiten.CursorShapeDefault {
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
cursorShape = ebiten.CursorShapeDefault
}
// Handle keyboard input.
if focusedWidget == nil {
return nil
}
if ebiten.IsKeyPressed(ebiten.KeyBackspace) {
} else if ebiten.IsKeyPressed(ebiten.KeyBackspace) {
if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) {
lastBackspaceRepeat = time.Now().Add(backspaceRepeatWait)
} else if time.Since(lastBackspaceRepeat) >= backspaceRepeatTime {
@ -380,13 +384,18 @@ func update(w Widget, cursor image.Point, pressed bool, clicked bool, mouseHandl
mouseHandled, err = w.HandleMouse(cursor, pressed, clicked)
if err != nil {
return false, fmt.Errorf("failed to handle widget mouse input: %s", err)
}
if mouseHandled && !clicked && pressedWidget != nil && (!pressed || pressedWidget != w) {
pressedWidget = nil
}
if clicked && mouseHandled {
SetFocus(w)
pressedWidget = w
} else if mouseHandled {
if clicked {
SetFocus(w)
pressedWidget = w
} else if pressedWidget != nil && (!pressed || pressedWidget != w) {
pressedWidget = nil
}
shape := w.Cursor()
if shape != -1 && shape != cursorShape {
ebiten.SetCursorShape(shape)
cursorShape = shape
}
}
}
return mouseHandled, nil

8
go.mod
View file

@ -1,15 +1,17 @@
module code.rocket9labs.com/tslocum/etk
go 1.18
go 1.22.0
toolchain go1.23.0
require (
github.com/hajimehoshi/ebiten/v2 v2.7.8
github.com/hajimehoshi/ebiten/v2 v2.7.9
github.com/llgcode/draw2d v0.0.0-20240627062922-0ed1ff131195
golang.org/x/image v0.20.0
)
require (
github.com/ebitengine/gomobile v0.0.0-20240825043811-96c531f5bd83 // indirect
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 // indirect
github.com/ebitengine/hideconsole v1.0.0 // indirect
github.com/ebitengine/purego v0.7.1 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect

10
go.sum
View file

@ -1,5 +1,5 @@
github.com/ebitengine/gomobile v0.0.0-20240825043811-96c531f5bd83 h1:yA0CtFKYZI/db1snCOInRS0Z18QGZU6aBYkqUT0H6RI=
github.com/ebitengine/gomobile v0.0.0-20240825043811-96c531f5bd83/go.mod h1:n2NbB/F4d9wOXFzC7FT1ipERidmYWC5I4YNOYRs5N7I=
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325 h1:Gk1XUEttOk0/hb6Tq3WkmutWa0ZLhNn/6fc6XZpM7tM=
github.com/ebitengine/gomobile v0.0.0-20240911145611-4856209ac325/go.mod h1:ulhSQcbPioQrallSuIzF8l1NKQoD7xmMZc5NxzibUMY=
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A=
github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
@ -7,13 +7,15 @@ github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/hajimehoshi/bitmapfont/v3 v3.0.0 h1:r2+6gYK38nfztS/et50gHAswb9hXgxXECYgE8Nczmi4=
github.com/hajimehoshi/ebiten/v2 v2.7.8 h1:QrlvF2byCzMuDsbxFReJkOCbM3O2z1H/NKQaGcA8PKk=
github.com/hajimehoshi/ebiten/v2 v2.7.8/go.mod h1:Ulbq5xDmdx47P24EJ+Mb31Zps7vQq+guieG9mghQUaA=
github.com/hajimehoshi/bitmapfont/v3 v3.0.0/go.mod h1:+CxxG+uMmgU4mI2poq944i3uZ6UYFfAkj9V6WqmuvZA=
github.com/hajimehoshi/ebiten/v2 v2.7.9 h1:DYH/usAa9dMHcGkBIIEApJsVqDekrJBxYHmsBuly8Iw=
github.com/hajimehoshi/ebiten/v2 v2.7.9/go.mod h1:Ulbq5xDmdx47P24EJ+Mb31Zps7vQq+guieG9mghQUaA=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/llgcode/draw2d v0.0.0-20240627062922-0ed1ff131195 h1:Vdz2cBh5Fw2MYHWi3ED2PraDQaWEUhNCr1XFHrP4N5A=
github.com/llgcode/draw2d v0.0.0-20240627062922-0ed1ff131195/go.mod h1:1Vk0LDW6jG5cGc2D9RQUxHaE0vYhTvIwSo9mOL6K4/U=
github.com/llgcode/ps v0.0.0-20210114104736-f4b0c5d1e02e h1:ZAvbj5hI/G/EbAYAcj4yCXUNiFKefEhH0qfImDDD0/8=
github.com/llgcode/ps v0.0.0-20210114104736-f4b0c5d1e02e/go.mod h1:1l8ky+Ew27CMX29uG+a2hNOKpeNYEQjjtiALiBlFQbY=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=

View file

@ -224,6 +224,12 @@ func (i *Input) SetMask(r rune) {
i.field.SetMask(r)
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (i *Input) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapeText
}
// Write writes to the text buffer.
func (i *Input) Write(p []byte) (n int, err error) {
return i.field.Write(p)

View file

@ -87,6 +87,12 @@ func (k *Keyboard) SetScheduleFrameFunc(f func()) {
k.k.SetScheduleFrameFunc(f)
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (k *Keyboard) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapePointer
}
// HandleMouse is called when a mouse event occurs.
func (k *Keyboard) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
k.Lock()

View file

@ -323,6 +323,12 @@ func (l *List) clampOffset(offset int) int {
return offset
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (l *List) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapeDefault
}
// HandleKeyboard is called when a keyboard event occurs.
func (l *List) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
l.Lock()

View file

@ -163,6 +163,12 @@ func (s *Select) _setMenuVisible(visible bool) {
}
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (s *Select) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapePointer
}
// HandleKeyboard is called when a keyboard event occurs.
func (s *Select) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
return false, nil

View file

@ -125,6 +125,12 @@ func (t *Text) SetVertical(h Alignment) {
t.field.SetVertical(messeji.Alignment(h))
}
// Cursor returns the cursor shape shown when a mouse cursor hovers over the
// widget, or -1 to let widgets beneath determine the cursor shape.
func (t *Text) Cursor() ebiten.CursorShapeType {
return ebiten.CursorShapeDefault
}
// Write writes to the text buffer.
func (t *Text) Write(p []byte) (n int, err error) {
t.Lock()

View file

@ -34,6 +34,10 @@ type Widget interface {
// SetVisible sets the visibility of the widget.
SetVisible(visible bool)
// Cursor returns the cursor shape shown when a mouse cursor hovers over
// the widget, or -1 to let widgets beneath determine the cursor shape.
Cursor() ebiten.CursorShapeType
// HandleKeyboard is called when a keyboard event occurs.
HandleKeyboard(ebiten.Key, rune) (handled bool, err error)