132 lines
3.2 KiB
Go
132 lines
3.2 KiB
Go
package messeji
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
"golang.org/x/image/font"
|
|
)
|
|
|
|
// InputField is a text input field. Call Update and Draw when your Game's
|
|
// Update and Draw methods are called.
|
|
//
|
|
// Note: A position and size must be set via SetRect before the field will appear.
|
|
// Keyboard events are not handled by default, and may be enabled via SetHandleKeyboard.
|
|
type InputField struct {
|
|
*TextField
|
|
|
|
// changedFunc is a function which is called when the text buffer is changed.
|
|
// The function may return false to skip adding the rune to the text buffer.
|
|
changedFunc func(r rune) (accept bool)
|
|
|
|
// selectedFunc is a function which is called when the enter key is pressed. The
|
|
// function may return true to clear the text buffer.
|
|
selectedFunc func() (accept bool)
|
|
|
|
// readBuffer is where incoming runes are stored before being added to the input buffer.
|
|
readBuffer []rune
|
|
|
|
sync.Mutex
|
|
}
|
|
|
|
// NewInputField returns a new InputField. See type documentation for more info.
|
|
func NewInputField(face font.Face) *InputField {
|
|
f := &InputField{
|
|
TextField: NewTextField(face),
|
|
}
|
|
f.TextField.suffix = "_"
|
|
return f
|
|
}
|
|
|
|
// SetHandleKeyboard sets a flag controlling whether keyboard input should be handled
|
|
// by the field. This can be used to facilitate focus changes between multiple inputs.
|
|
func (f *InputField) SetHandleKeyboard(handle bool) {
|
|
f.Lock()
|
|
defer f.Unlock()
|
|
|
|
f.handleKeyboard = handle
|
|
|
|
// Show or hide cursor.
|
|
if f.handleKeyboard {
|
|
f.TextField.suffix = "_"
|
|
} else {
|
|
f.TextField.suffix = ""
|
|
}
|
|
}
|
|
|
|
// SetChangedFunc sets a handler which is called when the text buffer is changed.
|
|
// The handler may return true to add the rune to the text buffer.
|
|
func (f *InputField) SetChangedFunc(changedFunc func(r rune) (accept bool)) {
|
|
f.changedFunc = changedFunc
|
|
}
|
|
|
|
// SetSelectedFunc sets a handler which is called when the enter key is pressed.
|
|
// Providing a nil function value will remove the existing handler (if set).
|
|
// The handler may return true to clear the text buffer.
|
|
func (f *InputField) SetSelectedFunc(selectedFunc func() (accept bool)) {
|
|
f.selectedFunc = selectedFunc
|
|
}
|
|
|
|
// Update updates the input field. This function should be called when
|
|
// Game.Update is called.
|
|
func (f *InputField) Update() error {
|
|
f.Lock()
|
|
defer f.Unlock()
|
|
|
|
if !f.visible || rectIsZero(f.r) {
|
|
return nil
|
|
}
|
|
|
|
if !f.handleKeyboard {
|
|
return f.TextField.Update()
|
|
}
|
|
|
|
var redraw bool
|
|
|
|
f.readBuffer = ebiten.AppendInputChars(f.readBuffer[:0])
|
|
for _, r := range f.readBuffer {
|
|
if f.changedFunc != nil {
|
|
f.Unlock()
|
|
accept := f.changedFunc(r)
|
|
f.Lock()
|
|
|
|
if !accept {
|
|
continue
|
|
}
|
|
}
|
|
|
|
f.buffer += string(r)
|
|
redraw = true
|
|
}
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) && len(f.buffer) > 0 {
|
|
f.buffer = f.buffer[:len(f.buffer)-1]
|
|
redraw = true
|
|
}
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) || inpututil.IsKeyJustPressed(ebiten.KeyKPEnter) {
|
|
if f.selectedFunc != nil {
|
|
f.Unlock()
|
|
accept := f.selectedFunc()
|
|
f.Lock()
|
|
|
|
// Clear input buffer.
|
|
if accept {
|
|
f.buffer = ""
|
|
redraw = true
|
|
}
|
|
} else if !f.singleLine {
|
|
// Append newline.
|
|
f.buffer += "\n"
|
|
redraw = true
|
|
}
|
|
}
|
|
|
|
if redraw {
|
|
f.bufferModified()
|
|
}
|
|
|
|
return f.TextField.Update()
|
|
}
|