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