Implemented a dialog box for the ONEWAY command.
[pspp-builds.git] / src / ui / gui / psppire-acr.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007 Free Software Foundation, Inc.
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 #include <gtk/gtk.h>
18
19 #include "psppire-acr.h"
20
21 static void psppire_acr_init (PsppireAcr *);
22
23 enum {
24   COLUMN_DOUBLE,
25   n_COLUMNS
26 };
27
28
29 GType
30 psppire_acr_get_type (void)
31 {
32   static GType acr_type = 0;
33
34   if (!acr_type)
35     {
36       static const GTypeInfo acr_info =
37       {
38         sizeof (PsppireAcrClass),
39         NULL, /* base_init */
40         NULL, /* base_finalize */
41         NULL, /* class_init */
42         NULL, /* class_finalize */
43         NULL, /* class_data */
44         sizeof (PsppireAcr),
45         0,
46         (GInstanceInitFunc) psppire_acr_init,
47       };
48
49       acr_type = g_type_register_static (GTK_TYPE_HBOX, "PsppireAcr",
50                                         &acr_info, 0);
51     }
52
53   return acr_type;
54 }
55
56 static void
57 on_add_button_clicked (PsppireAcr *acr)
58 {
59   GtkTreeIter iter;
60   gdouble x;
61
62   const gchar *text = gtk_entry_get_text (acr->entry);
63   x = g_strtod (text, 0);
64
65   gtk_list_store_append (acr->list_store, &iter);
66
67   gtk_list_store_set (acr->list_store, &iter,
68                       COLUMN_DOUBLE, x,
69                       -1);
70
71   gtk_entry_set_text (acr->entry, "");
72 }
73
74 static void
75 on_change_button_clicked (PsppireAcr *acr)
76 {
77   const gchar *text;
78   GValue value = {0};
79   GtkTreeModel *model = GTK_TREE_MODEL (acr->list_store);
80
81   GList *l=
82     gtk_tree_selection_get_selected_rows (acr->selection,
83                                           &model);
84
85   GtkTreePath *path = l->data;
86
87   GtkTreeIter iter;
88
89   gtk_tree_model_get_iter (model, &iter, path);
90
91   text = gtk_entry_get_text (acr->entry);
92
93   g_value_init (&value, G_TYPE_DOUBLE);
94   g_value_set_double (&value, g_strtod (text, NULL));
95   gtk_list_store_set_value (acr->list_store, &iter, 0, &value);
96
97   g_list_foreach (l, (GFunc) gtk_tree_path_free, NULL);
98   g_list_free (l);
99 }
100
101 static void
102 on_remove_button_clicked (PsppireAcr *acr)
103 {
104   GtkTreeModel *model = GTK_TREE_MODEL (acr->list_store);
105
106   GList *l=
107     gtk_tree_selection_get_selected_rows (acr->selection,
108                                           &model);
109
110   GtkTreePath *path = l->data;
111
112   GtkTreeIter iter;
113
114   gtk_tree_model_get_iter (model, &iter, path);
115
116   gtk_list_store_remove (acr->list_store, &iter);
117
118   g_list_foreach (l, (GFunc) gtk_tree_path_free, NULL);
119   g_list_free (l);
120 }
121
122 static gboolean
123 value_present (const PsppireAcr *acr)
124 {
125   const char *text = gtk_entry_get_text (acr->entry);
126   return !g_str_equal (text, "");
127 }
128
129 static gboolean
130 row_is_selected (PsppireAcr *acr)
131 {
132   gboolean result;
133   GtkTreeModel *model = GTK_TREE_MODEL (acr->list_store);
134   GList *l = gtk_tree_selection_get_selected_rows (acr->selection,
135                                                    &model);
136
137   result = (l != NULL);
138
139   g_list_foreach (l, (GFunc) gtk_tree_path_free, NULL);
140   g_list_free (l);
141
142   return result;
143 }
144
145
146 static void
147 on_select (GtkTreeSelection *selection, gpointer data)
148 {
149   PsppireAcr *acr = data;
150
151   gtk_widget_set_sensitive (acr->remove_button, row_is_selected (acr));
152
153   gtk_widget_set_sensitive (acr->change_button,
154                             row_is_selected (acr) && value_present (acr));
155 }
156
157
158
159 static void
160 psppire_acr_init (PsppireAcr *acr)
161 {
162   GtkWidget *bb  = gtk_vbutton_box_new ();
163
164   GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
165
166   acr->tv = GTK_TREE_VIEW (gtk_tree_view_new ());
167
168   acr->add_button = gtk_button_new_from_stock (GTK_STOCK_ADD);
169   acr->change_button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
170   acr->remove_button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
171
172   gtk_widget_set_sensitive (acr->change_button, FALSE);
173   gtk_widget_set_sensitive (acr->remove_button, FALSE);
174   gtk_widget_set_sensitive (acr->add_button, FALSE);
175
176   gtk_box_pack_start_defaults (GTK_BOX (bb), acr->add_button);
177   gtk_box_pack_start_defaults (GTK_BOX (bb), acr->change_button);
178   gtk_box_pack_start_defaults (GTK_BOX (bb), acr->remove_button);
179
180   gtk_box_pack_start (GTK_BOX (acr), bb, FALSE, TRUE, 5);
181
182   g_object_set (sw,
183                 "hscrollbar-policy", GTK_POLICY_NEVER,
184                 "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
185                 "shadow-type", GTK_SHADOW_ETCHED_IN,
186                 NULL);
187
188   gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (acr->tv));
189
190   gtk_box_pack_start (GTK_BOX (acr), sw, TRUE, TRUE, 5);
191
192
193   g_signal_connect_swapped (acr->add_button, "clicked",
194                             G_CALLBACK (on_add_button_clicked), acr);
195   g_signal_connect_swapped (acr->change_button, "clicked",
196                             G_CALLBACK (on_change_button_clicked), acr);
197   g_signal_connect_swapped (acr->remove_button, "clicked",
198                             G_CALLBACK (on_remove_button_clicked), acr);
199
200   gtk_widget_show_all (bb);
201
202
203   g_object_set (acr->tv, "headers-visible", FALSE, NULL);
204
205   acr->list_store = NULL;
206
207   psppire_acr_set_model (acr, acr->list_store);
208
209   acr->selection = gtk_tree_view_get_selection (acr->tv);
210
211   g_signal_connect (acr->selection, "changed", G_CALLBACK (on_select), acr);
212
213   gtk_widget_set_sensitive (GTK_WIDGET (acr), FALSE);
214
215   gtk_widget_show_all (sw);
216
217   {
218     GtkCellRenderer *renderer;
219     GtkTreeViewColumn *column;
220
221     renderer = gtk_cell_renderer_text_new ();
222     column = gtk_tree_view_column_new_with_attributes ("header",
223                                                        renderer,
224                                                        "text", COLUMN_DOUBLE,
225                                                        NULL);
226
227     gtk_tree_view_append_column (acr->tv, column);
228   }
229
230   acr->entry = NULL;
231 }
232
233
234 GtkWidget*
235 psppire_acr_new (void)
236 {
237   return GTK_WIDGET (g_object_new (psppire_acr_get_type (), NULL));
238 }
239
240 static void
241 on_entry_change (GtkEntry *entry, PsppireAcr *acr)
242 {
243   gtk_widget_set_sensitive (acr->add_button, value_present (acr));
244
245   gtk_widget_set_sensitive (acr->change_button, value_present (acr)
246                             && row_is_selected (acr));
247 }
248
249 void
250 psppire_acr_set_entry  (PsppireAcr *acr, GtkEntry *entry)
251 {
252   acr->entry = entry;
253
254   g_signal_connect (entry, "changed", G_CALLBACK (on_entry_change), acr);
255 }
256
257
258
259 /* Set the widget's treemodel */
260 void
261 psppire_acr_set_model (PsppireAcr *acr, GtkListStore *liststore)
262 {
263   acr->list_store = liststore;
264
265   gtk_tree_view_set_model (GTK_TREE_VIEW (acr->tv),
266                            GTK_TREE_MODEL (liststore));
267
268   gtk_widget_set_sensitive (GTK_WIDGET (acr), liststore != NULL);
269 }