britzl / gooey

Defold GUI system
MIT License
150 stars 22 forks source link

Dynamic List Refresh Behavior #78

Closed gragedaa closed 1 year ago

gragedaa commented 1 year ago

Hey! Just posting an issue about a forum post I made earlier about the refresh behavior of a dynamic list carousel.

https://forum.defold.com/t/refreshing-gooey-dynamiclist/72829

Here's a link to a toy example that showcases the behavior.

https://github.com/gragedaa/gooey_refresh_example/tree/main

On PC, you need to have a few items in the list, select one, then click the minus button without any input after. This behavior is easier to replicate on an android device due to the lack of mouse movement.

Please let me know if you have any questions!

britzl commented 1 year ago

I started looking at this today, but have so far not really figured out what goes wrong while refreshing the list.

gragedaa commented 1 year ago

No worries, thanks for taking a look though! I was able to resolve this issue by trimming down the refresh function by moving the gui node deletion and creation steps out. Instead, this occurs during initialization an the new nodes are 'reparented' on refresh using gui.set_parent(node, e.nodes[hash("dynamic_list_item")])

The only caveat with this method is that I had to manually set the item index. Otherwise, you will not be able to select a list item with scrolling first.

https://github.com/gragedaa/gooey_refresh_example/commit/78be32578bb4c30bf4214ddfa6b00940c8a901d4#diff-bb191de080fee0aff639a8aa5315c079df0d5d93817fcccbb7db0c53be3cc048

Still not sure why the previous behavior occurs, unfortunately

britzl commented 1 year ago

I'm not sure what you are doing wrong as the example you've included is relatively complicated to follow. But let's instead start by looking at the horizontal list example provided here in this repository:

https://github.com/britzl/gooey/blob/master/example/horizontallist.gui_script#L75-L77

Open that example and modify the list click behaviour to remove the item that is clicked:

    local list = gooey.horizontal_dynamic_list("dynamiclist_bg", "dynamiclist_stencil", "listitem_bg", self.list_data, action_id, action, nil, function(list)
        print("selected dynamic list item", list.selected_item.index, list.data[list.selected_item.index].text)
        local v = table.remove(list.data, list.selected_item.index)
        print("removed", v.text)
        gooey.horizontal_dynamic_list("dynamiclist_bg", "dynamiclist_stencil", "listitem_bg", self.list_data, nil, nil, nil, nil, refresh_dynamiclist)
    end, refresh_dynamiclist)

What we do here is to remove the item from the list.data and then we call the gooey.horizontal_dynamic_list() function again to make sure the internal list state is updated and the visuals refreshed. Try the example with the modification above and then click on items in the list to remove them. Notice that the list is refreshing properly.