ti83-sdk/tool/tilem-src/gui/fixedtreeview.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));
}