diamondburned / gotk4

Autogenerated GTK4 bindings for Go
GNU Affero General Public License v3.0
528 stars 20 forks source link

Missing: Information trees #141

Open kendellfab opened 7 months ago

kendellfab commented 7 months ago

I've been working on migrating TreeViews to ListViews with TreeListModels. I'm finding though that there is a lack of information of how to accomplish this. Specifically with regards to TreeListModelCreateModelFunc on the NewTreeListModel. How do I properly use the item *coreglib.Object to know what child listmodel I need to return?

diamondburned commented 7 months ago

You could either use gioutil.ListModel[T] to pass in arbitrary Go pointers or gtk.StringList to pass in strings. Each of these list model types have their own functions to get the underlying data from *Object.

We do have an ongoing PR somewhere to add a ListView example, but the code for that is quite outdated at the moment, unfortunately.

kendellfab commented 7 months ago

I have been able to successfully use those structs you mentioned above to build flat lists.

However, I've been looking at building trees, displaying trees.

Which it would look like a developer would need to use a tree model. It is both this tree model and the TreeListModelCreateModelFunc that expose item *coreglib.Object that I can't figure out how to turn into my model like I was able to with the gioutil.ListModel[T].

diamondburned commented 7 months ago

You could see how Dissent does it:

https://github.com/diamondburned/dissent/blob/main/internal/sidebar/channels/channels_model.go

It still uses the legacy StringList model; I haven't had the time to port it over yet. It should be similar either way though.

kendellfab commented 7 months ago

I think this is where I'm stuck, looking at your code here you're casting the item to a *gtk.StringObject.

I have a non-gtk struct that I need to cast to, and I get an error. So is it not possible to bring our own types to the TreeModel at this point?

diamondburned commented 7 months ago

If you're using gioutil.ListModel[T], you'd want to use gioutil.ObjectValue[T](obj) to get your Go object back.

You can get additional type safety by using gio.ListModelType[T] which wraps both at once:

var goModelType = gioutil.NewListModelType[goModel]()

var gtkModel = goModelType.New()
var goValue = goModelType.ObjectValue(obj)
kendellfab commented 7 months ago

Thank you. I'll give that a try. I'm curious, is there a way to update the rows that contain in the list views? I've seen some GTK forums discussing bound properties, but in go we don't have bound properties like someone in C would have, unless I'm missing something.

diamondburned commented 7 months ago

is there a way to update the rows that contain in the list views

What do you mean? Each row in the list view should reflect data from some Go model, so to change that data, you'd just change the data in the model.

The way you're supposed to use ListView is to treat it like a transformation pipeline: you have a list of data represented in a certain order (the list model), which then gets transformed (the widget builder) into widgets to be displayed by the view.

kendellfab commented 7 months ago

I suppose I'm just trying to figure out the listmodel/listview combo and the ins and outs. I have a ListModel, that displays a label. I updated the value that gets set on the label in my go struct, but I'm unsure how to get the bind to happen again.

Perhaps it is a mater of me needing to learn more of the specifics.

diamondburned commented 7 months ago

I updated the value that gets set on the label in my go struct, but I'm unsure how to get the bind to happen again.

You will probably have to Splice the list again to set the changed value into the list:

var n int
var v Value
list.Splice(n, 1, v)

A (*gio.ListModel[T]).Set(int, T) function would definitely make this easier, so that might be worth adding.

diamondburned commented 7 months ago

(You can consider each item in the ListModel immutable: modifying each item separately, even if they're pointers, won't cause the list to actually update until you intentionally set it again.)

kendellfab commented 7 months ago

OK, that makes sense. I did see the splice method. Is there an availability to splice with a TreeListModel?

diamondburned commented 7 months ago

OK, that makes sense. I did see the splice method. Is there an availability to splice with a TreeListModel?

You'd splice one of the relevant list models within the tree model and the change will automatically propagate to the entire tree.

kendellfab commented 7 months ago

I think I could have asked a better question. How do I find and access the underlying ListModel from the tree model? I have the root ListModel saved, but I haven't seen any API for accessing child ListModels.

diamondburned commented 6 months ago

You'd probably use TreeListModel.get_child_row for that. Normally, GTK signals should give you the right child row as part of the parameters though.