Trying to clear a layout but getting stuck at nested GridLayouts

I’m trying to delete the layout altogether with the code, below, because I want to regenerate the content in response to input from the user. clear_layout(fig.layout) successfully removes all the Axes, Labels, etc, but I’m stumped when it comes to removing the nested GridLayouts. You can see that my code recurses into them and it does successfully remove blocks in those nested GridLayouts, but how can I get rid of the GridLayouts themselves?

    function clear_layout(layout::gm.GridLayout)
        items_to_remove = []
        for x in gm.contents(layout)
            if typeof(x) == gm.GridLayout
                clear_layout(x)
            else
                push!(items_to_remove, x)
            end
        end
        map(delete!, items_to_remove)
    end

There’s no public function to remove a gridlayout, I somehow never got to it. The function to remove a child content in GridLayoutBase is remove_from_gridlayout! but you need to pass the gridcontent wrapper of the respective object which would be a bit roundabout for a public function.

Here’s an example that shows that a nested GridLayout can be removed, but which also demonstrates that the objects that were placed in that layout are still in the Figure and have to be delete!d manually (being in the Figure and being connected to a layout are two orthogonal things). They just stop being updated as the addition of the Box shows.

GLB = Makie.GridLayoutBase

f = Figure()
Axis(f[1, 1])
gl = GridLayout(f[1, 2])
for i in 1:3, j in 1:3
    Axis(gl[i, j])
end
GLB.remove_from_gridlayout!(GLB.gridcontent(gl))
Box(f[2, 1:2])
f

At some point I will probably make some unified interface for deleting stuff including GridLayouts from a Figure.

1 Like

Thanks… I was reading about remove_from_gridlayout! in another thread but it didn’t make sense until your reply, above. This now works for me:

function clear_layout(layout::gm.GridLayout)

    # Begin by removing the blocks from the recursive GridLayout structure
    items_to_remove = []
    for block in gm.contents(layout)
        if typeof(block) == gm.GridLayout
            clear_layout(block)
        else
            push!(items_to_remove, block)
        end
    end
    map(delete!, items_to_remove)

    # Now remove the GridLayout substructure
    items_to_remove = []
    for wrapper in layout.content
        push!(items_to_remove, wrapper) 
    end         
    map(glb.remove_from_gridlayout!, items_to_remove)

    # Finally, trim so that the layout is 1 by 1.
    gm.trim!(layout)
end

Glad you got it to work! As a side note, foreach is like map without storing the results in a vector

:joy: I was too lazy to look up foreach. Thanks!