-
Notifications
You must be signed in to change notification settings - Fork 19
/
listmodel.go
134 lines (111 loc) · 3.69 KB
/
listmodel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package gioutil
// #cgo pkg-config: gio-2.0
// #include "listmodel.h"
import "C"
import (
"unsafe"
"github.com/diamondburned/gotk4/pkg/core/gbox"
"github.com/diamondburned/gotk4/pkg/core/glib"
"github.com/diamondburned/gotk4/pkg/gio/v2"
coreglib "github.com/diamondburned/gotk4/pkg/core/glib"
)
// ListModelType is a type-safe wrapper around [ListModel] and [ObjectValue].
// For an example, see [ListModel]'s example.
type ListModelType[T any] struct{}
// NewListModelType creates a new list model type.
func NewListModelType[T any]() ListModelType[T] {
return ListModelType[T]{}
}
// New creates a new list model of type T.
func (t ListModelType[T]) New() *ListModel[T] {
return NewListModel[T]()
}
// ObjectValue returns the value of the given object as type T.
// The object must originate from a [ListModel].
func (t ListModelType[T]) ObjectValue(obj glib.Objector) T {
return ObjectValue[T](obj)
}
// ListModel is a wrapper around an internal ListModel that allows any Go value
// to be used as a list item. Internally, it uses core/gbox to store the values
// in a global registry for later retrieval.
type ListModel[T any] struct {
*gio.ListModel
}
// NewListModel creates a new list model.
func NewListModel[T any]() *ListModel[T] {
obj := coreglib.AssumeOwnership(unsafe.Pointer(C.gotk4_gbox_list_new())) // C.Gotk4GboxList
return &ListModel[T]{
ListModel: &gio.ListModel{
Object: obj,
},
}
}
func (l *ListModel[T]) native() *C.Gotk4GboxList {
return (*C.Gotk4GboxList)(unsafe.Pointer(l.Native()))
}
// Append appends a value to the list.
func (l *ListModel[T]) Append(v T) {
C.gotk4_gbox_list_append(l.native(), C.guintptr(gbox.Assign(v)))
}
// Remove removes the value at the given index.
func (l *ListModel[T]) Remove(index int) {
l.Splice(index, 1)
}
// Splice removes the values in the given range and replaces them with the
// given values.
func (l *ListModel[T]) Splice(position, removals int, values ...T) {
var idsPtr *C.guintptr
if len(values) > 0 {
idsPtr = (*C.guintptr)(unsafe.Pointer(C.g_malloc_n(C.gsize(len(values)+1), C.sizeof_guintptr)))
defer C.g_free(C.gpointer(idsPtr))
ids := unsafe.Slice(idsPtr, len(values)+1)
ids[len(values)] = 0
for i, v := range values {
ids[i] = C.guintptr(gbox.Assign(v))
}
}
C.gotk4_gbox_list_splice(l.native(), C.guint(position), C.guint(removals), idsPtr)
}
// Item returns the value at the given index.
func (l *ListModel[T]) Item(index int) T {
id := uintptr(C.gotk4_gbox_list_get_id(l.native(), C.guint(index)))
return gbox.Get(id).(T)
}
// NItems returns the number of items in the list.
func (l *ListModel[T]) NItems() int {
return int(l.ListModel.NItems())
}
// AllItems returns an iterator over all values in the list.
func (l *ListModel[T]) AllItems() func(yield func(T) bool) {
return func(yield func(T) bool) {
nItems := l.NItems()
for i := 0; i < nItems; i++ {
if !yield(l.Item(i)) {
break
}
}
}
}
// RangeItems returns an iterator over the values in the given range.
// If j is greater than the length of the list, it will be clamped to that.
func (l *ListModel[T]) RangeItems(i, j int) func(yield func(T) bool) {
return func(yield func(T) bool) {
nItems := l.NItems()
for j = min(j, nItems); i < j; i++ {
if !yield(l.Item(i)) {
break
}
}
}
}
// ObjectValue returns the value of the given object.
// The object must originate from a [ListModel].
func ObjectValue[T any](obj glib.Objector) T {
object := glib.BaseObject(obj)
if object.Type() != coreglib.Type(C.gotk4_gbox_object_get_type()) {
panic("StringObjectValue: obj must be a *Gotk4GboxObject")
}
native := (*C.Gotk4GboxObject)(unsafe.Pointer(object.Native()))
id := uintptr(C.gotk4_gbox_object_get_id(native))
return gbox.Get(id).(T)
}