166 lines
4.2 KiB
C
166 lines
4.2 KiB
C
|
/*
|
||
|
* 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include <config.h>
|
||
|
#endif
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
#include <gtk/gtk.h>
|
||
|
#include <gobject/gvaluecollector.h>
|
||
|
|
||
|
#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));
|
||
|
}
|