8858e8b4368bc921fbf932fb32b18722692c094b
[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 GtkBuilder *
118 psppire_dialog_action_barchart_activate (PsppireDialogAction *a, GVariant *param)
119 {
120   PsppireDialogActionBarchart *act = PSPPIRE_DIALOG_ACTION_BARCHART (a);
121   PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
122
123   GtkBuilder *xml = builder_new ("barchart.ui");
124
125   pda->dialog = get_widget_assert (xml, "barchart-dialog");
126   pda->source = get_widget_assert (xml, "dict-view");
127
128   act->variable_xaxis = get_widget_assert (xml, "entry1");
129   act->variable_cluster = get_widget_assert (xml, "entry3");
130   act->var = get_widget_assert (xml, "entry2");
131   act->button_freq_func[0] = get_widget_assert (xml, "radiobutton-count");
132   act->button_freq_func[1] = get_widget_assert (xml, "radiobutton-percent");
133   act->button_freq_func[2] = get_widget_assert (xml, "radiobutton-cum-count");
134   act->button_freq_func[3] = get_widget_assert (xml, "radiobutton-cum-percent");
135
136   act->button_summary_func = get_widget_assert (xml, "radiobutton3");
137   act->summary_variables = get_widget_assert (xml, "hbox1");
138   act->combobox = get_widget_assert (xml, "combobox1");
139
140   populate_combo_model (GTK_COMBO_BOX(act->combobox));
141
142   g_signal_connect_swapped (act->button_summary_func, "toggled",
143                             G_CALLBACK (on_summary_toggle), act);
144
145   psppire_dialog_action_set_refresh (pda, refresh);
146
147   psppire_dialog_action_set_valid_predicate (pda,
148                                              dialog_state_valid);
149
150   return xml;
151 }
152
153 static char *
154 generate_syntax (const PsppireDialogAction *a)
155 {
156   PsppireDialogActionBarchart *rd = PSPPIRE_DIALOG_ACTION_BARCHART (a);
157   gchar *text;
158   const gchar *var_name_xaxis = gtk_entry_get_text (GTK_ENTRY (rd->variable_xaxis));
159   const gchar *var_name_cluster = gtk_entry_get_text (GTK_ENTRY (rd->variable_cluster));
160
161   GString *string = g_string_new ("GRAPH /BAR = ");
162
163   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_summary_func)))
164     {
165       GtkTreeIter iter;
166       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (rd->combobox), &iter))
167         {
168           GValue value = {0};
169           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (rd->combobox));
170           gtk_tree_model_get_value (model, &iter, 1, &value);
171           g_string_append (string, g_value_get_string (&value));
172           g_value_unset (&value);
173         }
174       g_string_append (string, " (");
175       g_string_append (string, gtk_entry_get_text (GTK_ENTRY (rd->var)));
176       g_string_append (string, ")");
177     }
178   else
179     {
180       int b;
181       for (b = 0; b < 4; ++b)
182         {
183           if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->button_freq_func[b])))
184             break;
185         }
186       switch (b)
187         {
188         case 0:
189           g_string_append (string, "COUNT");
190           break;
191         case 1:
192           g_string_append (string, "PCT");
193           break;
194         case 2:
195           g_string_append (string, "CUFREQ");
196           break;
197         case 3:
198           g_string_append (string, "CUPCT");
199           break;
200         default:
201           g_assert_not_reached ();
202           break;
203         }
204     }
205
206   g_string_append (string, " BY ");
207   g_string_append (string, var_name_xaxis);
208
209   if (g_strcmp0 (var_name_cluster, ""))
210   {
211     g_string_append (string, " BY ");
212     g_string_append (string, var_name_cluster);
213   }
214
215   g_string_append (string, ".\n");
216
217   text = string->str;
218
219   g_string_free (string, FALSE);
220
221   return text;
222 }
223
224 static void
225 psppire_dialog_action_barchart_class_init (PsppireDialogActionBarchartClass *class)
226 {
227   PSPPIRE_DIALOG_ACTION_CLASS (class)->initial_activate = psppire_dialog_action_barchart_activate;
228
229   PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
230 }
231
232
233 static void
234 psppire_dialog_action_barchart_init (PsppireDialogActionBarchart *act)
235 {
236 }