Rename psppire_dialog_action_get_pointer -> psppire_dialog_action_get_hash_table
[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 (GtkAction *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   if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_barchart_parent_class)->activate)
157     PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_barchart_parent_class)->activate (pda);
158 }
159
160 static char *
161 generate_syntax (PsppireDialogAction *a)
162 {
163   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (a);
164   gchar *text;
165   const gchar *var_name_xaxis = gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis));
166   const gchar *var_name_cluster = gtk_entry_get_text (GTK_ENTRY (rd->variable_cluster));
167
168   GString *string = g_string_new ("GRAPH /BAR = ");
169
170   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)))
171     {
172       GtkTreeIter iter;
173       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (rd->combobox), &iter))
174         {
175           GValue value = {0};
176           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (rd->combobox));
177           gtk_tree_model_get_value (model, &iter, 1, &value);
178           g_string_append (string, g_value_get_string (&value));
179           g_value_unset (&value);
180         }
181       g_string_append (string, " (");
182       g_string_append (string, gtk_entry_get_text (GTK_ENTRY (rd->var)));
183       g_string_append (string, ")");
184     }
185   else
186     {
187       int b;
188       for (b = 0; b < 4; ++b)
189         {
190           if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[b])))
191             break;
192         }
193       switch (b)
194         {
195         case 0:
196           g_string_append (string, "COUNT");
197           break;
198         case 1:
199           g_string_append (string, "PCT");
200           break;
201         case 2:
202           g_string_append (string, "CUFREQ");
203           break;
204         case 3:
205           g_string_append (string, "CUPCT");
206           break;
207         default:
208           g_assert_not_reached ();
209           break;
210         }
211     }
212
213   g_string_append (string, " BY ");
214   g_string_append (string, var_name_xaxis);
215
216   if (g_strcmp0 (var_name_cluster, ""))
217   {
218     g_string_append (string, " BY ");
219     g_string_append (string, var_name_cluster);
220   }
221   
222   g_string_append (string, ".\n");
223
224   text = string->str;
225
226   g_string_free (string, FALSE);
227
228   return text;
229 }
230
231 static void
232 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class)
233 {
234   psppire_dialog_action_set_activation (class, psppire_dialog_action_barchart_activate);
235
236   PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
237 }
238
239
240 static void
241 psppire_dialog_action_barchart_init (PsppireDialogActionBarchart *act)
242 {
243 }