Replace checkbox-treeview functions with a object PsppireCheckboxTreeview
[pspp] / src / ui / gui / psppire-checkbox-treeview.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2012, 2013  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17
18 /* 
19    This module provides a subclass of GtkTreeView, designed for dialogs
20    which need lists of annotated checkbox items.
21    The object contains the necessary model and renderers, which means that
22    the user does not have to create these herself.
23  */
24
25 #include <config.h>
26 #include <gtk/gtk.h>
27
28 #include "psppire-checkbox-treeview.h"
29
30
31 #include "gettext.h"
32 #define _(msgid) gettext (msgid)
33 #define N_(msgid) msgid
34
35 static void psppire_checkbox_treeview_init          (PsppireCheckboxTreeview      *cbtv);
36
37 GType
38 psppire_checkbox_treeview_get_type (void)
39 {
40   static GType psppire_checkbox_treeview_type = 0;
41
42   if (!psppire_checkbox_treeview_type)
43     {
44       static const GTypeInfo psppire_checkbox_treeview_info =
45       {
46         sizeof (PsppireCheckboxTreeviewClass),
47         (GBaseInitFunc) NULL,
48         (GBaseFinalizeFunc) NULL,
49         (GClassInitFunc) NULL,
50         (GClassFinalizeFunc) NULL,
51         NULL,
52         sizeof (PsppireCheckboxTreeview),
53         0,
54         (GInstanceInitFunc) psppire_checkbox_treeview_init,
55       };
56
57       psppire_checkbox_treeview_type =
58         g_type_register_static (GTK_TYPE_TREE_VIEW, "PsppireCheckboxTreeview",
59                                 &psppire_checkbox_treeview_info, 0);
60     }
61
62   return psppire_checkbox_treeview_type;
63 }
64
65
66
67 /* Callback for checkbox cells in the statistics tree view.
68    Toggles the checkbox. */
69 static void
70 toggle (GtkCellRendererToggle *cell_renderer, const gchar *path_str, gpointer data)
71 {
72   GtkTreeView *tv = GTK_TREE_VIEW (data);
73   GtkTreeModel *model = gtk_tree_view_get_model (tv);
74   GtkTreeIter iter;
75   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
76   gboolean selected;
77
78   gtk_tree_model_get_iter (model, &iter, path);
79   gtk_tree_model_get (model, &iter, CHECKBOX_COLUMN_SELECTED, &selected, -1);
80   gtk_list_store_set (GTK_LIST_STORE (model), &iter, CHECKBOX_COLUMN_SELECTED,
81                       !selected, -1);
82   gtk_tree_path_free (path);
83 }
84
85 /* Create the necessary columns and renderers and add them to the widget */
86 static void
87 treeview_checkbox_populate (GtkTreeView *treeview)
88 {
89   /* Checkbox column. */
90   GtkTreeViewColumn *col = gtk_tree_view_column_new ();
91   GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
92
93   gtk_tree_view_column_pack_start (col, renderer, TRUE);
94
95   gtk_tree_view_append_column (treeview, col);
96
97   gtk_tree_view_column_add_attribute  (col, renderer, "active", CHECKBOX_COLUMN_SELECTED);
98
99   g_signal_connect (renderer, "toggled", G_CALLBACK (toggle), treeview);
100
101   /* Label column. */
102   col = gtk_tree_view_column_new ();
103   gtk_tree_view_column_set_title (col, _("Statistic"));
104   renderer = gtk_cell_renderer_text_new ();
105   gtk_tree_view_column_pack_start (col, renderer, TRUE);
106
107   gtk_tree_view_column_add_attribute  (col, renderer, "text", CHECKBOX_COLUMN_LABEL);
108
109   g_object_set (renderer, "ellipsize-set", TRUE, NULL);
110   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
111   gtk_tree_view_column_set_min_width (col, 200);
112   gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
113   gtk_tree_view_column_set_resizable (col, TRUE);
114   gtk_tree_view_append_column (treeview, col);
115 }
116
117 static void
118 psppire_checkbox_treeview_init (PsppireCheckboxTreeview *cbtv)
119 {
120   cbtv->list = GTK_TREE_MODEL (gtk_list_store_new (N_CHECKBOX_COLUMNS,
121                                                   G_TYPE_STRING, 
122                                                   G_TYPE_BOOLEAN));
123
124   gtk_tree_view_set_model (GTK_TREE_VIEW (cbtv), cbtv->list);
125   g_object_unref (cbtv->list);
126
127   treeview_checkbox_populate (GTK_TREE_VIEW (cbtv));
128 }
129
130
131 /*
132   Load the object's model from the array ITEMS.
133   N_ITEMS is the size of the array.
134   DEFAULT_ITEMS is a bitwise field indicating the initial state
135   of the items.
136 */
137 void
138 psppire_checkbox_treeview_populate (PsppireCheckboxTreeview *cbtv,
139                                     guint default_items,
140                                     gint n_items,
141                                     const struct checkbox_entry_item *items)
142 {
143   size_t i;
144   for (i = 0; i < n_items; ++i)
145     {
146       GtkTreeIter iter;
147       gtk_list_store_append (GTK_LIST_STORE (cbtv->list), &iter);
148       gtk_list_store_set (GTK_LIST_STORE (cbtv->list), &iter,
149                           CHECKBOX_COLUMN_LABEL, gettext (items[i].label),
150                           CHECKBOX_COLUMN_SELECTED,
151                           (default_items & (1u << i)) != 0,
152                           -1);
153     }
154
155 }