• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fyne-io / fyne / 13156141055

05 Feb 2025 11:14AM UTC coverage: 62.563% (-0.06%) from 62.619%
13156141055

Pull #5496

github

dweymouth
address code style comments
Pull Request #5496: Make table scrolling and resizing more efficient

38 of 38 new or added lines in 1 file covered. (100.0%)

266 existing lines in 11 files now uncovered.

24755 of 39568 relevant lines covered (62.56%)

841.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.16
/data/binding/binding.go
1
//go:generate go run gen.go
2

3
// Package binding provides support for binding data to widgets.
4
package binding
5

6
import (
7
        "errors"
8
        "reflect"
9
        "sync"
10

11
        "fyne.io/fyne/v2"
12
        "fyne.io/fyne/v2/internal/async"
13
)
14

15
var (
16
        errKeyNotFound = errors.New("key not found")
17
        errOutOfBounds = errors.New("index out of bounds")
18
        errParseFailed = errors.New("format did not match 1 value")
19

20
        // As an optimisation we connect any listeners asking for the same key, so that there is only 1 per preference item.
21
        prefBinds = newPreferencesMap()
22
)
23

24
// DataItem is the base interface for all bindable data items.
25
//
26
// Since: 2.0
27
type DataItem interface {
28
        // AddListener attaches a new change listener to this DataItem.
29
        // Listeners are called each time the data inside this DataItem changes.
30
        // Additionally, the listener will be triggered upon successful connection to get the current value.
31
        AddListener(DataListener)
32
        // RemoveListener will detach the specified change listener from the DataItem.
33
        // Disconnected listener will no longer be triggered when changes occur.
34
        RemoveListener(DataListener)
35
}
36

37
// DataListener is any object that can register for changes in a bindable DataItem.
38
// See NewDataListener to define a new listener using just an inline function.
39
//
40
// Since: 2.0
41
type DataListener interface {
42
        DataChanged()
43
}
44

45
// NewDataListener is a helper function that creates a new listener type from a simple callback function.
46
//
47
// Since: 2.0
27✔
48
func NewDataListener(fn func()) DataListener {
27✔
49
        return &listener{fn}
27✔
50
}
51

52
type listener struct {
53
        callback func()
54
}
55

76✔
56
func (l *listener) DataChanged() {
76✔
57
        l.callback()
76✔
58
}
59

60
type base struct {
61
        listeners async.Map[DataListener, bool]
62

63
        lock sync.RWMutex
64
}
65

66
// AddListener allows a data listener to be informed of changes to this item.
52✔
67
func (b *base) AddListener(l DataListener) {
104✔
68
        b.listeners.Store(l, true)
52✔
69
        queueItem(l.DataChanged)
52✔
70
}
52✔
71

72
// RemoveListener should be called if the listener is no longer interested in being informed of data change events.
73
func (b *base) RemoveListener(l DataListener) {
74
        b.listeners.Delete(l)
3✔
75
}
6✔
76

6✔
77
func (b *base) trigger() {
6✔
78
        var listeners []DataListener
3✔
79
        b.listeners.Range(func(listener DataListener, _ bool) bool {
3✔
80
                listeners = append(listeners, listener)
3✔
81
                return true
3✔
82
        })
3✔
83

3✔
84
        queueItem(func() {
3✔
85
                for _, listen := range listeners {
86
                        listen.DataChanged()
87
                }
88
        })
89
}
429✔
90

858✔
91
// Untyped supports binding a any value.
530✔
92
//
101✔
93
// Since: 2.1
101✔
94
type Untyped interface {
95
        DataItem
96
        Get() (any, error)
97
        Set(any) error
98
}
99

100
// NewUntyped returns a bindable any value that is managed internally.
101
//
102
// Since: 2.1
103
func NewUntyped() Untyped {
104
        var blank any = nil
105
        v := &blank
106
        return &boundUntyped{val: reflect.ValueOf(v).Elem()}
107
}
108

109
type boundUntyped struct {
2✔
110
        base
2✔
111

2✔
112
        val reflect.Value
2✔
113
}
2✔
114

115
func (b *boundUntyped) Get() (any, error) {
116
        b.lock.RLock()
117
        defer b.lock.RUnlock()
118

119
        return b.val.Interface(), nil
120
}
121

7✔
122
func (b *boundUntyped) Set(val any) error {
7✔
123
        b.lock.Lock()
7✔
124
        defer b.lock.Unlock()
7✔
125
        if b.val.Interface() == val {
7✔
126
                return nil
7✔
127
        }
128
        if val == nil {
5✔
129
                zeroValue := reflect.Zero(b.val.Type())
5✔
130
                b.val.Set(zeroValue)
6✔
131
        } else {
1✔
132
                b.val.Set(reflect.ValueOf(val))
1✔
133
        }
1✔
134

5✔
135
        b.trigger()
1✔
136
        return nil
1✔
137
}
4✔
138

3✔
139
// ExternalUntyped supports binding a any value to an external value.
3✔
140
//
4✔
141
// Since: 2.1
4✔
142
type ExternalUntyped interface {
4✔
143
        Untyped
4✔
144
        Reload() error
145
}
146

147
// BindUntyped returns a bindable any value that is bound to an external type.
148
// The parameter must be a pointer to the type you wish to bind.
149
//
150
// Since: 2.1
151
func BindUntyped(v any) ExternalUntyped {
152
        t := reflect.TypeOf(v)
153
        if t.Kind() != reflect.Ptr {
154
                fyne.LogError("Invalid type passed to BindUntyped, must be a pointer", nil)
155
                v = nil
156
        }
157

158
        if v == nil {
2✔
159
                var blank any
2✔
160
                v = &blank // never allow a nil value pointer
2✔
161
        }
×
162

×
UNCOV
163
        b := &boundExternalUntyped{}
×
164
        b.val = reflect.ValueOf(v).Elem()
165
        b.old = b.val.Interface()
2✔
UNCOV
166
        return b
×
UNCOV
167
}
×
UNCOV
168

×
169
type boundExternalUntyped struct {
170
        boundUntyped
2✔
171

2✔
172
        old any
2✔
173
}
2✔
174

175
func (b *boundExternalUntyped) Set(val any) error {
176
        b.lock.Lock()
177
        defer b.lock.Unlock()
178
        if b.old == val {
179
                return nil
180
        }
181
        b.val.Set(reflect.ValueOf(val))
182
        b.old = val
5✔
183

5✔
184
        b.trigger()
5✔
UNCOV
185
        return nil
×
UNCOV
186
}
×
UNCOV
187

×
188
func (b *boundExternalUntyped) Reload() error {
5✔
189
        return b.Set(b.val.Interface())
5✔
190
}
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc