fckeuspy-go/vendor/fyne.io/fyne/v2/data/binding/items.go

285 lines
6.6 KiB
Go

package binding
import (
"bytes"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/storage"
)
// Item supports binding any type T generically.
//
// Since: 2.6
type Item[T any] interface {
DataItem
Get() (T, error)
Set(T) error
}
// ExternalItem supports binding any external value of type T.
//
// Since: 2.6
type ExternalItem[T any] interface {
Item[T]
Reload() error
}
// NewItem returns a bindable value of type T that is managed internally.
//
// Since: 2.6
func NewItem[T any](comparator func(T, T) bool) Item[T] {
return &item[T]{val: new(T), comparator: comparator}
}
// BindItem returns a new bindable value that controls the contents of the provided variable of type T.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.6
func BindItem[T any](val *T, comparator func(T, T) bool) ExternalItem[T] {
if val == nil {
val = new(T) // never allow a nil value pointer
}
b := &externalItem[T]{}
b.comparator = comparator
b.val = val
b.old = *val
return b
}
// Bool supports binding a bool value.
//
// Since: 2.0
type Bool = Item[bool]
// ExternalBool supports binding a bool value to an external value.
//
// Since: 2.0
type ExternalBool = ExternalItem[bool]
// NewBool returns a bindable bool value that is managed internally.
//
// Since: 2.0
func NewBool() Bool {
return newItemComparable[bool]()
}
// BindBool returns a new bindable value that controls the contents of the provided bool variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.0
func BindBool(v *bool) ExternalBool {
return bindExternalComparable(v)
}
// Bytes supports binding a []byte value.
//
// Since: 2.2
type Bytes = Item[[]byte]
// ExternalBytes supports binding a []byte value to an external value.
//
// Since: 2.2
type ExternalBytes = ExternalItem[[]byte]
// NewBytes returns a bindable []byte value that is managed internally.
//
// Since: 2.2
func NewBytes() Bytes {
return NewItem(bytes.Equal)
}
// BindBytes returns a new bindable value that controls the contents of the provided []byte variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.2
func BindBytes(v *[]byte) ExternalBytes {
return BindItem(v, bytes.Equal)
}
// Float supports binding a float64 value.
//
// Since: 2.0
type Float = Item[float64]
// ExternalFloat supports binding a float64 value to an external value.
//
// Since: 2.0
type ExternalFloat = ExternalItem[float64]
// NewFloat returns a bindable float64 value that is managed internally.
//
// Since: 2.0
func NewFloat() Float {
return newItemComparable[float64]()
}
// BindFloat returns a new bindable value that controls the contents of the provided float64 variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.0
func BindFloat(v *float64) ExternalFloat {
return bindExternalComparable(v)
}
// Int supports binding a int value.
//
// Since: 2.0
type Int = Item[int]
// ExternalInt supports binding a int value to an external value.
//
// Since: 2.0
type ExternalInt = ExternalItem[int]
// NewInt returns a bindable int value that is managed internally.
//
// Since: 2.0
func NewInt() Int {
return newItemComparable[int]()
}
// BindInt returns a new bindable value that controls the contents of the provided int variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.0
func BindInt(v *int) ExternalInt {
return bindExternalComparable(v)
}
// Rune supports binding a rune value.
//
// Since: 2.0
type Rune = Item[rune]
// ExternalRune supports binding a rune value to an external value.
//
// Since: 2.0
type ExternalRune = ExternalItem[rune]
// NewRune returns a bindable rune value that is managed internally.
//
// Since: 2.0
func NewRune() Rune {
return newItemComparable[rune]()
}
// BindRune returns a new bindable value that controls the contents of the provided rune variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.0
func BindRune(v *rune) ExternalRune {
return bindExternalComparable(v)
}
// String supports binding a string value.
//
// Since: 2.0
type String = Item[string]
// ExternalString supports binding a string value to an external value.
//
// Since: 2.0
type ExternalString = ExternalItem[string]
// NewString returns a bindable string value that is managed internally.
//
// Since: 2.0
func NewString() String {
return newItemComparable[string]()
}
// BindString returns a new bindable value that controls the contents of the provided string variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.0
func BindString(v *string) ExternalString {
return bindExternalComparable(v)
}
// URI supports binding a fyne.URI value.
//
// Since: 2.1
type URI = Item[fyne.URI]
// ExternalURI supports binding a fyne.URI value to an external value.
//
// Since: 2.1
type ExternalURI = ExternalItem[fyne.URI]
// NewURI returns a bindable fyne.URI value that is managed internally.
//
// Since: 2.1
func NewURI() URI {
return NewItem(storage.EqualURI)
}
// BindURI returns a new bindable value that controls the contents of the provided fyne.URI variable.
// If your code changes the content of the variable this refers to you should call Reload() to inform the bindings.
//
// Since: 2.1
func BindURI(v *fyne.URI) ExternalURI {
return BindItem(v, storage.EqualURI)
}
func newItemComparable[T bool | float64 | int | rune | string]() Item[T] {
return NewItem[T](func(a, b T) bool { return a == b })
}
type item[T any] struct {
base
comparator func(T, T) bool
val *T
}
func (b *item[T]) Get() (T, error) {
b.lock.RLock()
defer b.lock.RUnlock()
if b.val == nil {
return *new(T), nil
}
return *b.val, nil
}
func (b *item[T]) Set(val T) error {
b.lock.Lock()
equal := b.comparator(*b.val, val)
*b.val = val
b.lock.Unlock()
if !equal {
b.trigger()
}
return nil
}
func bindExternalComparable[T bool | float64 | int | rune | string](val *T) ExternalItem[T] {
return BindItem(val, func(t1, t2 T) bool { return t1 == t2 })
}
type externalItem[T any] struct {
item[T]
old T
}
func (b *externalItem[T]) Set(val T) error {
b.lock.Lock()
if b.comparator(b.old, val) {
b.lock.Unlock()
return nil
}
*b.val = val
b.old = val
b.lock.Unlock()
b.trigger()
return nil
}
func (b *externalItem[T]) Reload() error {
return b.Set(*b.val)
}