Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping text in GTK3 treeview

Tags:

c++

gtk3

gtkmm3

I have trouble getting TreeView in GTK3 to wrap text correctly.

I set it up to wrap in this way:

    Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
    static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
        ->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
    static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
        ->property_wrap_width().set_value(200);

This works, text is wrapped, but when I resize the window and make it bigger, there is a lot of ugly white-space above and below cell with long text. It seems, that GTK reserves height for cell based on wrap width. Which makes no sense to me.

I tried to get around with setting needed in signal_check_resize with calculating needed width like this:

        Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
        auto width = this->get_allocated_width()
            - mTreeView.get_column(0)->get_width()
            - mTreeView.get_column(1)->get_width();
        static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
            ->property_wrap_width().set_value(width-100);
        this->forceRecreateModel = true; //Needed to work

But this lets me only make window bigger. It cannot be shrinked, after it was resized.

The question is, how this is properly done?

I am using gtk3.20.3-1 and gtkmm3.20.1-1 on Arch linux.

EDIT: fixed typo in the title...

like image 550
kracejic Avatar asked Apr 23 '16 15:04

kracejic


1 Answers

In the end I found how to do it.

In the setup of the window (for me constructor of the window derived class) it was necessary to set column to be AUTOSIZE in order to allow shrinking of the width.

//Last Column setup
{
    mTreeView.append_column("Translation", mColumns.mEnglish);
    Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
    pColumn->set_sizing(Gtk::TreeViewColumnSizing::TREE_VIEW_COLUMN_AUTOSIZE);
    static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
        ->property_wrap_mode().set_value(Pango::WRAP_WORD_CHAR);
}

Also there is needed to set correct wrap width on every resize. Without this, height of the row was as big as it would be necessary for currently set wrap_width with no regard on current width (resulting in big padding on the top, when stretched more and prohibiting to make window smaller).

This code was also in the constructor.

this->signal_check_resize().connect([this]()
{
    //calculate remaining size
    Gtk::TreeViewColumn* pColumn = mTreeView.get_column(2);
    auto width = this->get_allocated_width()
        - mTreeView.get_column(0)->get_width()
        - mTreeView.get_column(1)->get_width()-30;

    //minimum reasonable size for column
    if(width < 150)
        width = 150;

    static_cast<Gtk::CellRendererText *>(pColumn->get_first_cell())
        ->property_wrap_width().set_value(width);

    //debounce
    static auto oldsize = 0;
    {
        oldsize = width;

        //trigger redraw of mTreeView (by clearing and refilling Model,
        //it is done in 100ms pulse)
        this->mRedrawNeeded = true;
    }
});

And maybe it is worth noting, that I have mTreeView encapsulated in Gtk::ScrolledWindow. So this is a chunk which comes before column setup. :)

//in class is: Gtk::ScrolledWindow mScrollForResults;

//scrolling area
mGrid.attach(mScrollForResults, 0,2,10,1);
mScrollForResults.set_hexpand();
mScrollForResults.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC,
                             Gtk::PolicyType::POLICY_ALWAYS);
mScrollForResults.set_margin_top(10);
mScrollForResults.set_min_content_width(400);
mScrollForResults.set_min_content_height(200);
mScrollForResults.add(mTreeView);

//results treeView
mRefListStore = Gtk::ListStore::create(mColumns);
mTreeView.set_model(mRefListStore);
mTreeView.set_hexpand();
mTreeView.set_vexpand();
like image 54
kracejic Avatar answered Sep 27 '22 22:09

kracejic