TreeView word wrapping and row height

I’m trying to create TreeView with word-wrapped resizable column. In the example (Rust) wrap-width property of cell renderer is changed in width change handler. Unfortunately, row heights are not recalculated, neither at start nor after column resize.

When I run the example with GTK_DEBUG=interactive and change in inspector e.g. spacing property of the corresponding GtkTreeViewColumn, heights are recalculated properly for the current width.

If I call something like queue_resize for GtkTreeViewColumn in cell renderer width change handler, the result looks like infinite handler loop.

What is the correct way to recalculate row heights for the wrapped text?

You can’t do this with GtkTreeView natively, because to do it requires loops in the sizing machinery and row-height caching. However, in practice, if you are a bit clever, you can. Builder does this for various treeview’s like Diagnostics and ToDos.

https://gitlab.gnome.org/GNOME/gnome-builder/blob/master/src/libide/gui/ide-fancy-tree-view.c
https://gitlab.gnome.org/GNOME/gnome-builder/blob/master/src/libide/gui/ide-cell-renderer-fancy.c

1 Like

Thank you! I couldn’t previously find some code examples featuring word wrapping.

Unfortunately, subclassing in gtk-rs is rather complex. But based on your example from Builder code, I think, I found possible workaround. It was surprising that notify on width is triggered for TreeViewColumn even when width value is unchanged. I store last_width (in terms of IdeFancyTreeView) in wrap-width of CellRendererText, so I can use it to break the loop:

column.connect_property_width_notify(move |col| {
    let width = col.get_width();
    let cell: gtk::CellRendererText = col.get_cells()[0].clone().downcast().unwrap();
    // new check:
    if cell.get_property_wrap_width() != width {
        cell.set_property_wrap_width(width);
        let col_closure = col.clone();
        gtk::idle_add(move || {
            col_closure.queue_resize();
            Continue(false)
        });
    }
});

But in this case it would be impossible to remove the “idle-task” at TreeView destructor.

You can use the GtkWidget::destroy() signal to perform cleanup operations.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.