X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fvar-type-dialog.c;h=a2792ef08993b5ea7d55830f85b899035b079957;hb=fb224459eed00514cbc36ecbc311c644f8b22def;hp=0d58026df083b139b56dd4979d4a5b6588cdb9b3;hpb=72147c12357446b304264b6944b8a1d92c45f53c;p=pspp diff --git a/src/ui/gui/var-type-dialog.c b/src/ui/gui/var-type-dialog.c index 0d58026df0..a2792ef089 100644 --- a/src/ui/gui/var-type-dialog.c +++ b/src/ui/gui/var-type-dialog.c @@ -1,22 +1,18 @@ -/* - PSPPIRE --- A Graphical User Interface for PSPP - Copyright (C) 2005, 2006 Free Software Foundation - Written by John Darrington +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2005, 2006, 2010, 2011, 2012, 2015 Free Software Foundation - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ /* This module describes the behaviour of the Variable Type dialog box used @@ -25,56 +21,41 @@ #include #include -#include - #include #include -#include "var-type-dialog.h" - -#include "helper.h" - -#include -#include -#include - - -struct tgs -{ - struct var_type_dialog *dialog; - gint button; -}; - +#include "data/data-out.h" +#include "data/settings.h" +#include "data/variable.h" +#include "libpspp/message.h" +#include "ui/gui/builder-wrapper.h" +#include "ui/gui/psppire-format.h" +#include "ui/gui/var-type-dialog.h" -struct format_opt { - gchar desc[18]; - struct fmt_spec spec; -}; - - -static const struct format_opt format_option[] = +static const struct fmt_spec date_format[] = { - { "dd-mmm-yyyy", {FMT_DATE, 11, 0} }, - { "dd-mmm-yy", {FMT_DATE, 9, 0} }, - { "mm/dd/yyyy", {FMT_ADATE, 10, 0} }, - { "mm/dd/yy", {FMT_ADATE, 8, 0} }, - { "dd.mm.yyyy", {FMT_EDATE, 10, 0} }, - { "dd.mm.yy", {FMT_EDATE, 8, 0} }, - { "yyyy/mm/dd", {FMT_SDATE, 10, 0} }, - { "yy/mm/dd", {FMT_SDATE, 8, 0} }, - { "yyddd", {FMT_JDATE, 5, 0} }, - { "yyyyddd", {FMT_JDATE, 7, 0} }, - { "q Q yyyy", {FMT_QYR, 8, 0} }, - { "q Q yy", {FMT_QYR, 6, 0} }, - { "mmm yyyy", {FMT_MOYR, 8, 0} }, - { "mmm yy", {FMT_MOYR, 6, 0} }, - { "dd WK yyyy", {FMT_WKYR, 10, 0} }, - { "dd WK yy", {FMT_WKYR, 8, 0} }, - { "dd-mmm-yyyy HH:MM", {FMT_DATETIME, 17, 0}} + {FMT_DATE, 11, 0}, + {FMT_DATE, 9, 0}, + {FMT_ADATE, 10, 0}, + {FMT_ADATE, 8, 0}, + {FMT_EDATE, 10, 0}, + {FMT_EDATE, 8, 0}, + {FMT_SDATE, 10, 0}, + {FMT_SDATE, 8, 0}, + {FMT_JDATE, 5, 0}, + {FMT_JDATE, 7, 0}, + {FMT_QYR, 8, 0}, + {FMT_QYR, 6, 0}, + {FMT_MOYR, 8, 0}, + {FMT_MOYR, 6, 0}, + {FMT_WKYR, 10, 0}, + {FMT_WKYR, 8, 0}, + {FMT_DATETIME, 17, 0}, + {FMT_DATETIME, 20, 0} }; -static const struct fmt_spec dollar_format[] = +static const struct fmt_spec dollar_format[] = { {FMT_DOLLAR, 2, 0}, {FMT_DOLLAR, 3, 0}, @@ -90,174 +71,366 @@ static const struct fmt_spec dollar_format[] = {FMT_DOLLAR, 19, 2} }; -static const int cc_format[] = +static const int cc_format[] = { - FMT_CCA, - FMT_CCB, - FMT_CCC, - FMT_CCD, - FMT_CCE, + FMT_CCA, + FMT_CCB, + FMT_CCC, + FMT_CCD, + FMT_CCE, }; +static GObject *psppire_var_type_dialog_constructor (GType type, guint, + GObjectConstructParam *); +static void psppire_var_type_dialog_set_state (PsppireVarTypeDialog *); -static void select_treeview_from_format - (GtkTreeView *treeview, const struct fmt_spec *fmt); +static void psppire_var_type_dialog_set_format (PsppireVarTypeDialog *dialog, + const struct fmt_spec *format); -static void select_treeview_from_format_type(GtkTreeView *treeview, - const int fmt_type); +static int find_format (const struct fmt_spec *target, + const struct fmt_spec formats[], int n_formats); +static int find_format_type (int target, const int types[], int n_types); +static void select_treeview_at_index (GtkTreeView *, int index); -/* callback for when any of the radio buttons are toggled */ -static void -on_toggle_1(GtkToggleButton *togglebutton, gpointer user_data) -{ - struct tgs *tgs = user_data; +static void update_width_decimals (const PsppireVarTypeDialog *); +static void refresh_active_button (PsppireVarTypeDialog *); +static void on_active_button_change (GtkToggleButton *, + PsppireVarTypeDialog *); +static void on_width_changed (GtkEntry *, PsppireVarTypeDialog *); +static void on_decimals_changed (GtkEntry *, PsppireVarTypeDialog *); - if ( gtk_toggle_button_get_active(togglebutton) == FALSE) - return ; +G_DEFINE_TYPE (PsppireVarTypeDialog, + psppire_var_type_dialog, + PSPPIRE_TYPE_DIALOG); - tgs->dialog->active_button = tgs->button; -} +enum + { + PROP_0, + PROP_FORMAT + }; -static void update_width_decimals(const struct var_type_dialog *dialog); +static void +psppire_var_type_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PsppireVarTypeDialog *obj = PSPPIRE_VAR_TYPE_DIALOG (object); -#define force_max(x, val) if (x > val) x = val + switch (prop_id) + { + case PROP_FORMAT: + psppire_var_type_dialog_set_format (obj, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} -/* - Set the local format from the variable - and force them to have sensible values */ static void -set_local_width_decimals(struct var_type_dialog *dialog) +psppire_var_type_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - dialog->fmt_l = * var_get_write_format (dialog->pv); + PsppireVarTypeDialog *obj = PSPPIRE_VAR_TYPE_DIALOG (object); - switch (dialog->active_button) + switch (prop_id) { - case BUTTON_STRING: - force_max( dialog->fmt_l.w, 255); + case PROP_FORMAT: + g_value_set_boxed (value, &obj->fmt_l); break; default: - force_max( dialog->fmt_l.w, 40); - force_max( dialog->fmt_l.d, 16); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +psppire_var_type_dialog_set_format (PsppireVarTypeDialog *dialog, + const struct fmt_spec *format) +{ + dialog->base_format = *format; + psppire_var_type_dialog_set_state (dialog); +} + +static const struct fmt_spec * +psppire_var_type_dialog_get_format (const PsppireVarTypeDialog *dialog) +{ + return &dialog->fmt_l; +} + +static void +psppire_var_type_dialog_init (PsppireVarTypeDialog *obj) +{ + /* We do all of our work on widgets in the constructor function, because that + runs after the construction properties have been set. Otherwise + PsppireDialog's "orientation" property hasn't been set and therefore we + have no box to populate. */ + obj->base_format = F_8_0; + obj->fmt_l = F_8_0; +} + +static void +psppire_var_type_dialog_class_init (PsppireVarTypeDialogClass *class) +{ + GObjectClass *gobject_class; + gobject_class = G_OBJECT_CLASS (class); + + gobject_class->constructor = psppire_var_type_dialog_constructor; + gobject_class->set_property = psppire_var_type_dialog_set_property; + gobject_class->get_property = psppire_var_type_dialog_get_property; + + g_object_class_install_property ( + gobject_class, PROP_FORMAT, + g_param_spec_boxed ("format", + "Format", + "The format being edited.", + PSPPIRE_TYPE_FORMAT, + G_PARAM_READABLE | G_PARAM_WRITABLE)); +} + +PsppireVarTypeDialog * +psppire_var_type_dialog_new (const struct fmt_spec *format) +{ + return PSPPIRE_VAR_TYPE_DIALOG ( + g_object_new (PSPPIRE_TYPE_VAR_TYPE_DIALOG, + "format", format, + NULL)); +} + +gint +psppire_var_type_dialog_run (GtkWindow *parent_window, + struct fmt_spec *format) +{ + PsppireVarTypeDialog *dialog; + + dialog = psppire_var_type_dialog_new (format); + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + gtk_widget_show (GTK_WIDGET (dialog)); + + gint result = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); + if (result == GTK_RESPONSE_OK) + *format = *psppire_var_type_dialog_get_format (dialog); + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return result; +} + /* callback for when any of the radio buttons are toggled */ -static void -on_toggle_2(GtkToggleButton *togglebutton, gpointer user_data) +static void +on_toggle (GtkToggleButton *togglebutton, gpointer dialog_) +{ + PsppireVarTypeDialog *dialog = dialog_; + + if ( gtk_toggle_button_get_active (togglebutton) == TRUE) + refresh_active_button (dialog); +} + +static void +refresh_active_button (PsppireVarTypeDialog *dialog) { - struct var_type_dialog *dialog = user_data; - if ( gtk_toggle_button_get_active(togglebutton) == FALSE) + int i; + + for (i = 0; i < num_BUTTONS; i++) { - switch (dialog->active_button) - { - case BUTTON_DATE: - gtk_widget_hide(dialog->date_format_list); - break; - case BUTTON_CUSTOM: - gtk_widget_hide(dialog->custom_currency_hbox); - break; - case BUTTON_DOLLAR: - gtk_widget_hide(dialog->dollar_window); - break; - case BUTTON_STRING: - gtk_widget_show(dialog->label_decimals); - gtk_widget_show(dialog->entry_decimals); - break; - } - return ; + GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (dialog->radioButton[i]); + + if (gtk_toggle_button_get_active (toggle)) + { + if (dialog->active_button != i) + { + dialog->active_button = i; + on_active_button_change (toggle, dialog); + } + return; + } } - set_local_width_decimals(dialog); - update_width_decimals(dialog); + g_return_if_reached (); +} + +static void +update_adj_ranges (PsppireVarTypeDialog *dialog) +{ + enum fmt_type type = dialog->fmt_l.type; + const enum fmt_use use = FMT_FOR_OUTPUT; + int min_w = fmt_min_width (type, use); + int max_w = fmt_max_width (type, use); + int max_d = fmt_max_decimals (type, max_w, use); + + g_object_set (dialog->adj_width, + "lower", (double) min_w, + "upper", (double) max_w, + NULL); + + g_object_set (dialog->adj_decimals, + "lower", 0.0, + "upper", (double) max_d, + NULL); +} + +/* callback for when any of the radio buttons are toggled */ +static void +on_active_button_change (GtkToggleButton *togglebutton, + PsppireVarTypeDialog *dialog) +{ + enum widgets { + W_WIDTH = 1 << 0, + W_DECIMALS = 1 << 1, + W_DATE_FORMATS = 1 << 2, + W_DOLLAR_FORMATS = 1 << 3, + W_CC_FORMATS = 1 << 4, + }; + + enum widgets widgets; + int indx; - switch (dialog->active_button) + switch (dialog->active_button) { + case BUTTON_NUMERIC: + case BUTTON_COMMA: + case BUTTON_DOT: + case BUTTON_SCIENTIFIC: + widgets = W_WIDTH | W_DECIMALS; + break; + case BUTTON_STRING: - gtk_widget_show(dialog->width_decimals); - gtk_widget_hide(dialog->label_decimals); - gtk_widget_hide(dialog->entry_decimals); + widgets = W_WIDTH; break; + case BUTTON_DATE: - select_treeview_from_format(dialog->date_format_treeview, - &format_option[0].spec); - gtk_widget_hide(dialog->width_decimals); - gtk_widget_show(dialog->date_format_list); + widgets = W_DATE_FORMATS; break; + case BUTTON_DOLLAR: - select_treeview_from_format(dialog->dollar_treeview, - &dollar_format[0]); - gtk_widget_show(dialog->dollar_window); - gtk_widget_show_all(dialog->width_decimals); + widgets = W_DOLLAR_FORMATS; break; - case BUTTON_CUSTOM: - select_treeview_from_format_type(dialog->custom_treeview, - cc_format[0]); - gtk_widget_show(dialog->width_decimals); - gtk_widget_show(dialog->custom_currency_hbox); + case BUTTON_CUSTOM: + widgets = W_CC_FORMATS | W_WIDTH | W_DECIMALS; break; + default: - gtk_widget_show_all(dialog->width_decimals); - break; + /* No button active */ + return; } -} + gtk_widget_set_visible (dialog->width_decimals, (widgets & W_WIDTH) != 0); + gtk_widget_set_visible (dialog->entry_width, (widgets & W_WIDTH) != 0); + gtk_widget_set_visible (dialog->entry_decimals, (widgets & W_DECIMALS) != 0); + gtk_widget_set_visible (dialog->label_decimals, (widgets & W_DECIMALS) != 0); + gtk_widget_set_visible (dialog->date_format_list, + (widgets & W_DATE_FORMATS) != 0); + gtk_widget_set_visible (dialog->custom_currency_hbox, + (widgets & W_CC_FORMATS) != 0); + gtk_widget_set_visible (dialog->dollar_window, + (widgets & W_DOLLAR_FORMATS) != 0); + dialog->fmt_l = dialog->base_format; -static gint on_var_type_ok_clicked(GtkWidget *w, gpointer data); + switch (dialog->active_button) + { + case BUTTON_NUMERIC: + dialog->fmt_l.type = FMT_F; + break; + case BUTTON_COMMA: + dialog->fmt_l.type = FMT_COMMA; + break; + case BUTTON_DOT: + dialog->fmt_l.type = FMT_DOT; + break; + case BUTTON_SCIENTIFIC: + dialog->fmt_l.type = FMT_E; + break; + case BUTTON_STRING: + dialog->fmt_l.type = FMT_A; + break; + case BUTTON_DATE: + indx = find_format (&dialog->fmt_l, date_format, + sizeof date_format / sizeof *date_format); + select_treeview_at_index (dialog->date_format_treeview, indx); + dialog->fmt_l = date_format[indx]; + break; + case BUTTON_DOLLAR: + indx = find_format (&dialog->fmt_l, dollar_format, + sizeof dollar_format / sizeof *dollar_format); + select_treeview_at_index (dialog->dollar_treeview, indx); + dialog->fmt_l = dollar_format[indx]; + break; + case BUTTON_CUSTOM: + indx = find_format_type (dialog->fmt_l.type, cc_format, + sizeof cc_format / sizeof *cc_format); + select_treeview_at_index (dialog->custom_treeview, indx); + dialog->fmt_l.type = cc_format[indx]; + break; + } -#define LEN 20 + fmt_fix_output (&dialog->fmt_l); + update_adj_ranges (dialog); + update_width_decimals (dialog); +} static void -add_to_group(GtkWidget *w, gpointer data) +add_to_group (GtkWidget *w, gpointer data) { GtkSizeGroup *sg = data; - - gtk_size_group_add_widget(sg, w); + + gtk_size_group_add_widget (sg, w); } /* Set the local width and decimals entry boxes to reflec the local format */ static void -update_width_decimals(const struct var_type_dialog *dialog) +update_width_decimals (const PsppireVarTypeDialog *dialog) { - gchar *text; - g_assert(dialog); + gtk_adjustment_set_value (dialog->adj_width, dialog->fmt_l.w); + gtk_adjustment_set_value (dialog->adj_decimals, dialog->fmt_l.d); +} - text = g_strdup_printf("%d", dialog->fmt_l.w); - gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), text); - g_free(text); +static void +on_width_changed (GtkEntry *entry, PsppireVarTypeDialog *dialog) +{ + int w = atoi (gtk_entry_get_text (GTK_ENTRY (dialog->entry_width))); + fmt_change_width (&dialog->fmt_l, w, FMT_FOR_OUTPUT); + update_width_decimals (dialog); +} - text = g_strdup_printf("%d", dialog->fmt_l.d); - gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), text); - g_free(text); +static void +on_decimals_changed (GtkEntry *entry, PsppireVarTypeDialog *dialog) +{ + int d = atoi (gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals))); + fmt_change_decimals (&dialog->fmt_l, d, FMT_FOR_OUTPUT); + update_width_decimals (dialog); } /* Callback for when the custom treeview row is changed. It sets dialog box to reflect the selected format */ static void -preview_custom(GtkWidget *w, gpointer data) +preview_custom (GtkWidget *w, gpointer data) { const gchar *text ; - struct var_type_dialog *dialog = data; + PsppireVarTypeDialog *dialog = data; - if ( dialog->active_button != BUTTON_CUSTOM ) + if ( dialog->active_button != BUTTON_CUSTOM ) return; - text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_decimals)); - dialog->fmt_l.d = atoi(text); + text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_decimals)); + dialog->fmt_l.d = atoi (text); - text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_width)); - dialog->fmt_l.w = atoi(text); + text = gtk_entry_get_text (GTK_ENTRY (dialog->entry_width)); + dialog->fmt_l.w = atoi (text); msg_disable (); - if ( ! fmt_check_output(&dialog->fmt_l)) + if ( ! fmt_check_output (&dialog->fmt_l)) { - gtk_label_set_text(GTK_LABEL(dialog->label_psample), "---"); - gtk_label_set_text(GTK_LABEL(dialog->label_nsample), "---"); + gtk_label_set_text (GTK_LABEL (dialog->label_psample), "---"); + gtk_label_set_text (GTK_LABEL (dialog->label_nsample), "---"); } else { @@ -265,120 +438,152 @@ preview_custom(GtkWidget *w, gpointer data) union value v; v.f = 1234.56; - sample_text = value_to_text(v, dialog->fmt_l); - gtk_label_set_text(GTK_LABEL(dialog->label_psample), sample_text); - g_free(sample_text); + sample_text = g_strchug (data_out (&v, NULL, &dialog->fmt_l)); + gtk_label_set_text (GTK_LABEL (dialog->label_psample), sample_text); + g_free (sample_text); v.f = -v.f; - sample_text = value_to_text(v, dialog->fmt_l); - gtk_label_set_text(GTK_LABEL(dialog->label_nsample), sample_text); - g_free(sample_text); + sample_text = g_strchug (data_out (&v, NULL, &dialog->fmt_l)); + gtk_label_set_text (GTK_LABEL (dialog->label_nsample), sample_text); + g_free (sample_text); } msg_enable (); } -/* Callback for when a treeview row is changed. - It sets the fmt_l_spec to reflect the selected format */ -static void -set_format_from_treeview(GtkTreeView *treeview, gpointer data) +static gint +get_index_from_treeview (GtkTreeView *treeview) { - struct var_type_dialog *dialog = data; - GtkTreeIter iter ; - GValue the_value = {0}; + GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview); + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gint index; - GtkTreeSelection* sel = gtk_tree_view_get_selection(treeview); + if (selection == NULL) + return -1; - GtkTreeModel * model = gtk_tree_view_get_model(treeview); + gtk_tree_selection_get_selected (selection, &model, &iter); + path = gtk_tree_model_get_path (model, &iter); + if (!path || gtk_tree_path_get_depth (path) < 1) + index = 0; + else + index = gtk_tree_path_get_indices (path)[0]; + gtk_tree_path_free (path); - gtk_tree_selection_get_selected (sel, &model, &iter); + return index; +} - gtk_tree_model_get_value(model, &iter, 1, &the_value); +/* Callback for when a date treeview row is changed. + It sets the fmt_l_spec to reflect the selected format */ +static void +set_date_format_from_treeview (GtkTreeView *treeview, + PsppireVarTypeDialog *dialog) +{ + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; - dialog->fmt_l = *(struct fmt_spec *) g_value_get_pointer(&the_value); + dialog->fmt_l = date_format[idx]; } +/* Callback for when a dollar treeview row is changed. + It sets the fmt_l_spec to reflect the selected format */ +static void +set_dollar_format_from_treeview (GtkTreeView *treeview, + PsppireVarTypeDialog *dialog) +{ + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; + + dialog->fmt_l = dollar_format[idx]; +} /* Callback for when a treeview row is changed. It sets the type of the fmt_l to reflect the selected type */ static void -set_format_type_from_treeview(GtkTreeView *treeview, gpointer data) +set_custom_format_from_treeview (GtkTreeView *treeview, + PsppireVarTypeDialog *dialog) { - static struct fmt_spec custom_format = {0,0,0}; - struct var_type_dialog *dialog = data; - GtkTreeIter iter ; - GValue the_value = {0}; - - GtkTreeSelection* sel = gtk_tree_view_get_selection(treeview); - - GtkTreeModel * model = gtk_tree_view_get_model(treeview); - - gtk_tree_selection_get_selected (sel, &model, &iter); - - gtk_tree_model_get_value(model, &iter, 1, &the_value); - - dialog->fmt_l = custom_format; - dialog->fmt_l.type = *(int*) g_value_get_pointer(&the_value); + gint idx = get_index_from_treeview (treeview); + if (idx < 0) + return; + dialog->fmt_l.type = cc_format[idx]; + update_adj_ranges (dialog); + fmt_fix_output (&dialog->fmt_l); + update_width_decimals (dialog); } - - - -/* Create the structure from the XML definitions */ -struct var_type_dialog * -var_type_dialog_create(GladeXML *xml) +/* Create the structure */ +static GObject * +psppire_var_type_dialog_constructor (GType type, + guint n_properties, + GObjectConstructParam *properties) { + PsppireVarTypeDialog *dialog; + GtkContainer *content_area; + GtkBuilder *xml; + GObject *obj; gint i; - struct var_type_dialog *dialog = g_malloc(sizeof(struct var_type_dialog)); - - g_assert(xml); - - dialog->window = get_widget_assert(xml,"var_type_dialog"); - - gtk_window_set_transient_for(GTK_WINDOW(dialog->window), - GTK_WINDOW(get_widget_assert(xml, "data_editor"))); - - dialog->radioButton[BUTTON_NUMERIC] = - get_widget_assert(xml,"radiobutton1"); - dialog->radioButton[BUTTON_COMMA] = - get_widget_assert(xml,"radiobutton2"); - dialog->radioButton[BUTTON_DOT] = - get_widget_assert(xml,"radiobutton3"); - dialog->radioButton[BUTTON_SCIENTIFIC] = - get_widget_assert(xml,"radiobutton4"); - dialog->radioButton[BUTTON_DATE] = - get_widget_assert(xml,"radiobutton5"); - dialog->radioButton[BUTTON_DOLLAR] = - get_widget_assert(xml,"radiobutton6"); - dialog->radioButton[BUTTON_CUSTOM] = - get_widget_assert(xml,"radiobutton7"); - dialog->radioButton[BUTTON_STRING] = - get_widget_assert(xml,"radiobutton8"); - - dialog->date_format_list = get_widget_assert(xml, "scrolledwindow4"); - dialog->width_decimals = get_widget_assert(xml, "width_decimals"); - dialog->label_decimals = get_widget_assert(xml, "decimals_label"); - dialog->entry_decimals = get_widget_assert(xml, "decimals_entry"); - - dialog->label_psample = get_widget_assert(xml, "psample_label"); - dialog->label_nsample = get_widget_assert(xml, "nsample_label"); - - - dialog->entry_width = get_widget_assert(xml,"width_entry"); - - dialog->custom_currency_hbox = get_widget_assert(xml, + obj = G_OBJECT_CLASS (psppire_var_type_dialog_parent_class)->constructor ( + type, n_properties, properties); + dialog = PSPPIRE_VAR_TYPE_DIALOG (obj); + + xml = builder_new ("var-type-dialog.ui"); + + content_area = GTK_CONTAINER (PSPPIRE_DIALOG (dialog)); + gtk_container_add (GTK_CONTAINER (content_area), + get_widget_assert (xml, "var-type-dialog")); + + dialog->active_button = -1; + + g_signal_connect (dialog, "delete-event", + G_CALLBACK (gtk_widget_hide_on_delete), NULL); + + dialog->radioButton[BUTTON_NUMERIC] = + get_widget_assert (xml,"radiobutton1"); + dialog->radioButton[BUTTON_COMMA] = + get_widget_assert (xml,"radiobutton2"); + dialog->radioButton[BUTTON_DOT] = + get_widget_assert (xml,"radiobutton3"); + dialog->radioButton[BUTTON_SCIENTIFIC] = + get_widget_assert (xml,"radiobutton4"); + dialog->radioButton[BUTTON_DATE] = + get_widget_assert (xml,"radiobutton5"); + dialog->radioButton[BUTTON_DOLLAR] = + get_widget_assert (xml,"radiobutton6"); + dialog->radioButton[BUTTON_CUSTOM] = + get_widget_assert (xml,"radiobutton7"); + dialog->radioButton[BUTTON_STRING] = + get_widget_assert (xml,"radiobutton8"); + + + dialog->date_format_list = get_widget_assert (xml, "scrolledwindow4"); + dialog->width_decimals = get_widget_assert (xml, "width_decimals"); + dialog->label_decimals = get_widget_assert (xml, "decimals_label"); + dialog->entry_decimals = get_widget_assert (xml, "decimals_entry"); + dialog->adj_decimals = gtk_spin_button_get_adjustment ( + GTK_SPIN_BUTTON (dialog->entry_decimals)); + + dialog->label_psample = get_widget_assert (xml, "psample_label"); + dialog->label_nsample = get_widget_assert (xml, "nsample_label"); + + + dialog->entry_width = get_widget_assert (xml,"width_entry"); + dialog->adj_width = gtk_spin_button_get_adjustment ( + GTK_SPIN_BUTTON (dialog->entry_width)); + dialog->custom_currency_hbox = get_widget_assert (xml, "custom_currency_hbox"); - dialog->dollar_window = get_widget_assert(xml, "dollar_window"); - dialog->dollar_treeview = - GTK_TREE_VIEW(get_widget_assert(xml, "dollar_treeview")); - - dialog->custom_treeview = - GTK_TREE_VIEW(get_widget_assert(xml, "custom_treeview")); + dialog->dollar_window = get_widget_assert (xml, "dollar_window"); + dialog->dollar_treeview = + GTK_TREE_VIEW (get_widget_assert (xml, "dollar_treeview")); + dialog->custom_treeview = + GTK_TREE_VIEW (get_widget_assert (xml, "custom_treeview")); - dialog->ok = get_widget_assert(xml,"var_type_ok"); { @@ -388,456 +593,259 @@ var_type_dialog_create(GladeXML *xml) GtkTreeViewColumn *column; GtkCellRenderer *renderer ; - static struct tgs tgs[num_BUTTONS]; /* The "middle_box" is a vbox with serveral children. However only one child is ever shown at a time. We need to make sure that they all have the same width, to avoid upleasant resizing effects */ - GtkSizeGroup *sizeGroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + GtkSizeGroup *sizeGroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - gtk_container_foreach(GTK_CONTAINER(get_widget_assert(xml, "middle_box")), + gtk_container_foreach (GTK_CONTAINER (get_widget_assert (xml, "middle_box")), add_to_group, sizeGroup); - for (i = 0 ; i < num_BUTTONS; ++i ) - { - tgs[i].dialog = dialog; - tgs[i].button = i; - g_signal_connect(dialog->radioButton[i], "toggled", - G_CALLBACK(on_toggle_1), &tgs[i]); - - g_signal_connect(dialog->radioButton[i], "toggled", - G_CALLBACK(on_toggle_2), dialog); - } + for (i = 0 ; i < num_BUTTONS; ++i ) + g_signal_connect (dialog->radioButton[i], "toggled", + G_CALLBACK (on_toggle), dialog); /* Populate the date format tree view */ - dialog->date_format_treeview = GTK_TREE_VIEW(get_widget_assert(xml, + dialog->date_format_treeview = GTK_TREE_VIEW (get_widget_assert (xml, "date_format_list_view")); - renderer = gtk_cell_renderer_text_new(); - + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Title", renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->date_format_treeview), + gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->date_format_treeview), column); - list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); + list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < sizeof(format_option) / sizeof(format_option[0]) ; ++i ) + for ( i = 0 ; i < sizeof (date_format) / sizeof (date_format[0]) ; ++i ) { + const struct fmt_spec *f = &date_format[i]; gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, - 0, format_option[i].desc, - 1, &format_option[i].spec, + 0, fmt_date_template (f->type, f->w), -1); } - gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->date_format_treeview), - GTK_TREE_MODEL(list_store)); + gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->date_format_treeview), + GTK_TREE_MODEL (list_store)); - g_object_unref(list_store); + g_object_unref (list_store); - g_signal_connect(GTK_OBJECT(dialog->date_format_treeview), "cursor-changed", - GTK_SIGNAL_FUNC(set_format_from_treeview), dialog); + g_signal_connect (dialog->date_format_treeview, "cursor-changed", + G_CALLBACK (set_date_format_from_treeview), dialog); /* populate the dollar treeview */ - renderer = gtk_cell_renderer_text_new(); - + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Title", renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->dollar_treeview), + gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->dollar_treeview), column); - list_store = gtk_list_store_new (2, G_TYPE_STRING, - G_TYPE_POINTER); + list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < sizeof(dollar_format)/sizeof(dollar_format[0]) ; ++i ) + for ( i = 0 ; i < sizeof (dollar_format)/sizeof (dollar_format[0]) ; ++i ) { - char *template = fmt_dollar_template (&dollar_format[i]); + char *template = settings_dollar_template (&dollar_format[i]); gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, 0, template, - 1, &dollar_format[i], -1); free (template); } - gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->dollar_treeview), - GTK_TREE_MODEL(list_store)); + gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->dollar_treeview), + GTK_TREE_MODEL (list_store)); - g_object_unref(list_store); + g_object_unref (list_store); - g_signal_connect(GTK_OBJECT(dialog->dollar_treeview), + g_signal_connect (dialog->dollar_treeview, "cursor-changed", - GTK_SIGNAL_FUNC(set_format_from_treeview), dialog); + G_CALLBACK (set_dollar_format_from_treeview), dialog); - g_signal_connect_swapped(GTK_OBJECT(dialog->dollar_treeview), + g_signal_connect_swapped (dialog->dollar_treeview, "cursor-changed", - GTK_SIGNAL_FUNC(update_width_decimals), dialog); + G_CALLBACK (update_width_decimals), dialog); /* populate the custom treeview */ - renderer = gtk_cell_renderer_text_new(); - + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Title", renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->custom_treeview), + gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->custom_treeview), column); - list_store = gtk_list_store_new (2, G_TYPE_STRING, - G_TYPE_POINTER); + list_store = gtk_list_store_new (1, G_TYPE_STRING); - for ( i = 0 ; i < 5 ; ++i ) + for ( i = 0 ; i < 5 ; ++i ) { enum fmt_type cc_fmts[5] = {FMT_CCA, FMT_CCB, FMT_CCC, FMT_CCD, FMT_CCE}; - gchar text[4]; - g_snprintf(text, 4, "%s", fmt_name (cc_fmts[i])); gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, - 0, text, - 1, &cc_format[i], + 0, fmt_name (cc_fmts[i]), -1); } - gtk_tree_view_set_model(GTK_TREE_VIEW(dialog->custom_treeview), - GTK_TREE_MODEL(list_store)); + gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->custom_treeview), + GTK_TREE_MODEL (list_store)); - g_object_unref(list_store); + g_object_unref (list_store); - g_signal_connect(GTK_OBJECT(dialog->custom_treeview), + g_signal_connect (dialog->custom_treeview, "cursor-changed", - GTK_SIGNAL_FUNC(set_format_type_from_treeview), dialog); + G_CALLBACK (set_custom_format_from_treeview), dialog); - g_signal_connect(GTK_OBJECT(dialog->custom_treeview), + g_signal_connect (dialog->custom_treeview, "cursor-changed", - GTK_SIGNAL_FUNC(preview_custom), dialog); + G_CALLBACK (preview_custom), dialog); + + g_signal_connect (dialog->entry_width, "changed", + G_CALLBACK (on_width_changed), dialog); + g_signal_connect (dialog->entry_decimals, "changed", + G_CALLBACK (on_decimals_changed), dialog); - g_signal_connect(GTK_OBJECT(dialog->entry_width), + g_signal_connect (dialog->entry_width, "changed", - GTK_SIGNAL_FUNC(preview_custom), dialog); + G_CALLBACK (preview_custom), dialog); - g_signal_connect(GTK_OBJECT(dialog->entry_decimals), + g_signal_connect (dialog->entry_decimals, "changed", - GTK_SIGNAL_FUNC(preview_custom), dialog); + G_CALLBACK (preview_custom), dialog); + } - /* Connect the OK button */ - g_signal_connect(dialog->ok, "clicked", G_CALLBACK(on_var_type_ok_clicked), - dialog); - + g_object_unref (xml); - } + psppire_var_type_dialog_set_state (dialog); - return dialog; + return obj; } /* Set a particular button to be active */ void -var_type_dialog_set_active_button(struct var_type_dialog *dialog, gint b) +var_type_dialog_set_active_button (PsppireVarTypeDialog *dialog, gint b) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->radioButton[b]), + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radioButton[b]), TRUE); - dialog->active_button = b; } -/* Set the TREEVIEW list cursor to the item described by FMT */ static void -select_treeview_from_format(GtkTreeView *treeview, const struct fmt_spec *fmt) +select_treeview_at_index (GtkTreeView *treeview, int index) { - GtkTreePath *path ; - - /* - We do this with a linear search through the model --- hardly - efficient, but the list is short ... */ - GtkTreeIter iter; - - GtkTreeModel * model = gtk_tree_view_get_model(treeview); + GtkTreePath *path; - gboolean success; - for (success = gtk_tree_model_get_iter_first(model, &iter); - success; - success = gtk_tree_model_iter_next(model, &iter)) - { - const struct fmt_spec *spec; - - GValue value = {0}; - - gtk_tree_model_get_value(model, &iter, 1, &value); - - spec = g_value_get_pointer(&value); - - if ( 0 == memcmp(spec, fmt, sizeof (struct fmt_spec))) - { - break; - } - } - - path = gtk_tree_model_get_path(model, &iter); - if ( path ) - { - gtk_tree_view_set_cursor(treeview, path, 0, 0); - gtk_tree_path_free(path); - } - else - { - char str[FMT_STRING_LEN_MAX + 1]; - g_warning("Unusual date format: %s\n", fmt_to_string(fmt, str)); - } + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_view_set_cursor (treeview, path, 0, 0); + gtk_tree_path_free (path); } - -/* Set the TREEVIEW list cursor to the item described by FMT_TYPE */ -static void -select_treeview_from_format_type(GtkTreeView *treeview, - const int fmt_type) +static int +find_format (const struct fmt_spec *target, + const struct fmt_spec formats[], int n_formats) { - GtkTreePath *path ; - - /* - We do this with a linear search through the model --- hardly - efficient, but the list is short ... */ - GtkTreeIter iter; + int i; - GtkTreeModel * model = gtk_tree_view_get_model(treeview); + for (i = 0; i < n_formats; i++) + if (fmt_equal (target, &formats[i])) + return i; - gboolean success; - for (success = gtk_tree_model_get_iter_first(model, &iter); - success; - success = gtk_tree_model_iter_next(model, &iter)) - { - int spec ; - - GValue value = {0}; + return 0; +} - gtk_tree_model_get_value(model, &iter, 1, &value); - - spec = * ((int *) g_value_get_pointer(&value)); +static int +find_format_type (int target, const int types[], int n_types) +{ + int i; - if ( spec == fmt_type) - break; - } - - path = gtk_tree_model_get_path(model, &iter); - if ( path ) - { - gtk_tree_view_set_cursor(treeview, path, 0, 0); - gtk_tree_path_free(path); - } - else - g_warning("Unknown custom type %d\n", fmt_type); + for (i = 0; i < n_types; i++) + if (target == types[i]) + return i; + return 0; } /* Set up the state of the dialog box to match the variable VAR */ static void -var_type_dialog_set_state(struct var_type_dialog *dialog) +psppire_var_type_dialog_set_state (PsppireVarTypeDialog *dialog) { - const struct fmt_spec *write_spec ; - GString *str = g_string_new(""); + int button; - g_assert(dialog); - g_assert(dialog->pv); - - /* Populate width and decimals */ - write_spec = var_get_write_format (dialog->pv); - - g_string_printf(str, "%d", write_spec->d); - - gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), - str->str); - - g_string_printf(str, "%d", write_spec->w); - - gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), - str->str); - - g_string_free(str, TRUE); + g_return_if_fail (dialog != NULL); /* Populate the radio button states */ - switch (write_spec->type) + switch (dialog->base_format.type) { + default: case FMT_F: - var_type_dialog_set_active_button(dialog, BUTTON_NUMERIC); - gtk_widget_show_all(dialog->width_decimals); + button = BUTTON_NUMERIC; break; case FMT_A: - var_type_dialog_set_active_button(dialog, BUTTON_STRING); - gtk_widget_hide(dialog->label_decimals); - gtk_widget_hide(dialog->entry_decimals); + button = BUTTON_STRING; break; case FMT_COMMA: - var_type_dialog_set_active_button(dialog, BUTTON_COMMA); - gtk_widget_show_all(dialog->width_decimals); + button = BUTTON_COMMA; break; case FMT_DOT: - var_type_dialog_set_active_button(dialog, BUTTON_DOT); - gtk_widget_show_all(dialog->width_decimals); + button = BUTTON_DOT; break; case FMT_DOLLAR: - var_type_dialog_set_active_button(dialog, BUTTON_DOLLAR); - gtk_widget_show_all(dialog->width_decimals); - - select_treeview_from_format(dialog->dollar_treeview, write_spec); + button = BUTTON_DOLLAR; break; - case FMT_DATE: - case FMT_EDATE: - case FMT_SDATE: - case FMT_ADATE: - case FMT_JDATE: - case FMT_QYR: - case FMT_MOYR: - case FMT_WKYR: - case FMT_DATETIME: - case FMT_TIME: - case FMT_DTIME: - case FMT_WKDAY: - case FMT_MONTH: - var_type_dialog_set_active_button(dialog, BUTTON_DATE); - gtk_widget_hide(dialog->width_decimals); - gtk_widget_show(dialog->date_format_list); - select_treeview_from_format(dialog->date_format_treeview, write_spec); + case FMT_DATE: + case FMT_EDATE: + case FMT_SDATE: + case FMT_ADATE: + case FMT_JDATE: + case FMT_QYR: + case FMT_MOYR: + case FMT_WKYR: + case FMT_DATETIME: + case FMT_TIME: + case FMT_DTIME: + case FMT_WKDAY: + case FMT_MONTH: + button = BUTTON_DATE; break; case FMT_CCA: case FMT_CCB: case FMT_CCC: case FMT_CCD: case FMT_CCE: - var_type_dialog_set_active_button(dialog, BUTTON_CUSTOM); - select_treeview_from_format_type(dialog->custom_treeview, - write_spec->type); - gtk_widget_show_all(dialog->width_decimals); - break; - default: - gtk_widget_show_all(dialog->width_decimals); + button = BUTTON_CUSTOM; break; } -} - - -/* Popup the dialog box */ -void -var_type_dialog_show(struct var_type_dialog *dialog) -{ - var_type_dialog_set_state(dialog); - gtk_widget_show(dialog->window); + var_type_dialog_set_active_button (dialog, button); + refresh_active_button (dialog); + on_active_button_change (GTK_TOGGLE_BUTTON (dialog->radioButton[button]), + dialog); } - -/* Fills F with an output format specification with type TYPE, width - W, and D decimals. Iff it's a valid format, then return true. -*/ -static bool -make_output_format_try (struct fmt_spec *f, int type, int w, int d) -{ - f->type = type; - f->w = w; - f->d = d; - return fmt_check_output (f); -} - - - - -/* Callbacks for the Variable Type Dialog Box */ - -/* Callback for when the var type dialog is closed using the OK button. - It sets the appropriate variable accordingly. */ -static gint -on_var_type_ok_clicked(GtkWidget *w, gpointer data) -{ - struct var_type_dialog *dialog = data; - - g_assert(dialog); - g_assert(dialog->pv); - - { - gint width = atoi(gtk_entry_get_text - (GTK_ENTRY(dialog->entry_width))); - - gint decimals = atoi(gtk_entry_get_text - (GTK_ENTRY(dialog->entry_decimals))); - - gint new_type = VAR_NUMERIC; - gint new_width = 0; - bool result = false; - struct fmt_spec spec; - switch (dialog->active_button) - { - case BUTTON_STRING: - new_type = VAR_STRING; - new_width = width; - result = make_output_format_try(&spec, FMT_A, width, 0); - break; - case BUTTON_NUMERIC: - result = make_output_format_try(&spec, FMT_F, width, decimals); - break; - case BUTTON_COMMA: - result = make_output_format_try(&spec, FMT_COMMA, width, decimals); - break; - case BUTTON_DOT: - result = make_output_format_try(&spec, FMT_DOT, width, decimals); - break; - case BUTTON_SCIENTIFIC: - result = make_output_format_try(&spec, FMT_E, width, decimals); - break; - case BUTTON_DATE: - case BUTTON_CUSTOM: - g_assert(fmt_check_output(&dialog->fmt_l)); - result = memcpy(&spec, &dialog->fmt_l, sizeof(struct fmt_spec)); - break; - case BUTTON_DOLLAR: - result = make_output_format_try(&spec, FMT_DOLLAR, width, decimals); - break; - default: - g_print("Unknown variable type: %d\n", dialog->active_button) ; - result = false; - break; - } - - if ( result == true ) - { - var_set_width (dialog->pv, new_width); - var_set_both_formats (dialog->pv, &spec); - } - - } - gtk_widget_hide(dialog->window); - - return FALSE; -} - - - -gint -on_var_type_cancel_clicked(GtkWidget *w, gpointer data) -{ - gtk_widget_hide(w); - - return FALSE; -} -