clui/edit_osx.go

146 lines
3.3 KiB
Go

// +build darwin
package clui
import (
xs "github.com/huandu/xstrings"
term "github.com/nsf/termbox-go"
"time"
)
const charInvervalMs = 20
/*
EditField is a single-line text edit contol. Edit field consumes some keyboard
events when it is active: all printable charaters; Delete, BackSpace, Home,
End, left and right arrows; Ctrl+R to clear EditField.
Edit text can be limited. By default a user can enter text of any length.
Use SetMaxWidth to limit the maximum text length. If the text is longer than
maximun then the text is automatically truncated.
EditField calls onChage in case of its text is changed. Event field Msg contains the new text
*/
type EditField struct {
BaseControl
// cursor position in edit text
cursorPos int
// the number of the first displayed text character - it is used in case of text is longer than edit width
offset int
readonly bool
maxWidth int
showStars bool
onChange func(Event)
onKeyPress func(term.Key, rune) bool
lastEvent time.Time
}
// NewEditField creates a new EditField control
// view - is a View that manages the control
// parent - is container that keeps the control. The same View can be a view and a parent at the same time.
// width - is minimal width of the control.
// text - text to edit.
// scale - the way of scaling the control when the parent is resized. Use DoNotScale constant if the
// control should keep its original size.
func CreateEditField(parent Control, width int, text string, scale int) *EditField {
e := new(EditField)
e.BaseControl = NewBaseControl()
e.onChange = nil
e.SetTitle(text)
e.SetEnabled(true)
if width == AutoSize {
width = xs.Len(text) + 1
}
e.SetSize(width, 1)
e.cursorPos = xs.Len(text)
e.offset = 0
e.parent = parent
e.readonly = false
e.SetScale(scale)
e.lastEvent = time.Now()
e.SetConstraints(width, 1)
e.end()
if parent != nil {
parent.AddChild(e)
}
return e
}
/*
ProcessEvent processes all events come from the control parent. If a control
processes an event it should return true. If the method returns false it means
that the control do not want or cannot process the event and the caller sends
the event to the control parent
*/
func (e *EditField) ProcessEvent(event Event) bool {
if !e.Active() || !e.Enabled() {
return false
}
if event.Type == EventActivate && event.X == 0 {
term.HideCursor()
}
if event.Type == EventMouse && event.Key == term.MouseLeft {
e.lastEvent = time.Now()
}
if event.Type == EventKey && event.Key != term.KeyTab {
if e.onKeyPress != nil {
res := e.onKeyPress(event.Key, event.Ch)
if res {
return true
}
}
switch event.Key {
case term.KeyEnter:
return false
case term.KeySpace:
e.insertRune(' ')
return true
case term.KeyBackspace, term.KeyBackspace2:
e.backspace()
return true
case term.KeyDelete:
e.del()
return true
case term.KeyArrowLeft:
e.charLeft()
return true
case term.KeyHome:
e.home()
return true
case term.KeyEnd:
e.end()
return true
case term.KeyCtrlR:
if !e.readonly {
e.Clear()
}
return true
case term.KeyArrowRight:
e.charRight()
return true
default:
if event.Ch != 0 {
elapsed := time.Now().Sub(e.lastEvent)
if elapsed > time.Duration(charInvervalMs)*time.Millisecond {
e.insertRune(event.Ch)
e.lastEvent = time.Now()
}
return true
}
}
return false
}
return false
}