Skip to content

Commit

Permalink
Fix gioutil.ListModel[T] not working
Browse files Browse the repository at this point in the history
  • Loading branch information
diamondburned committed Feb 11, 2024
1 parent 819f350 commit 9b8c8f6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 32 deletions.
11 changes: 3 additions & 8 deletions pkg/core/gioutil/listmodel.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "listmodel.h"

// defined in gboxlist.go.
void gotk4_gboxlist_remove(guintptr id);
// defined in gbox.
extern void callbackDelete(guintptr id);

#define GDK_ARRAY_ELEMENT_TYPE Gotk4GboxObject *
#define GDK_ARRAY_NAME objects
Expand All @@ -21,7 +21,7 @@ static void gotk4_gbox_object_init(Gotk4GboxObject *self) { self->id = 0; }
static void gotk4_gbox_object_finalize(GObject *object) {
Gotk4GboxObject *self = GOTK4_GBOX_OBJECT(object);
if (self->id != 0) {
gotk4_gboxlist_remove(self->id);
callbackDelete(self->id);
}
G_OBJECT_CLASS(gotk4_gbox_object_parent_class)->finalize(object);
}
Expand Down Expand Up @@ -123,11 +123,6 @@ void gotk4_gbox_list_append(Gotk4GboxList *self, guintptr id) {
objects_get_size(&self->items) - 1, 0, 1);
}

void gotk4_gbox_list_remove(Gotk4GboxList *self, guint position) {
g_return_if_fail(GOTK4_IS_GBOX_LIST(self));
gotk4_gbox_list_splice(self, position, 1, NULL);
}

guintptr gotk4_gbox_list_get_id(Gotk4GboxList *self, guint position) {
g_return_val_if_fail(GOTK4_IS_GBOX_LIST(self), 0);
g_return_val_if_fail(position < objects_get_size(&self->items), 0);
Expand Down
28 changes: 12 additions & 16 deletions pkg/core/gioutil/listmodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,22 @@ import "C"
import (
"unsafe"

"github.com/diamondburned/gotk4/pkg/core/gbox"
"github.com/diamondburned/gotk4/pkg/core/glib"
"github.com/diamondburned/gotk4/pkg/core/slab"
"github.com/diamondburned/gotk4/pkg/gio/v2"

coreglib "github.com/diamondburned/gotk4/pkg/core/glib"
)

var registry slab.Slab

func init() {
registry.Grow(128)
}

//export gotk4_gboxlist_remove
func gotk4_gboxlist_remove(id uintptr) { registry.Delete(id) }

// 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]()
Expand Down Expand Up @@ -61,26 +57,26 @@ func (l *ListModel[T]) native() *C.Gotk4GboxList {

// Append appends a value to the list.
func (l *ListModel[T]) Append(v T) {
C.gotk4_gbox_list_append(l.native(), C.guintptr(registry.Put(v, false)))
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) {
C.gotk4_gbox_list_remove(l.native(), C.guint(index))
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_gpointer)))
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(registry.Put(v, false))
ids[i] = C.guintptr(gbox.Assign(v))
}
}

Expand All @@ -90,7 +86,7 @@ func (l *ListModel[T]) Splice(position, removals int, values ...T) {
// 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 registry.Get(id).(T)
return gbox.Get(id).(T)
}

// NItems returns the number of items in the list.
Expand Down Expand Up @@ -134,5 +130,5 @@ func ObjectValue[T any](obj glib.Objector) T {
native := (*C.Gotk4GboxObject)(unsafe.Pointer(object.Native()))
id := uintptr(C.gotk4_gbox_object_get_id(native))

return registry.Get(id).(T)
return gbox.Get(id).(T)
}
1 change: 0 additions & 1 deletion pkg/core/gioutil/listmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ Gotk4GboxList *gotk4_gbox_list_new(void);
void gotk4_gbox_list_splice(Gotk4GboxList *self, guint position,
guint n_removals, const guintptr *additions);
void gotk4_gbox_list_append(Gotk4GboxList *self, guintptr id);
void gotk4_gbox_list_remove(Gotk4GboxList *self, guint position);
guintptr gotk4_gbox_list_get_id(Gotk4GboxList *self, guint position);

G_END_DECLS
5 changes: 3 additions & 2 deletions pkg/core/gioutil/listmodel_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

type peopleListModel = gioutil.ListModelType[Person]
var peopleListModel = gioutil.NewListModelType[Person]()

func ExampleListModel() {
list := peopleListModel.New()
Expand All @@ -25,8 +25,9 @@ func ExampleListModel() {

// AllItems() can be iterated over if rangefunc is supported.
all := list.AllItems()
all(func(p Person) {
all(func(p Person) bool {
fmt.Println(p)
return true
})

// Output:
Expand Down
16 changes: 11 additions & 5 deletions pkg/core/gioutil/listmodel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import (
"reflect"
"runtime"
"testing"
"time"
)

type weirdType struct {
weird string
ptr *string
}

type weirdTypeList = ListModelType[weirdType]
var weirdTypeList = NewListModelType[weirdType]()

func TestListModel(t *testing.T) {
expect := []weirdType{
Expand All @@ -23,8 +22,16 @@ func TestListModel(t *testing.T) {
}

list := weirdTypeList.New()
list.Append(expect[0])
list.Splice(1, 0, expect[1], expect[2])
list.ConnectItemsChanged(func(position, removed, added uint) {
t.Logf(
"ItemsChanged: position=%d, removed=%d, added=%d",
position, removed, added)
})

fuckShitUp()

list.Splice(0, 0, expect[0], expect[1])
list.Append(expect[2])

fuckShitUp()

Expand Down Expand Up @@ -106,7 +113,6 @@ func drainIterator[T any](iter func(yield func(T) bool)) []T {
func fuckShitUp() {
for i := 0; i < 10; i++ {
runtime.GC()
time.Sleep(10 * time.Millisecond)
}
}

Expand Down

0 comments on commit 9b8c8f6

Please sign in to comment.