Added event callbacks to text box
This commit is contained in:
parent
48db645f9f
commit
36c5ed40e9
@ -7,6 +7,7 @@ import "git.tebibyte.media/sashakoshka/tomo/artist"
|
|||||||
import "git.tebibyte.media/sashakoshka/tomo/textmanip"
|
import "git.tebibyte.media/sashakoshka/tomo/textmanip"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
|
|
||||||
|
// TextBox is a single-line text input.
|
||||||
type TextBox struct {
|
type TextBox struct {
|
||||||
*core.Core
|
*core.Core
|
||||||
core core.CoreControl
|
core core.CoreControl
|
||||||
@ -19,9 +20,14 @@ type TextBox struct {
|
|||||||
text []rune
|
text []rune
|
||||||
placeholderDrawer artist.TextDrawer
|
placeholderDrawer artist.TextDrawer
|
||||||
valueDrawer artist.TextDrawer
|
valueDrawer artist.TextDrawer
|
||||||
|
onKeyDown func (tomo.Key, tomo.Modifiers, bool) (bool)
|
||||||
|
onChange func ()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTextBox (placeholder, text string) (element *TextBox) {
|
// NewTextBox creates a new text box with the specified placeholder text, and
|
||||||
|
// a value. When the value is empty, the placeholder will be displayed in gray
|
||||||
|
// text.
|
||||||
|
func NewTextBox (placeholder, value string) (element *TextBox) {
|
||||||
element = &TextBox { enabled: true }
|
element = &TextBox { enabled: true }
|
||||||
element.Core, element.core = core.NewCore(element)
|
element.Core, element.core = core.NewCore(element)
|
||||||
element.placeholderDrawer.SetFace(theme.FontFaceRegular())
|
element.placeholderDrawer.SetFace(theme.FontFaceRegular())
|
||||||
@ -29,7 +35,7 @@ func NewTextBox (placeholder, text string) (element *TextBox) {
|
|||||||
element.placeholder = placeholder
|
element.placeholder = placeholder
|
||||||
element.placeholderDrawer.SetText([]rune(placeholder))
|
element.placeholderDrawer.SetText([]rune(placeholder))
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.SetText(text)
|
element.SetValue(value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +58,10 @@ func (element *TextBox) HandleKeyDown (
|
|||||||
modifiers tomo.Modifiers,
|
modifiers tomo.Modifiers,
|
||||||
repeated bool,
|
repeated bool,
|
||||||
) {
|
) {
|
||||||
|
if element.onKeyDown != nil && element.onKeyDown(key, modifiers, repeated) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
altered := true
|
altered := true
|
||||||
switch {
|
switch {
|
||||||
case key == tomo.KeyBackspace:
|
case key == tomo.KeyBackspace:
|
||||||
@ -60,6 +70,7 @@ func (element *TextBox) HandleKeyDown (
|
|||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.cursor,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
|
element.runOnChange()
|
||||||
|
|
||||||
case key == tomo.KeyDelete:
|
case key == tomo.KeyDelete:
|
||||||
if len(element.text) < 1 { break }
|
if len(element.text) < 1 { break }
|
||||||
@ -67,6 +78,7 @@ func (element *TextBox) HandleKeyDown (
|
|||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.cursor,
|
||||||
modifiers.Control)
|
modifiers.Control)
|
||||||
|
element.runOnChange()
|
||||||
|
|
||||||
case key == tomo.KeyLeft:
|
case key == tomo.KeyLeft:
|
||||||
element.cursor = textmanip.MoveLeft (
|
element.cursor = textmanip.MoveLeft (
|
||||||
@ -85,6 +97,7 @@ func (element *TextBox) HandleKeyDown (
|
|||||||
element.text,
|
element.text,
|
||||||
element.cursor,
|
element.cursor,
|
||||||
rune(key))
|
rune(key))
|
||||||
|
element.runOnChange()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
altered = false
|
altered = false
|
||||||
@ -168,10 +181,11 @@ func (element *TextBox) updateMinimumSize () {
|
|||||||
theme.Padding() * 2)
|
theme.Padding() * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *TextBox) SetText (text string) {
|
func (element *TextBox) SetValue (text string) {
|
||||||
// if element.text == text { return }
|
// if element.text == text { return }
|
||||||
|
|
||||||
element.text = []rune(text)
|
element.text = []rune(text)
|
||||||
|
element.runOnChange()
|
||||||
element.valueDrawer.SetText(element.text)
|
element.valueDrawer.SetText(element.text)
|
||||||
if element.cursor > element.valueDrawer.Length() {
|
if element.cursor > element.valueDrawer.Length() {
|
||||||
element.cursor = element.valueDrawer.Length()
|
element.cursor = element.valueDrawer.Length()
|
||||||
@ -187,6 +201,30 @@ func (element *TextBox) Value () (value string) {
|
|||||||
return string(element.text)
|
return string(element.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (element *TextBox) Filled () (filled bool) {
|
||||||
|
return len(element.text) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *TextBox) OnKeyDown (
|
||||||
|
callback func (
|
||||||
|
key tomo.Key, modifiers tomo.Modifiers, repeated bool,
|
||||||
|
) (
|
||||||
|
handled bool,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
element.onKeyDown = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *TextBox) OnChange (callback func ()) {
|
||||||
|
element.onChange = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
func (element *TextBox) runOnChange () {
|
||||||
|
if element.onChange != nil {
|
||||||
|
element.onChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (element *TextBox) draw () {
|
func (element *TextBox) draw () {
|
||||||
bounds := element.core.Bounds()
|
bounds := element.core.Bounds()
|
||||||
|
|
||||||
|
@ -12,24 +12,39 @@ func main () {
|
|||||||
|
|
||||||
func run () {
|
func run () {
|
||||||
window, _ := tomo.NewWindow(2, 2)
|
window, _ := tomo.NewWindow(2, 2)
|
||||||
window.SetTitle("Approaching")
|
window.SetTitle("Enter Details")
|
||||||
container := basic.NewContainer(layouts.Vertical { true, true })
|
container := basic.NewContainer(layouts.Vertical { true, true })
|
||||||
window.Adopt(container)
|
window.Adopt(container)
|
||||||
|
|
||||||
|
// create inputs
|
||||||
firstName := basic.NewTextBox("First name", "")
|
firstName := basic.NewTextBox("First name", "")
|
||||||
lastName := basic.NewTextBox("Last name", "")
|
lastName := basic.NewTextBox("Last name", "")
|
||||||
fingerLength := basic.NewTextBox("Length of fingers", "")
|
fingerLength := basic.NewTextBox("Length of fingers", "")
|
||||||
button := basic.NewButton("Ok")
|
button := basic.NewButton("Ok")
|
||||||
|
|
||||||
lastName.SetEnabled(false)
|
button.SetEnabled(false)
|
||||||
button.OnClick (func () {
|
button.OnClick (func () {
|
||||||
|
// create a dialog displaying the results
|
||||||
popups.NewDialog (
|
popups.NewDialog (
|
||||||
popups.DialogKindInfo,
|
popups.DialogKindInfo,
|
||||||
"Profile",
|
"Profile",
|
||||||
firstName.Value() + " [REDACTED]'s fingers\n" +
|
firstName.Value() + " " + lastName.Value() +
|
||||||
"measure in at " + fingerLength.Value() + " feet.")
|
"'s fingers\nmeasure in at " + fingerLength.Value() +
|
||||||
|
" feet.")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// enable the Ok button if all three inputs have text in them
|
||||||
|
check := func () {
|
||||||
|
button.SetEnabled (
|
||||||
|
firstName.Filled() &&
|
||||||
|
lastName.Filled() &&
|
||||||
|
fingerLength.Filled())
|
||||||
|
}
|
||||||
|
firstName.OnChange(check)
|
||||||
|
lastName.OnChange(check)
|
||||||
|
fingerLength.OnChange(check)
|
||||||
|
|
||||||
|
// add elements to container
|
||||||
container.Adopt(basic.NewLabel("Choose your words carefully.", false), true)
|
container.Adopt(basic.NewLabel("Choose your words carefully.", false), true)
|
||||||
container.Adopt(firstName, false)
|
container.Adopt(firstName, false)
|
||||||
container.Adopt(lastName, false)
|
container.Adopt(lastName, false)
|
||||||
@ -37,8 +52,6 @@ func run () {
|
|||||||
container.Adopt(basic.NewSpacer(true), false)
|
container.Adopt(basic.NewSpacer(true), false)
|
||||||
container.Adopt(button, false)
|
container.Adopt(button, false)
|
||||||
|
|
||||||
firstName.Select()
|
|
||||||
|
|
||||||
window.OnClose(tomo.Stop)
|
window.OnClose(tomo.Stop)
|
||||||
window.Show()
|
window.Show()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user