ee85831b6472c92097bc8ef98eb861af49e577e2
[pspp] / src / ui / gui / psppire-dialog-action-barchart.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2015  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 #include <config.h>
19
20 #include "psppire-dialog-action-barchart.h"
21 #include "psppire-value-entry.h"
22
23 #include "dialog-common.h"
24 #include <ui/syntax-gen.h>
25 #include "psppire-var-view.h"
26
27 #include "psppire-dialog.h"
28 #include "builder-wrapper.h"
29
30 #include "psppire-dict.h"
31 #include "libpspp/str.h"
32
33 #include "language/stats/chart-category.h"
34
35 static void
36 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class);
37
38 G_DEFINE_TYPE (PsppireDialogActionBarchart, psppire_dialog_action_barchart, PSPPIRE_TYPE_DIALOG_ACTION);
39
40 static gboolean
41 dialog_state_valid (gpointer rd_)
42 {
43   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (rd_);
44
45   if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)) )
46     {
47       if (0 == g_strcmp0 ("", gtk_entry_get_text (GTK_ENTRY (rd->var))))
48         return FALSE;
49     }
50
51   if (0 == g_strcmp0 ("", gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis))))
52     return FALSE;
53
54   return TRUE;
55 }
56
57 static void
58 refresh (PsppireDialogAction *rd_)
59 {
60   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (rd_);
61
62   gtk_entry_set_text (GTK_ENTRY (rd->var), "");
63   gtk_entry_set_text (GTK_ENTRY (rd->variable_xaxis), "");
64   gtk_entry_set_text (GTK_ENTRY (rd->variable_cluster), "");
65
66   /* Set summary_func to true, then let it get unset again.
67      This ensures that the signal handler gets called.   */
68   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->button_summary_func), TRUE);
69   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[0]), TRUE);
70                                 
71   gtk_widget_set_sensitive (rd->combobox, FALSE);
72
73   gtk_combo_box_set_active (GTK_COMBO_BOX (rd->combobox), 0);
74 }
75
76 static void
77 on_summary_toggle (PsppireDialogActionBarchart *act)
78 {
79   gboolean status = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->button_summary_func));
80
81   gtk_widget_set_sensitive (act->summary_variables, status);
82   gtk_widget_set_sensitive (act->combobox, status);
83 }
84
85 static void
86 populate_combo_model (GtkComboBox *cb)
87 {
88   int i;
89   GtkListStore *list =  gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
90   GtkTreeIter iter;
91   GtkCellRenderer *renderer ;
92
93   for (i = 0; i < N_AG_FUNCS;  ++i)
94     {
95       const struct ag_func *af = ag_func + i;
96
97       if (af->arity == 0)
98         continue;
99
100       gtk_list_store_append (list, &iter);
101       gtk_list_store_set (list, &iter,
102                           0, af->description,
103                           1, af->name,
104                           -1);
105     }
106
107   renderer = gtk_cell_renderer_text_new ();
108   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), renderer, FALSE);
109
110   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (cb), renderer, "text", 0);
111
112   gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (list));
113   g_object_unref (list);
114 }
115
116
117 static void
118 psppire_dialog_action_barchart_activate (PsppireDialogAction *a)
119 {
120   PsppireDialogActionBarchart *act = PSPPIRE_DIALOG_ACTION_BARCHART (a);
121   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
122
123   GHashTable *thing = psppire_dialog_action_get_hash_table (pda);
124   GtkBuilder *xml = g_hash_table_lookup (thing, a);
125   if (!xml)
126     {
127       xml = builder_new ("barchart.ui");
128       g_hash_table_insert (thing, a, xml);
129
130       pda->dialog = get_widget_assert (xml, "barchart-dialog");
131       pda->source = get_widget_assert (xml, "dict-view");
132
133       act->variable_xaxis = get_widget_assert (xml, "entry1");
134       act->variable_cluster = get_widget_assert (xml, "entry3");
135       act->var = get_widget_assert (xml, "entry2");
136       act->button_freq_func[0] = get_widget_assert (xml, "radiobutton-count");
137       act->button_freq_func[1] = get_widget_assert (xml, "radiobutton-percent");
138       act->button_freq_func[2] = get_widget_assert (xml, "radiobutton-cum-count");
139       act->button_freq_func[3] = get_widget_assert (xml, "radiobutton-cum-percent");
140   
141       act->button_summary_func = get_widget_assert (xml, "radiobutton3");
142       act->summary_variables = get_widget_assert (xml, "hbox1");
143       act->combobox = get_widget_assert (xml, "combobox1");
144
145       populate_combo_model (GTK_COMBO_BOX(act->combobox));
146   
147       g_signal_connect_swapped (act->button_summary_func, "toggled",
148                                 G_CALLBACK (on_summary_toggle), act);
149
150       psppire_dialog_action_set_refresh (pda, refresh);
151
152       psppire_dialog_action_set_valid_predicate (pda,
153                                                  dialog_state_valid);
154     }
155
156 }
157
158 static char *
159 generate_syntax (const PsppireDialogAction *a)
160 {
161   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (a);
162   gchar *text;
163   const gchar *var_name_xaxis = gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis));
164   const gchar *var_name_cluster = gtk_entry_get_text (GTK_ENTRY (rd->variable_cluster));
165
166   GString *string = g_string_new ("GRAPH /BAR = ");
167
168   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)))
169     {
170       GtkTreeIter iter;
171       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (rd->combobox), &iter))
172         {
173           GValue value = {0};
174           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (rd->combobox));
175           gtk_tree_model_get_value (model, &iter, 1, &value);
176           g_string_append (string, g_value_get_string (&value));
177           g_value_unset (&value);
178         }
179       g_string_append (string, " (");
180       g_string_append (string, gtk_entry_get_text (GTK_ENTRY (rd->var)));
181       g_string_append (string, ")");
182     }
183   else
184     {
185       int b;
186       for (b = 0; b < 4; ++b)
187         {
188           if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[b])))
189             break;
190         }
191       switch (b)
192         {
193         case 0:
194           g_string_append (string, "COUNT");
195           break;
196         case 1:
197           g_string_append (string, "PCT");
198           break;
199         case 2:
200           g_string_append (string, "CUFREQ");
201           break;
202         case 3:
203           g_string_append (string, "CUPCT");
204           break;
205         default:
206           g_assert_not_reached ();
207           break;
208         }
209     }
210
211   g_string_append (string, " BY ");
212   g_string_append (string, var_name_xaxis);
213
214   if (g_strcmp0 (var_name_cluster, ""))
215   {
216     g_string_append (string, " BY ");
217     g_string_append (string, var_name_cluster);
218   }
219   
220   g_string_append (string, ".\n");
221
222   text = string->str;
223
224   g_string_free (string, FALSE);
225
226   return text;
227 }
228
229 static void
230 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class)
231 {
232   psppire_dialog_action_set_activation (class, psppire_dialog_action_barchart_activate);
233
234   PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
235 }
236
237
238 static void
239 psppire_dialog_action_barchart_init (PsppireDialogActionBarchart *act)
240 {
241 }