You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.2 KiB
131 lines
3.2 KiB
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() |
|
}
|
|
|