5.3. Cell Data Functions

A cell data function is a function that is called for a specific cell renderer for each single row before that row is rendered. It gives you maximum control over what exactly is going to be rendered, as you can set the cell renderer's properties just like you want to have them. Remember not only to set a property if you want it to be active, but also to unset a property if it should not be active (and it might have been set in the previous row).

Cell data functions are often used if you want more fine-grained control over what is to be displayed, or if the standard way to display something is not quite like you want it to be. A case in point are floating point numbers. If you want floating point numbers to be displayed in a certain way, say with only one digit after the colon/comma, then you need to use a cell data function. Use gtk_tree_view_column_set_cell_data_func to set up a cell data function for a particular cell renderer. Here is an example:


   enum
   {
     COLUMN_NAME = 0,
     COLUMN_AGE_FLOAT,
     NUM_COLS
   };

   ...

   void
   age_cell_data_function (GtkTreeViewColumn *col,
                           GtkCellRenderer   *renderer,
                           GtkTreeModel      *model,
                           GtkTreeIter       *iter,
                           gpointer           user_data)
   {
     gfloat  age;
     gchar   buf[20];

     gtk_tree_model_get(model, iter, COLUMN_AGE_FLOAT, &age, -1);

     g_snprintf(buf, sizeof(buf), "%.1f", age);

     g_object_set(renderer, "text", buf, NULL);
   }

   ...

   liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_FLOAT);

   col = gtk_tree_view_column_new();

   cell = gtk_cell_renderer_text_new();

   gtk_tree_view_column_pack_start(col, cell, TRUE);

   gtk_tree_view_column_set_cell_data_func(col, cell, age_cell_data_func, NULL, NULL);

   ...

for each row to be rendered by this particular cell renderer, the cell data function is going to be called, which then retrieves the float from the mode, and turns it into a string where the float has only one digit after the colon/comma, and renders that with the text cell renderer.

This is only a simple example, you can make cell data functions a lot more complicated if you want to. As always, there is a trade-off to keep in mind though. Your cell data function is going to be called every single time a cell in that (renderer) column is going to be rendered. Go and check how often this function is called in your program if you ever use one. If you do time-consuming operations within a cell data function, things are not going to be fast, especially if you have a lot of rows. The alternative in this case would have been to make an additional column COLUMN_AGE_FLOAT_STRING of type G_TYPE_STRING, and to set the float in string form whenever you set the float itself in a row, and then hook up the string column to a text cell renderer using attributes. This way the float to string conversion would only need to be done once. This is a cpu cycles / memory trade-off, and it depends on your particular case which one is more suitable. Things you should probably not do is to convert long strings into UTF8 format in a cell data function, for example.

You might notice that your cell data function is called at times even for rows that are not visible at the moment. This is because the tree view needs to know its total height, and in order to calculate this it needs to know the height of each and every single row, and it can only know that by having it measured, which is going to be slow when you have a lot of rows with different heights (if your rows all have the same height, there should not be any visible delay though).