Fixed bug reporting the significance of paired value t-test.
[pspp-builds.git] / src / ui / gui / var-type-dialog.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2     Copyright (C) 2005, 2006  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 /*  This module describes the behaviour of the Variable Type dialog box used
19     for inputing the variable type in the var sheet */
20
21 #include <config.h>
22
23 #include <gtk/gtk.h>
24 #include <glade/glade.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "var-type-dialog.h"
30
31 #include "helper.h"
32
33 #include <data/variable.h>
34 #include <data/settings.h>
35 #include <libpspp/message.h>
36
37
38 struct tgs
39 {
40   struct var_type_dialog *dialog;
41   gint button;
42 };
43
44
45 struct format_opt {
46   gchar desc[21];
47   struct fmt_spec spec;
48 };
49
50
51 static const struct format_opt format_option[] =
52   {
53     { "dd-mmm-yyyy", {FMT_DATE,  11, 0} },
54     { "dd-mmm-yy",   {FMT_DATE,   9, 0} },
55     { "mm/dd/yyyy",  {FMT_ADATE, 10, 0} },
56     { "mm/dd/yy",    {FMT_ADATE, 8, 0} },
57     { "dd.mm.yyyy",  {FMT_EDATE, 10, 0} },
58     { "dd.mm.yy",    {FMT_EDATE, 8, 0} },
59     { "yyyy/mm/dd",  {FMT_SDATE, 10, 0} },
60     { "yy/mm/dd",    {FMT_SDATE, 8, 0} },
61     { "yyddd",       {FMT_JDATE, 5, 0} },
62     { "yyyyddd",     {FMT_JDATE, 7, 0} },
63     { "q Q yyyy",    {FMT_QYR, 8, 0} },
64     { "q Q yy",      {FMT_QYR, 6, 0} },
65     { "mmm yyyy",    {FMT_MOYR, 8, 0} },
66     { "mmm yy",      {FMT_MOYR, 6, 0} },
67     { "dd WK yyyy",  {FMT_WKYR, 10, 0} },
68     { "dd WK yy",    {FMT_WKYR, 8, 0} },
69     { "dd-mmm-yyyy HH:MM", {FMT_DATETIME, 17, 0}},
70     { "dd-mmm-yyyy HH:MM:SS", {FMT_DATETIME, 20, 0}}
71   };
72
73
74 static const struct fmt_spec dollar_format[] =
75   {
76     {FMT_DOLLAR, 2, 0},
77     {FMT_DOLLAR, 3, 0},
78     {FMT_DOLLAR, 4, 0},
79     {FMT_DOLLAR, 7, 2},
80     {FMT_DOLLAR, 6, 0},
81     {FMT_DOLLAR, 9, 2},
82     {FMT_DOLLAR, 8, 0},
83     {FMT_DOLLAR, 11, 2},
84     {FMT_DOLLAR, 12, 0},
85     {FMT_DOLLAR, 15, 2},
86     {FMT_DOLLAR, 16, 0},
87     {FMT_DOLLAR, 19, 2}
88   };
89
90 static const int cc_format[] =
91   {
92     FMT_CCA,
93     FMT_CCB,
94     FMT_CCC,
95     FMT_CCD,
96     FMT_CCE,
97   };
98
99
100 static void select_treeview_from_format
101  (GtkTreeView *treeview, const struct fmt_spec *fmt);
102
103 static void select_treeview_from_format_type (GtkTreeView *treeview,
104                                              const int fmt_type);
105
106
107 /* callback for when any of the radio buttons are toggled */
108 static void
109 on_toggle_1 (GtkToggleButton *togglebutton, gpointer user_data)
110 {
111   struct tgs *tgs = user_data;
112
113   if ( gtk_toggle_button_get_active (togglebutton) == FALSE)
114     return ;
115
116   tgs->dialog->active_button = tgs->button;
117 }
118
119 static void update_width_decimals (const struct var_type_dialog *dialog);
120
121 #define force_max(x, val) if (x > val) x = val
122
123 /*
124    Set the local format from the variable
125    and force them to have sensible values */
126 static void
127 set_local_width_decimals (struct var_type_dialog *dialog)
128 {
129   dialog->fmt_l = * var_get_write_format (dialog->pv);
130
131   switch (dialog->active_button)
132     {
133     case BUTTON_STRING:
134       force_max ( dialog->fmt_l.w, 255);
135       break;
136     default:
137       force_max ( dialog->fmt_l.w, 40);
138       force_max ( dialog->fmt_l.d, 16);
139       break;
140     }
141 }
142
143
144 /* callback for when any of the radio buttons are toggled */
145 static void
146 on_toggle_2 (GtkToggleButton *togglebutton, gpointer user_data)
147 {
148   struct var_type_dialog *dialog = user_data;
149   if ( gtk_toggle_button_get_active (togglebutton) == FALSE)
150     {
151       switch (dialog->active_button)
152         {
153         case BUTTON_DATE:
154           gtk_widget_hide (dialog->date_format_list);
155           break;
156         case BUTTON_CUSTOM:
157           gtk_widget_hide (dialog->custom_currency_hbox);
158           break;
159         case BUTTON_DOLLAR:
160           gtk_widget_hide (dialog->dollar_window);
161           break;
162         case BUTTON_STRING:
163           gtk_widget_show (dialog->label_decimals);
164           gtk_widget_show (dialog->entry_decimals);
165           break;
166         }
167       return ;
168     }
169
170   set_local_width_decimals (dialog);
171   update_width_decimals (dialog);
172
173   switch (dialog->active_button)
174     {
175     case BUTTON_STRING:
176       gtk_widget_show (dialog->entry_width);
177       gtk_widget_show (dialog->width_decimals);
178       gtk_widget_hide (dialog->label_decimals);
179       gtk_widget_hide (dialog->entry_decimals);
180       break;
181     case BUTTON_DATE:
182       select_treeview_from_format (dialog->date_format_treeview,
183                                   &format_option[0].spec);
184       gtk_widget_hide (dialog->width_decimals);
185       gtk_widget_show (dialog->date_format_list);
186       break;
187     case BUTTON_DOLLAR:
188       select_treeview_from_format (dialog->dollar_treeview,
189                                   &dollar_format[0]);
190       gtk_widget_show (dialog->dollar_window);
191       gtk_widget_show_all (dialog->width_decimals);
192       break;
193     case BUTTON_CUSTOM:
194       select_treeview_from_format_type (dialog->custom_treeview,
195                                   cc_format[0]);
196
197       gtk_widget_show (dialog->width_decimals);
198       gtk_widget_show (dialog->custom_currency_hbox);
199       break;
200     default:
201       gtk_widget_show_all (dialog->width_decimals);
202       break;
203     }
204 }
205
206
207
208 static gint on_var_type_ok_clicked (GtkWidget *w, gpointer data);
209 static gint hide_dialog (GtkWidget *w,  gpointer data);
210
211
212 static void
213 add_to_group (GtkWidget *w, gpointer data)
214 {
215   GtkSizeGroup *sg = data;
216
217   gtk_size_group_add_widget (sg, w);
218 }
219
220 /* Set the local width and decimals entry boxes to reflec the local format */
221 static void
222 update_width_decimals (const struct var_type_dialog *dialog)
223 {
224   gchar *text;
225   g_assert (dialog);
226
227   text = g_strdup_printf ("%d", dialog->fmt_l.w);
228   gtk_entry_set_text (GTK_ENTRY (dialog->entry_width), text);
229   g_free (text);
230
231   text = g_strdup_printf ("%d", dialog->fmt_l.d);
232   gtk_entry_set_text (GTK_ENTRY (dialog->entry_decimals), text);
233   g_free (text);
234 }
235
236 /* Callback for when the custom treeview row is changed.
237    It sets dialog box to reflect the selected format */
238 static void
239 preview_custom (GtkWidget *w, gpointer data)
240 {
241   const gchar *text ;
242
243   struct var_type_dialog *dialog = data;
244
245   if ( dialog->active_button != BUTTON_CUSTOM )
246     return;
247
248   text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals));
249   dialog->fmt_l.d = atoi (text);
250
251   text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_width));
252   dialog->fmt_l.w = atoi (text);
253
254   msg_disable ();
255   if ( ! fmt_check_output (&dialog->fmt_l))
256     {
257       gtk_label_set_text (GTK_LABEL (dialog->label_psample), "---");
258       gtk_label_set_text (GTK_LABEL (dialog->label_nsample), "---");
259     }
260   else
261     {
262       gchar *sample_text;
263       union value v;
264       v.f = 1234.56;
265
266       sample_text = value_to_text (v, dialog->fmt_l);
267       gtk_label_set_text (GTK_LABEL (dialog->label_psample), sample_text);
268       g_free (sample_text);
269
270       v.f = -v.f;
271       sample_text = value_to_text (v, dialog->fmt_l);
272       gtk_label_set_text (GTK_LABEL (dialog->label_nsample), sample_text);
273       g_free (sample_text);
274     }
275   msg_enable ();
276 }
277
278 /* Callback for when a treeview row is changed.
279    It sets the fmt_l_spec to reflect the selected format */
280 static void
281 set_format_from_treeview (GtkTreeView *treeview, gpointer data)
282 {
283   struct var_type_dialog *dialog = data;
284   GtkTreeIter iter ;
285   GValue the_value = {0};
286
287   GtkTreeSelection* sel =  gtk_tree_view_get_selection (treeview);
288
289   GtkTreeModel * model  = gtk_tree_view_get_model (treeview);
290
291   gtk_tree_selection_get_selected (sel, &model, &iter);
292
293   gtk_tree_model_get_value (model, &iter, 1, &the_value);
294
295   dialog->fmt_l = *(struct fmt_spec *) g_value_get_pointer (&the_value);
296 }
297
298
299 /* Callback for when a treeview row is changed.
300    It sets the type of the fmt_l to reflect the selected type */
301 static void
302 set_format_type_from_treeview (GtkTreeView *treeview, gpointer data)
303 {
304   static struct fmt_spec custom_format = {0,0,0};
305   struct var_type_dialog *dialog = data;
306   GtkTreeIter iter ;
307   GValue the_value = {0};
308
309   GtkTreeSelection* sel =  gtk_tree_view_get_selection (treeview);
310
311   GtkTreeModel * model  = gtk_tree_view_get_model (treeview);
312
313   gtk_tree_selection_get_selected (sel, &model, &iter);
314
315   gtk_tree_model_get_value (model, &iter, 1, &the_value);
316
317   dialog->fmt_l = custom_format;
318   dialog->fmt_l.type = *(int*) g_value_get_pointer (&the_value);
319
320 }
321
322
323
324
325 /* Create the structure from the XML definitions */
326 struct var_type_dialog *
327 var_type_dialog_create (GladeXML *xml)
328 {
329   gint i;
330   struct var_type_dialog *dialog = g_malloc (sizeof (struct var_type_dialog));
331
332   g_assert (xml);
333
334   dialog->window = get_widget_assert (xml,"var_type_dialog");
335   dialog->active_button = -1;
336
337
338   g_signal_connect (dialog->window, "delete-event",
339                     G_CALLBACK (gtk_widget_hide_on_delete), NULL);
340
341   gtk_window_set_transient_for (GTK_WINDOW (dialog->window),
342                                GTK_WINDOW (get_widget_assert (xml, "data_editor")));
343
344   dialog->radioButton[BUTTON_NUMERIC] =
345     get_widget_assert (xml,"radiobutton1");
346   dialog->radioButton[BUTTON_COMMA] =
347     get_widget_assert (xml,"radiobutton2");
348   dialog->radioButton[BUTTON_DOT] =
349     get_widget_assert (xml,"radiobutton3");
350   dialog->radioButton[BUTTON_SCIENTIFIC] =
351     get_widget_assert (xml,"radiobutton4");
352   dialog->radioButton[BUTTON_DATE] =
353     get_widget_assert (xml,"radiobutton5");
354   dialog->radioButton[BUTTON_DOLLAR] =
355     get_widget_assert (xml,"radiobutton6");
356   dialog->radioButton[BUTTON_CUSTOM] =
357     get_widget_assert (xml,"radiobutton7");
358   dialog->radioButton[BUTTON_STRING] =
359     get_widget_assert (xml,"radiobutton8");
360
361
362   dialog->date_format_list = get_widget_assert (xml, "scrolledwindow4");
363   dialog->width_decimals = get_widget_assert (xml, "width_decimals");
364   dialog->label_decimals = get_widget_assert (xml, "decimals_label");
365   dialog->entry_decimals = get_widget_assert (xml, "decimals_entry");
366
367   dialog->label_psample = get_widget_assert (xml, "psample_label");
368   dialog->label_nsample = get_widget_assert (xml, "nsample_label");
369
370
371   dialog->entry_width = get_widget_assert (xml,"width_entry");
372
373   dialog->custom_currency_hbox = get_widget_assert (xml,
374                                                    "custom_currency_hbox");
375
376   dialog->dollar_window = get_widget_assert (xml, "dollar_window");
377   dialog->dollar_treeview =
378     GTK_TREE_VIEW (get_widget_assert (xml, "dollar_treeview"));
379
380   dialog->custom_treeview =
381     GTK_TREE_VIEW (get_widget_assert (xml, "custom_treeview"));
382
383
384   dialog->ok = get_widget_assert (xml,"var_type_ok");
385
386
387   {
388   GtkTreeIter iter;
389   GtkListStore *list_store ;
390
391   GtkTreeViewColumn *column;
392   GtkCellRenderer *renderer ;
393
394   static struct tgs tgs[num_BUTTONS];
395   /* The "middle_box" is a vbox with serveral children.
396      However only one child is ever shown at a time.
397      We need to make sure that they all have the same width, to avoid
398      upleasant resizing effects */
399   GtkSizeGroup *sizeGroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
400
401   gtk_container_foreach (GTK_CONTAINER (get_widget_assert (xml, "middle_box")),
402                         add_to_group, sizeGroup);
403
404
405   for (i = 0 ; i < num_BUTTONS; ++i )
406     {
407       tgs[i].dialog = dialog;
408       tgs[i].button = i;
409       g_signal_connect (dialog->radioButton[i], "toggled",
410                        G_CALLBACK (on_toggle_1), &tgs[i]);
411
412       g_signal_connect (dialog->radioButton[i], "toggled",
413                        G_CALLBACK (on_toggle_2), dialog);
414     }
415
416   /* Populate the date format tree view */
417   dialog->date_format_treeview = GTK_TREE_VIEW (get_widget_assert (xml,
418                                               "date_format_list_view"));
419
420   renderer = gtk_cell_renderer_text_new ();
421
422   column = gtk_tree_view_column_new_with_attributes ("Title",
423                                                      renderer,
424                                                      "text",
425                                                      0,
426                                                      NULL);
427
428   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->date_format_treeview),
429                                column);
430
431
432   list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
433
434   for ( i = 0 ; i < sizeof (format_option) / sizeof (format_option[0]) ; ++i )
435     {
436       gtk_list_store_append (list_store, &iter);
437       gtk_list_store_set (list_store, &iter,
438                           0, format_option[i].desc,
439                           1, &format_option[i].spec,
440                           -1);
441     }
442
443   gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->date_format_treeview),
444                           GTK_TREE_MODEL (list_store));
445
446   g_object_unref (list_store);
447
448   g_signal_connect (dialog->date_format_treeview, "cursor-changed",
449                    GTK_SIGNAL_FUNC (set_format_from_treeview), dialog);
450
451
452   /* populate the dollar treeview */
453
454   renderer = gtk_cell_renderer_text_new ();
455
456   column = gtk_tree_view_column_new_with_attributes ("Title",
457                                                      renderer,
458                                                      "text",
459                                                      0,
460                                                      NULL);
461
462   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->dollar_treeview),
463                                column);
464
465
466   list_store = gtk_list_store_new (2, G_TYPE_STRING,
467                                                  G_TYPE_POINTER);
468
469   for ( i = 0 ; i < sizeof (dollar_format)/sizeof (dollar_format[0]) ; ++i )
470     {
471       char *template = settings_dollar_template (&dollar_format[i]);
472       gtk_list_store_append (list_store, &iter);
473       gtk_list_store_set (list_store, &iter,
474                           0, template,
475                           1, &dollar_format[i],
476                           -1);
477       free (template);
478     }
479
480   gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->dollar_treeview),
481                           GTK_TREE_MODEL (list_store));
482
483   g_object_unref (list_store);
484
485   g_signal_connect (dialog->dollar_treeview,
486                    "cursor-changed",
487                    GTK_SIGNAL_FUNC (set_format_from_treeview), dialog);
488
489   g_signal_connect_swapped (dialog->dollar_treeview,
490                    "cursor-changed",
491                    GTK_SIGNAL_FUNC (update_width_decimals), dialog);
492
493
494   /* populate the custom treeview */
495
496   renderer = gtk_cell_renderer_text_new ();
497
498   column = gtk_tree_view_column_new_with_attributes ("Title",
499                                                      renderer,
500                                                      "text",
501                                                      0,
502                                                      NULL);
503
504   gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->custom_treeview),
505                                column);
506
507
508   list_store = gtk_list_store_new (2, G_TYPE_STRING,
509                                                  G_TYPE_POINTER);
510
511   for ( i = 0 ; i < 5 ; ++i )
512     {
513       enum fmt_type cc_fmts[5] = {FMT_CCA, FMT_CCB, FMT_CCC, FMT_CCD, FMT_CCE};
514       gchar text[4];
515       g_snprintf (text, 4, "%s", fmt_name (cc_fmts[i]));
516       gtk_list_store_append (list_store, &iter);
517       gtk_list_store_set (list_store, &iter,
518                           0, text,
519                           1, &cc_format[i],
520                           -1);
521     }
522
523   gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->custom_treeview),
524                           GTK_TREE_MODEL (list_store));
525
526   g_object_unref (list_store);
527
528
529   g_signal_connect (dialog->custom_treeview,
530                    "cursor-changed",
531                    GTK_SIGNAL_FUNC (set_format_type_from_treeview), dialog);
532
533
534   g_signal_connect (dialog->custom_treeview,
535                    "cursor-changed",
536                    GTK_SIGNAL_FUNC (preview_custom), dialog);
537
538
539   g_signal_connect (dialog->entry_width,
540                    "changed",
541                    GTK_SIGNAL_FUNC (preview_custom), dialog);
542
543
544   g_signal_connect (dialog->entry_decimals,
545                    "changed",
546                    GTK_SIGNAL_FUNC (preview_custom), dialog);
547
548
549   /* Connect to the OK button */
550   g_signal_connect (dialog->ok, "clicked", G_CALLBACK (on_var_type_ok_clicked),
551                    dialog);
552
553
554   /* And the cancel button */
555   g_signal_connect (get_widget_assert (xml, "var_type_cancel") , "clicked",
556                     G_CALLBACK (hide_dialog),
557                     dialog);
558
559
560   }
561
562   return dialog;
563 }
564
565
566 /* Set a particular button to be active */
567 void
568 var_type_dialog_set_active_button (struct var_type_dialog *dialog, gint b)
569 {
570   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radioButton[b]),
571                                TRUE);
572   dialog->active_button = b;
573 }
574
575
576
577 /* Set the TREEVIEW list cursor to the item described by FMT */
578 static void
579 select_treeview_from_format (GtkTreeView *treeview, const struct fmt_spec *fmt)
580 {
581   GtkTreePath *path ;
582
583   /*
584     We do this with a linear search through the model --- hardly
585     efficient, but the list is short ... */
586   GtkTreeIter iter;
587
588   GtkTreeModel * model  = gtk_tree_view_get_model (treeview);
589
590   gboolean success;
591   for (success = gtk_tree_model_get_iter_first (model, &iter);
592        success;
593        success = gtk_tree_model_iter_next (model, &iter))
594     {
595       const struct fmt_spec *spec;
596
597       GValue value = {0};
598
599       gtk_tree_model_get_value (model, &iter, 1, &value);
600
601       spec = g_value_get_pointer (&value);
602
603       if ( 0 == memcmp (spec, fmt, sizeof (struct fmt_spec)))
604         {
605           break;
606         }
607     }
608
609   path = gtk_tree_model_get_path (model, &iter);
610   if ( path )
611     {
612       gtk_tree_view_set_cursor (treeview, path, 0, 0);
613       gtk_tree_path_free (path);
614     }
615   else
616     {
617       char str[FMT_STRING_LEN_MAX + 1];
618       g_warning ("Unusual date format: %s\n", fmt_to_string (fmt, str));
619     }
620 }
621
622
623 /* Set the TREEVIEW list cursor to the item described by FMT_TYPE */
624 static void
625 select_treeview_from_format_type (GtkTreeView *treeview,
626                                  const int fmt_type)
627 {
628   GtkTreePath *path ;
629
630  /*
631     We do this with a linear search through the model --- hardly
632     efficient, but the list is short ... */
633   GtkTreeIter iter;
634
635   GtkTreeModel * model  = gtk_tree_view_get_model (treeview);
636
637   gboolean success;
638   for (success = gtk_tree_model_get_iter_first (model, &iter);
639        success;
640        success = gtk_tree_model_iter_next (model, &iter))
641     {
642       int spec ;
643
644       GValue value = {0};
645
646       gtk_tree_model_get_value (model, &iter, 1, &value);
647
648       spec = * ((int *) g_value_get_pointer (&value));
649
650       if ( spec == fmt_type)
651         break;
652     }
653
654   path = gtk_tree_model_get_path (model, &iter);
655   if ( path )
656     {
657       gtk_tree_view_set_cursor (treeview, path, 0, 0);
658       gtk_tree_path_free (path);
659     }
660   else
661     g_warning ("Unknown custom type  %d\n", fmt_type);
662
663 }
664
665 /* Set up the state of the dialog box to match the variable VAR */
666 static void
667 var_type_dialog_set_state (struct var_type_dialog *dialog)
668 {
669   const struct fmt_spec *write_spec ;
670   GString *str = g_string_new ("");
671
672   g_assert (dialog);
673   g_assert (dialog->pv);
674
675   /* Populate width and decimals */
676   write_spec = var_get_write_format (dialog->pv);
677
678   g_string_printf (str, "%d", write_spec->d);
679
680   gtk_entry_set_text (GTK_ENTRY (dialog->entry_decimals),
681                      str->str);
682
683   g_string_printf (str, "%d", write_spec->w);
684
685   gtk_entry_set_text (GTK_ENTRY (dialog->entry_width),
686                      str->str);
687
688   g_string_free (str, TRUE);
689
690   /* Populate the radio button states */
691   switch (write_spec->type)
692     {
693     case FMT_F:
694       var_type_dialog_set_active_button (dialog, BUTTON_NUMERIC);
695       gtk_widget_show_all (dialog->width_decimals);
696       break;
697     case FMT_A:
698       var_type_dialog_set_active_button (dialog, BUTTON_STRING);
699       gtk_widget_hide (dialog->label_decimals);
700       gtk_widget_hide (dialog->entry_decimals);
701       break;
702     case FMT_COMMA:
703       var_type_dialog_set_active_button (dialog, BUTTON_COMMA);
704       gtk_widget_show_all (dialog->width_decimals);
705       break;
706     case FMT_DOT:
707       var_type_dialog_set_active_button (dialog, BUTTON_DOT);
708       gtk_widget_show_all (dialog->width_decimals);
709       break;
710     case FMT_DOLLAR:
711       var_type_dialog_set_active_button (dialog, BUTTON_DOLLAR);
712       gtk_widget_show_all (dialog->width_decimals);
713
714       select_treeview_from_format (dialog->dollar_treeview, write_spec);
715       break;
716     case FMT_DATE:
717     case FMT_EDATE:
718     case FMT_SDATE:
719     case FMT_ADATE:
720     case FMT_JDATE:
721     case FMT_QYR:
722     case FMT_MOYR:
723     case FMT_WKYR:
724     case FMT_DATETIME:
725     case FMT_TIME:
726     case FMT_DTIME:
727     case FMT_WKDAY:
728     case FMT_MONTH:
729       var_type_dialog_set_active_button (dialog, BUTTON_DATE);
730       gtk_widget_hide (dialog->width_decimals);
731       gtk_widget_show (dialog->date_format_list);
732       select_treeview_from_format (dialog->date_format_treeview, write_spec);
733       break;
734     case FMT_CCA:
735     case FMT_CCB:
736     case FMT_CCC:
737     case FMT_CCD:
738     case FMT_CCE:
739       var_type_dialog_set_active_button (dialog, BUTTON_CUSTOM);
740       select_treeview_from_format_type (dialog->custom_treeview,
741                                        write_spec->type);
742       gtk_widget_show_all (dialog->width_decimals);
743       break;
744     default:
745       gtk_widget_show_all (dialog->width_decimals);
746       break;
747     }
748 }
749
750
751 /* Popup the dialog box */
752 void
753 var_type_dialog_show (struct var_type_dialog *dialog)
754 {
755   var_type_dialog_set_state (dialog);
756
757   gtk_widget_show (dialog->window);
758 }
759
760 /* Fills F with an output format specification with type TYPE, width
761    W, and D decimals. Iff it's a valid format, then return true.
762 */
763 static bool
764 make_output_format_try (struct fmt_spec *f, int type, int w, int d)
765 {
766   f->type = type;
767   f->w = w;
768   f->d = d;
769   return fmt_check_output (f);
770 }
771
772
773
774
775 /* Callbacks for the Variable Type Dialog Box */
776
777 /* Callback for when the var type dialog is closed using the OK button.
778    It sets the appropriate variable accordingly. */
779 static gint
780 on_var_type_ok_clicked (GtkWidget *w, gpointer data)
781 {
782   struct var_type_dialog *dialog = data;
783
784   g_assert (dialog);
785   g_assert (dialog->pv);
786
787   {
788     gint width = atoi (gtk_entry_get_text
789                       (GTK_ENTRY (dialog->entry_width)));
790
791     gint decimals = atoi (gtk_entry_get_text
792                          (GTK_ENTRY (dialog->entry_decimals)));
793
794     gint new_type = VAL_NUMERIC;
795     gint new_width = 0;
796     bool result = false;
797     struct fmt_spec spec;
798     switch (dialog->active_button)
799       {
800       case BUTTON_STRING:
801         new_type = VAL_STRING;
802         new_width = width;
803         result = make_output_format_try (&spec, FMT_A, width, 0);
804         break;
805       case BUTTON_NUMERIC:
806         result = make_output_format_try (&spec, FMT_F, width, decimals);
807         break;
808       case BUTTON_COMMA:
809         result = make_output_format_try (&spec, FMT_COMMA, width, decimals);
810         break;
811       case BUTTON_DOT:
812         result = make_output_format_try (&spec, FMT_DOT, width, decimals);
813         break;
814       case BUTTON_SCIENTIFIC:
815         result = make_output_format_try (&spec, FMT_E, width, decimals);
816         break;
817       case BUTTON_DATE:
818       case BUTTON_CUSTOM:
819         g_assert (fmt_check_output (&dialog->fmt_l));
820         result = memcpy (&spec, &dialog->fmt_l, sizeof (struct fmt_spec));
821         break;
822       case BUTTON_DOLLAR:
823         result = make_output_format_try (&spec, FMT_DOLLAR, width, decimals);
824         break;
825       default:
826         g_print ("Unknown variable type: %d\n", dialog->active_button) ;
827         result = false;
828         break;
829       }
830
831     if ( result == true )
832       {
833         var_set_width (dialog->pv, new_width);
834         var_set_both_formats (dialog->pv, &spec);
835       }
836
837   }
838   gtk_widget_hide (dialog->window);
839
840   return FALSE;
841 }
842
843
844
845 static gint
846 hide_dialog (GtkWidget *w,  gpointer data)
847 {
848   struct var_type_dialog *dialog = data;
849
850   gtk_widget_hide (dialog->window);
851
852   return FALSE;
853 }
854