/* * TilEm II * * Copyright (c) 2011 Benjamin Moody * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "fixedtreeview.h" /* Style set on tree view; update column sizes */ static void ftv_style_set(GtkWidget *treeview, G_GNUC_UNUSED GtkStyle *oldstyle, G_GNUC_UNUSED gpointer data) { GtkTreeModel *template; GtkTreeIter iter; GList *cols, *cp; GtkTreeViewColumn *col; int width; template = g_object_get_data(G_OBJECT(treeview), "ftv-template"); if (!template) return; if (!gtk_tree_model_get_iter_first(template, &iter)) return; cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(treeview)); for (cp = cols; cp; cp = cp->next) { col = cp->data; gtk_tree_view_column_cell_set_cell_data(col, template, &iter, FALSE, FALSE); gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, &width, NULL); gtk_tree_view_column_set_fixed_width(col, width + 2); } g_list_free(cols); } /* Widget destroyed */ static void ftv_destroy(GtkWidget *treeview, G_GNUC_UNUSED gpointer data) { GtkTreeModel *template; template = g_object_get_data(G_OBJECT(treeview), "ftv-template"); if (template) g_object_unref(template); g_object_set_data(G_OBJECT(treeview), "ftv-template", NULL); } void fixed_tree_view_init_with_template(GtkWidget *treeview, GtkTreeModel *template) { GtkTreeModel *oldtemplate; if (template) g_object_ref_sink(template); oldtemplate = g_object_get_data(G_OBJECT(treeview), "ftv-template"); if (oldtemplate) { g_object_unref(oldtemplate); } else { g_signal_connect(treeview, "style-set", G_CALLBACK(ftv_style_set), NULL); g_signal_connect(treeview, "destroy", G_CALLBACK(ftv_destroy), NULL); } g_object_set_data(G_OBJECT(treeview), "ftv-template", template); if (template && GTK_WIDGET_REALIZED(treeview)) ftv_style_set(treeview, NULL, NULL); } void fixed_tree_view_init(GtkWidget *treeview, int colgroupsize, ...) { GtkTreeModel *real_model; int ncols, i, col; GType *types; GtkListStore *store; GtkTreeIter iter; GValue value; gchar *error = NULL; va_list ap; g_return_if_fail(GTK_IS_TREE_VIEW(treeview)); g_return_if_fail(colgroupsize >= 0); real_model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); g_return_if_fail(real_model != NULL); ncols = gtk_tree_model_get_n_columns(real_model); g_return_if_fail(ncols > 0); if (colgroupsize == 0) colgroupsize = ncols; g_return_if_fail(ncols % colgroupsize == 0); types = g_new(GType, ncols); for (i = 0; i < ncols; i++) { types[i] = gtk_tree_model_get_column_type(real_model, i); if (i > colgroupsize) g_return_if_fail(types[i] == types[i - colgroupsize]); } store = gtk_list_store_newv(ncols, types); va_start(ap, colgroupsize); gtk_list_store_append(store, &iter); memset(&value, 0, sizeof(value)); col = va_arg(ap, int); while (col != -1) { if (col < 0 || col >= colgroupsize) { g_critical("missing sentinel"); break; } g_value_init(&value, types[col]); G_VALUE_COLLECT(&value, ap, 0, &error); if (error) { g_critical("%s", error); g_free(error); break; } for (i = col; i < ncols; i += colgroupsize) gtk_list_store_set_value(store, &iter, i, &value); g_value_unset(&value); col = va_arg(ap, int); } va_end(ap); g_free(types); fixed_tree_view_init_with_template(treeview, GTK_TREE_MODEL(store)); }