antoyo / relm

Idiomatic, GTK+-based, GUI library, inspired by Elm, written in Rust
MIT License
2.44k stars 78 forks source link

support for virtualized widget lists? #277

Open emmanueltouzery opened 3 years ago

emmanueltouzery commented 3 years ago

i'm having a great time writing relm apps, but my #1 issue is the memory use when adding many relm widget to a gtk ListBox. I actually once drew my big list in a DrawingArea to work around this. This is not specifically a relm problem, that's a gtk problem, and it seems they've fixed it in gtk4: https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/

So I've been expecting for a while that this issue gets fixed when relm supports gtk4, but now I started to worry that it's not enough that gtk4 offers that, it might be quite some work for relm to also support the concept of virtualized widget lists, where components get recycled as the user scrolls the list? I am curious, do you think it's achievable for relm without big changes?

antoyo commented 3 years ago

I read a bit about this because I was not familiar with this new feature.

I was thinking maybe we could do the following:

Add an attribute above a property binding and specify somehow a message to be sent for the bind signal. That might require a relm widget wrapping GtkSignalListItemFactory.

If I convert the code (not the builder one) example from the link above to this idea in relm, we would have:

fn update(&mut self, msg: Msg) {
    match msg {
        Msg::Bind(list_item) {
            self.model.icon = list_item.get_item().unwrap().get_icon();
        },
    }
}

view! {
    gtk::Image {
        icon_size: IconSize::Large,
        #[binding]
        from_gicon: &self.model.icon,
    }
}

But I'm not sure this is convenient, as we would need to initialize the icon model attribute in the model() function, which probably means we'll initialize it to None and use an Option.

Now that I think of it, maybe it's simplest to do nothing special in relm and use GtkSignalListItemFactory:

What do you think?

Edit: Actually, I don't think it makes sense to send the Bind message to the child widget: I guess it should be sent to the parent (list) widget. Not sure how convenient all of this would be. I guess we can assume relm would work as is with GtkSignalListItemFactory (we should check that the bind signal can be handled asynchronously).

Maybe if I see a more complex example using a Builder (ui) file, I would have more ideas to port this to relm.

emmanueltouzery commented 3 years ago

Yes.. I'm myself not familiar with the API, i'm just feeling the pain that the API is supposed to relieve :)

For examples I usually look at gtk-demo and indeed I see in gtk4-demo, at least Lists -> Application Launcher and Lists -> Weather. Maybe it's enough to clarify things?

I'm relieved you think that relm could support the feature. I was worried that there was a conflict between the gtk recycling widgets that I imagine is going on and relm's component lifecycle (although the factory pattern means that maybe there is no recycling.. honestly I didn't dig too much into this).

As for myself, since I need the feature now and I think I won't find the time to help in the porting of relm to gtk4 and the introduction of this feature, I'm likely to again down the path of using a gtk drawingarea and manual render to achieve good performance with large (thousands of items and more) widget lists (what I get are not really widget lists, but they look and feel like such to the user).

antoyo commented 3 years ago

The only conflict I could see would be if you create bindings in setup, but I guess you could do the same without relm anyway.

Yeah, for the porting to gtk4, I'm very busy these days, but I should have more time in a few weeks and there's the Rust+GNOME hackfest coming soon, so I'll probably work on this during the hackfest.

emmanueltouzery commented 3 years ago

no problem of course! I just wanted to get an idea whether it was feasible and point this out as, in my mind, an important feature of gtk4. Thanks again for relm! Pretty sure I wouldn't be doing any gtk these days without it.