package numeric import ( "galaxy/client/widget/validator" "galaxy/util" "strconv" "strings" "unicode/utf8" "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/mobile" "fyne.io/fyne/v2/widget" ) type FloatEntry struct { widget.Entry origin float64 MaxValue float64 maxSize uint validator fyne.StringValidator Valid bool } type IntEntry struct { widget.Entry origin uint MaxValue uint maxSize uint validator fyne.StringValidator Valid bool } func NewFloatEntry(maxSize uint, onChanged func(string)) *FloatEntry { e := &FloatEntry{maxSize: maxSize, validator: validator.FloatEntryValidator} e.ExtendBaseWidget(e) e.Entry.Scroll = fyne.ScrollNone e.Entry.TextStyle = fyne.TextStyle{Monospace: true} // e.Validator = validator.FloatEntryValidator // e.AlwaysShowValidationError = true e.Entry.ActionItem = nil e.SetOrigin(0) e.Validate() e.Entry.OnChanged = onChanged return e } func NewIntEntry(maxSize uint, onChanged func(string)) *IntEntry { e := &IntEntry{maxSize: maxSize, validator: validator.IntEntryValidator} e.ExtendBaseWidget(e) e.Entry.Scroll = fyne.ScrollNone e.Entry.TextStyle = fyne.TextStyle{Monospace: true} // e.Validator = validator.IntEntryValidator // e.AlwaysShowValidationError = true e.Entry.ActionItem = nil e.SetOrigin(0) e.Validate() e.Entry.OnChanged = onChanged return e } func (e *FloatEntry) CreateRenderer() fyne.WidgetRenderer { r := e.Entry.CreateRenderer() return r } func (e *FloatEntry) TypedRune(r rune) { if !((r >= '0' && r <= '9') || r == '.') { return } if !lengthBelowLimit(e.Entry.Text, e.maxSize) && e.Entry.SelectedText() == "" { return } if r == '.' && strings.Contains(e.Entry.Text, ".") { return } e.Entry.TypedRune(r) } func (e *FloatEntry) TypedShortcut(shortcut fyne.Shortcut) { paste, ok := shortcut.(*fyne.ShortcutPaste) if !ok { e.Entry.TypedShortcut(shortcut) return } content := paste.Clipboard.Content() if _, err := strconv.ParseFloat(content, 64); err == nil { e.Entry.TypedShortcut(shortcut) } } func (e *FloatEntry) Keyboard() mobile.KeyboardType { return mobile.NumberKeyboard } func (e *FloatEntry) SetOrigin(v float64) { if v < 0 { return } e.origin = v e.Reset() } func (e *FloatEntry) Reset() { e.SetValue(e.origin) } func (e *FloatEntry) Clear() { onChanged := e.Entry.OnChanged e.Entry.OnChanged = nil e.Entry.SetText("") e.Entry.OnChanged = onChanged } func (e *FloatEntry) SetValue(v float64) { if v < 0 { return } e.Entry.SetText(strconv.FormatFloat(util.Fixed3(v), 'f', -1, 64)) } func (e *FloatEntry) Value() (float64, bool) { if v, err := validator.ParseFloat(e.Entry.Text); err != nil { return 0, false } else { return v, true } } func (e *FloatEntry) Overriden() bool { if v, ok := e.Value(); !ok { return false } else { return util.Fixed3(v) != util.Fixed3(e.origin) } } func (e *FloatEntry) Validate() { if e.validator == nil { return } err := e.validator(e.Entry.Text) e.Valid = err == nil } func (e *IntEntry) TypedRune(r rune) { if r >= '0' && r <= '9' { if lengthBelowLimit(e.Entry.Text, e.maxSize) || e.Entry.SelectedText() != "" { e.Entry.TypedRune(r) } } } func (e *IntEntry) TypedShortcut(shortcut fyne.Shortcut) { paste, ok := shortcut.(*fyne.ShortcutPaste) if !ok { e.Entry.TypedShortcut(shortcut) return } content := paste.Clipboard.Content() if _, err := strconv.ParseInt(content, 10, 64); err == nil { e.Entry.TypedShortcut(shortcut) } } func (e *IntEntry) Keyboard() mobile.KeyboardType { return mobile.NumberKeyboard } func (e *IntEntry) SetOrigin(v int) { if v < 0 { return } e.origin = uint(v) e.Reset() } func (e *IntEntry) Reset() { e.SetValue(int(e.origin)) } func (e *IntEntry) SetValue(v int) { if v < 0 { return } e.Entry.SetText(strconv.Itoa(v)) } func (e *IntEntry) Value() (int, bool) { if v, err := validator.ParseInt(e.Entry.Text); err != nil { return 0, false } else { return v, true } } func (e *IntEntry) Overriden() bool { if v, ok := e.Value(); !ok { return false } else { return v != int(e.origin) } } func (e *IntEntry) Validate() { if e.validator == nil { return } err := e.validator(e.Entry.Text) e.Valid = err == nil } func lengthBelowLimit(s string, max uint) bool { return utf8.RuneCountInString(s) < int(max) }