|
|
|
@ -76,6 +76,9 @@ type InputField struct {
|
|
|
|
|
// The background color of the selected ListItem.
|
|
|
|
|
autocompleteListSelectedBackgroundColor tcell.Color
|
|
|
|
|
|
|
|
|
|
// The text color of the suggestion.
|
|
|
|
|
autocompleteSuggestionTextColor tcell.Color
|
|
|
|
|
|
|
|
|
|
// The screen width of the label area. A value of 0 means use the width of
|
|
|
|
|
// the label text.
|
|
|
|
|
labelWidth int
|
|
|
|
@ -100,6 +103,9 @@ type InputField struct {
|
|
|
|
|
// nil, the list's main texts represent the current autocomplete entries.
|
|
|
|
|
autocompleteList *List
|
|
|
|
|
|
|
|
|
|
// The suggested completion of the current autocomplete ListItem.
|
|
|
|
|
autocompleteListSuggestion string
|
|
|
|
|
|
|
|
|
|
// An optional function which may reject the last character that was entered.
|
|
|
|
|
accept func(text string, ch rune) bool
|
|
|
|
|
|
|
|
|
@ -140,6 +146,7 @@ func NewInputField() *InputField {
|
|
|
|
|
autocompleteListBackgroundColor: Styles.MoreContrastBackgroundColor,
|
|
|
|
|
autocompleteListSelectedTextColor: Styles.PrimitiveBackgroundColor,
|
|
|
|
|
autocompleteListSelectedBackgroundColor: Styles.PrimaryTextColor,
|
|
|
|
|
autocompleteSuggestionTextColor: Styles.ContrastPrimaryTextColor,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -308,6 +315,12 @@ func (i *InputField) SetAutocompleteListSelectedBackgroundColor(color tcell.Colo
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetAutocompleteSuggestionColor sets the text color of the autocomplete suggestion in the input field.
|
|
|
|
|
func (i *InputField) SetAutocompleteSuggestionTextColor(color tcell.Color) *InputField {
|
|
|
|
|
i.autocompleteSuggestionTextColor = color
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetFormAttributes sets attributes shared by all form items.
|
|
|
|
|
func (i *InputField) SetFormAttributes(labelWidth int, bgColor, labelColor, labelColorFocused, fieldTextColor, fieldTextColorFocused, fieldBgColor, fieldBgColorFocused tcell.Color) FormItem {
|
|
|
|
|
i.Lock()
|
|
|
|
@ -405,6 +418,7 @@ func (i *InputField) Autocomplete() *InputField {
|
|
|
|
|
// No entries, no list.
|
|
|
|
|
i.Lock()
|
|
|
|
|
i.autocompleteList = nil
|
|
|
|
|
i.autocompleteListSuggestion = ""
|
|
|
|
|
i.Unlock()
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
@ -415,6 +429,7 @@ func (i *InputField) Autocomplete() *InputField {
|
|
|
|
|
if i.autocompleteList == nil {
|
|
|
|
|
i.autocompleteList = NewList()
|
|
|
|
|
i.autocompleteList.
|
|
|
|
|
SetChangedFunc(i.autocompleteChanged).
|
|
|
|
|
ShowSecondaryText(false).
|
|
|
|
|
SetMainTextColor(i.autocompleteListTextColor).
|
|
|
|
|
SetSelectedTextColor(i.autocompleteListSelectedTextColor).
|
|
|
|
@ -443,6 +458,16 @@ func (i *InputField) Autocomplete() *InputField {
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// autocompleteChanged gets called when another item in the
|
|
|
|
|
// autocomplete list has been selected.
|
|
|
|
|
func (i *InputField) autocompleteChanged(_ int, item *ListItem) {
|
|
|
|
|
if referenceVal, isString := item.reference.(string); isString {
|
|
|
|
|
i.autocompleteListSuggestion = referenceVal[len(i.text):]
|
|
|
|
|
} else {
|
|
|
|
|
i.autocompleteListSuggestion = item.mainText[len(i.text):]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetAcceptanceFunc sets a handler which may reject the last character that was
|
|
|
|
|
// entered (by returning false).
|
|
|
|
|
//
|
|
|
|
@ -554,9 +579,11 @@ func (i *InputField) Draw(screen tcell.Screen) {
|
|
|
|
|
if i.maskCharacter > 0 {
|
|
|
|
|
text = strings.Repeat(string(i.maskCharacter), utf8.RuneCountInString(i.text))
|
|
|
|
|
}
|
|
|
|
|
drawnText := ""
|
|
|
|
|
if fieldWidth >= stringWidth(text) {
|
|
|
|
|
// We have enough space for the full text.
|
|
|
|
|
Print(screen, Escape(text), x, y, fieldWidth, AlignLeft, fieldTextColor)
|
|
|
|
|
drawnText = Escape(text)
|
|
|
|
|
Print(screen, drawnText, x, y, fieldWidth, AlignLeft, fieldTextColor)
|
|
|
|
|
i.offset = 0
|
|
|
|
|
iterateString(text, func(main rune, comb []rune, textPos, textWidth, screenPos, screenWidth int) bool {
|
|
|
|
|
if textPos >= i.cursorPos {
|
|
|
|
@ -594,7 +621,12 @@ func (i *InputField) Draw(screen tcell.Screen) {
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
})
|
|
|
|
|
Print(screen, Escape(text[i.offset:]), x, y, fieldWidth, AlignLeft, fieldTextColor)
|
|
|
|
|
drawnText = Escape(text[i.offset:])
|
|
|
|
|
Print(screen, drawnText, x, y, fieldWidth, AlignLeft, fieldTextColor)
|
|
|
|
|
}
|
|
|
|
|
// Draw suggestion
|
|
|
|
|
if i.maskCharacter == 0 && i.autocompleteListSuggestion != "" {
|
|
|
|
|
Print(screen, i.autocompleteListSuggestion, x+stringWidth(drawnText), y, fieldWidth-stringWidth(drawnText), AlignLeft, i.autocompleteSuggestionTextColor)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -767,14 +799,31 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|
|
|
|
home()
|
|
|
|
|
case tcell.KeyEnd, tcell.KeyCtrlE:
|
|
|
|
|
end()
|
|
|
|
|
case tcell.KeyEnter, tcell.KeyEscape: // We might be done.
|
|
|
|
|
case tcell.KeyEnter: // We might be done.
|
|
|
|
|
if i.autocompleteList != nil {
|
|
|
|
|
i.autocompleteList = nil
|
|
|
|
|
currentItem := i.autocompleteList.GetCurrentItem()
|
|
|
|
|
i.Unlock()
|
|
|
|
|
if referenceVal, isString := currentItem.reference.(string); isString {
|
|
|
|
|
i.SetText(referenceVal)
|
|
|
|
|
} else {
|
|
|
|
|
i.SetText(currentItem.mainText)
|
|
|
|
|
}
|
|
|
|
|
i.Lock()
|
|
|
|
|
i.autocompleteList = nil
|
|
|
|
|
i.autocompleteListSuggestion = ""
|
|
|
|
|
} else {
|
|
|
|
|
i.Unlock()
|
|
|
|
|
finish(key)
|
|
|
|
|
}
|
|
|
|
|
i.Unlock()
|
|
|
|
|
return
|
|
|
|
|
case tcell.KeyEscape:
|
|
|
|
|
if i.autocompleteList != nil {
|
|
|
|
|
i.autocompleteList = nil
|
|
|
|
|
i.autocompleteListSuggestion = ""
|
|
|
|
|
} else {
|
|
|
|
|
finish(key)
|
|
|
|
|
}
|
|
|
|
|
i.Unlock()
|
|
|
|
|
return
|
|
|
|
|
case tcell.KeyDown, tcell.KeyTab: // Autocomplete selection.
|
|
|
|
|
if i.autocompleteList != nil {
|
|
|
|
@ -784,9 +833,7 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|
|
|
|
newEntry = 0
|
|
|
|
|
}
|
|
|
|
|
i.autocompleteList.SetCurrentItem(newEntry)
|
|
|
|
|
currentText, _ = i.autocompleteList.GetItemText(newEntry) // Don't trigger changed function twice.
|
|
|
|
|
i.Unlock()
|
|
|
|
|
i.SetText(currentText)
|
|
|
|
|
} else {
|
|
|
|
|
i.Unlock()
|
|
|
|
|
finish(key)
|
|
|
|
@ -799,9 +846,7 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|
|
|
|
newEntry = i.autocompleteList.GetItemCount() - 1
|
|
|
|
|
}
|
|
|
|
|
i.autocompleteList.SetCurrentItem(newEntry)
|
|
|
|
|
currentText, _ = i.autocompleteList.GetItemText(newEntry) // Don't trigger changed function twice.
|
|
|
|
|
i.Unlock()
|
|
|
|
|
i.SetText(currentText)
|
|
|
|
|
} else {
|
|
|
|
|
i.Unlock()
|
|
|
|
|
finish(key)
|
|
|
|
|