New widget PsppireValChooser.
authorJohn Darrington <john@darrington.wattle.id.au>
Fri, 1 Jul 2011 16:39:10 +0000 (18:39 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Fri, 1 Jul 2011 16:39:10 +0000 (18:39 +0200)
This widget provides a user interface allowing the user to input the
a value, or range of values.  This was previously done "by hand" in
the recode dialog, but was awkward to maintain, and clumsy.  Upcoming
dialogs will need something very similar. So now seemed like a good
time to encapsulate it.

src/ui/gui/automake.mk
src/ui/gui/psppire-val-chooser.c [new file with mode: 0644]
src/ui/gui/psppire-val-chooser.h [new file with mode: 0644]
src/ui/gui/recode-dialog.c
src/ui/gui/recode.ui
src/ui/gui/widgets.c

index 31253dbd99123c108a25a799c85bd3d82a350871..5eccb206b9ea57749d84ae14e9f8eeaae878250d 100644 (file)
@@ -198,6 +198,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-select-dest.h \
        src/ui/gui/psppire-syntax-window.c \
        src/ui/gui/psppire-syntax-window.h \
+       src/ui/gui/psppire-val-chooser.c \
+       src/ui/gui/psppire-val-chooser.h \
        src/ui/gui/psppire-var-ptr.c \
        src/ui/gui/psppire-var-ptr.h \
        src/ui/gui/psppire-var-sheet.c \
diff --git a/src/ui/gui/psppire-val-chooser.c b/src/ui/gui/psppire-val-chooser.c
new file mode 100644 (file)
index 0000000..368eea3
--- /dev/null
@@ -0,0 +1,676 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  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 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include "psppire-val-chooser.h"
+
+#include "libpspp/str.h"
+
+
+#include "ui/syntax-gen.h"
+
+#include <gettext.h>
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+static void psppire_val_chooser_base_finalize (PsppireValChooserClass *, gpointer);
+static void psppire_val_chooser_base_init     (PsppireValChooserClass *class);
+static void psppire_val_chooser_class_init    (PsppireValChooserClass *class);
+static void psppire_val_chooser_init          (PsppireValChooser      *vc);
+
+static void psppire_val_chooser_realize       (GtkWidget *w);
+
+
+
+GType
+psppire_val_chooser_get_type (void)
+{
+  static GType psppire_val_chooser_type = 0;
+
+  if (!psppire_val_chooser_type)
+    {
+      static const GTypeInfo psppire_val_chooser_info =
+      {
+       sizeof (PsppireValChooserClass),
+       (GBaseInitFunc) psppire_val_chooser_base_init,
+        (GBaseFinalizeFunc) psppire_val_chooser_base_finalize,
+       (GClassInitFunc)psppire_val_chooser_class_init,
+       (GClassFinalizeFunc) NULL,
+       NULL,
+        sizeof (PsppireValChooser),
+       0,
+       (GInstanceInitFunc) psppire_val_chooser_init,
+      };
+
+      psppire_val_chooser_type =
+       g_type_register_static (GTK_TYPE_FRAME, "PsppireValChooser",
+                               &psppire_val_chooser_info, 0);
+    }
+
+  return psppire_val_chooser_type;
+}
+
+
+static void
+psppire_val_chooser_finalize (GObject *object)
+{
+
+}
+
+/* Properties */
+enum
+{
+  PROP_0,
+  PROP_IS_STRING,
+};
+
+
+static void
+psppire_val_chooser_set_property (GObject         *object,
+                              guint            prop_id,
+                              const GValue    *value,
+                              GParamSpec      *pspec)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_IS_STRING:
+      vr->input_var_is_string = g_value_get_boolean (value);
+
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[1].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[2].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[3].rb), !vr->input_var_is_string);
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[4].rb), !vr->input_var_is_string);      
+      gtk_widget_set_sensitive (GTK_WIDGET (vr->rw[5].rb), !vr->input_var_is_string);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static void
+psppire_val_chooser_get_property (GObject         *object,
+                              guint            prop_id,
+                              GValue          *value,
+                              GParamSpec      *pspec)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_IS_STRING:
+      g_value_set_boolean (value, vr->input_var_is_string);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static GObjectClass * parent_class = NULL;
+
+static void
+psppire_val_chooser_class_init (PsppireValChooserClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  GParamSpec *is_string_spec =
+    g_param_spec_boolean ("is-string",
+                         "String Value",
+                         "Should the value range be a string value",
+                         FALSE,
+                         G_PARAM_READWRITE);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->set_property = psppire_val_chooser_set_property;
+  object_class->get_property = psppire_val_chooser_get_property;
+
+  widget_class->realize = psppire_val_chooser_realize;
+
+  g_object_class_install_property (object_class,
+                                   PROP_IS_STRING,
+                                   is_string_spec);
+}
+
+
+static void
+psppire_val_chooser_base_init (PsppireValChooserClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = psppire_val_chooser_finalize;
+}
+
+
+
+static void
+psppire_val_chooser_base_finalize (PsppireValChooserClass *class,
+                                gpointer class_data)
+{
+
+}
+
+
+/* Set the focus of B to follow the sensitivity of A */
+static void
+focus_follows_sensitivity (GtkWidget *a, GParamSpec *pspec, GtkWidget *b)
+{
+  gboolean sens = gtk_widget_get_sensitive (a);
+
+  g_object_set (b, "has-focus", sens, NULL);
+}
+
+
+struct layout;
+typedef GtkWidget *filler_f (struct layout *, struct range_widgets *);
+typedef void set_f (PsppireValChooser *, struct old_value *, const struct range_widgets *);
+
+struct layout
+{
+  const gchar *label;
+  filler_f *fill;
+  set_f *set;
+};
+
+
+
+static void simple_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+
+  if ( vr->input_var_is_string)
+    {
+      ov->type = OV_STRING;
+      ov->v.s = g_strdup (text);
+    }
+  else
+    {
+      ov->type = OV_NUMERIC;
+      ov->v.v = g_strtod (text, 0);
+    }
+}
+
+static void lo_up_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets  *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+  
+  ov->type = OV_LOW_UP;
+  ov->v.range[1] = g_strtod (text, 0);
+}
+
+
+static void hi_down_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+  
+  ov->type = OV_HIGH_DOWN;
+  ov->v.range[0] = g_strtod (text, 0);
+}
+
+static void missing_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_MISSING;
+}
+
+
+static void sysmis_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_SYSMIS;
+}
+
+static void else_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *l)
+{
+  ov->type = OV_ELSE;
+}
+
+
+static void range_set (PsppireValChooser *vr, struct old_value *ov, const struct range_widgets *rw)
+{
+  const gchar *text = gtk_entry_get_text (rw->e1);
+
+  ov->type = OV_RANGE;
+  ov->v.range[0] = g_strtod (text, 0);
+  
+  text = gtk_entry_get_text (rw->e2);
+  ov->v.range[1] = g_strtod (text, 0);
+}
+
+static GtkWidget * range_entry (struct layout *l, struct range_widgets *rw)
+{
+  GtkWidget *vbox = gtk_vbox_new (3, FALSE);
+  GtkWidget *entrylo = gtk_entry_new ();
+  GtkWidget *label = gtk_label_new (_("through"));
+  GtkWidget *entryhi = gtk_entry_new ();
+
+  rw->e1 = GTK_ENTRY (entrylo);
+  rw->e2 = GTK_ENTRY (entryhi);
+
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+  g_signal_connect (vbox, "notify::sensitive", G_CALLBACK (focus_follows_sensitivity), entrylo);
+
+  gtk_box_pack_start (GTK_BOX (vbox), entrylo, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), entryhi, TRUE, TRUE, 0);
+  return vbox;
+}
+
+static GtkWidget * simple_entry (struct layout *l, struct range_widgets *rw)
+{
+  GtkWidget *entry = gtk_entry_new ();
+
+  rw->e1 = GTK_ENTRY (entry);
+
+  g_signal_connect (entry, "notify::sensitive", G_CALLBACK (focus_follows_sensitivity), entry);
+  return entry;
+}
+
+
+static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]= 
+  {
+    {N_("Value:"),                    simple_entry, simple_set },
+    {N_("System Missing"),            NULL,         sysmis_set },
+    {N_("System or User Missing"),    NULL,         missing_set},
+    {N_("Range:"),                    range_entry,  range_set  },
+    {N_("Range, LOWEST thru value"),  simple_entry, lo_up_set  },
+    {N_("Range, value thru HIGHEST"), simple_entry, hi_down_set},
+    {N_("All other values"),          NULL,         else_set   }
+  };
+
+static void
+set_sensitivity_from_toggle (GtkToggleButton *togglebutton,  GtkWidget *w)
+{
+  gboolean active = gtk_toggle_button_get_active (togglebutton);
+
+  gtk_widget_set_sensitive (w, active);
+}
+
+static void
+psppire_val_chooser_init (PsppireValChooser *vr)
+{
+  gint i;
+  GtkWidget *aln = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+  GtkWidget *table = gtk_table_new (11, 2, FALSE);
+  GSList *group = NULL;
+  gint row = 0;
+
+  gtk_alignment_set_padding (GTK_ALIGNMENT (aln), 0, 0, 5, 5);
+
+  vr->input_var_is_string = FALSE;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      struct layout *l = &range_opt[i];
+      GtkWidget *label = gtk_label_new (gettext (l->label));
+      vr->rw[i].rb = GTK_TOGGLE_BUTTON (gtk_radio_button_new (group));
+
+      gtk_widget_set_sensitive (label, FALSE);
+      g_signal_connect (vr->rw[i].rb, "toggled", G_CALLBACK (set_sensitivity_from_toggle), label);
+
+      gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+      group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (vr->rw[i].rb));
+
+      gtk_table_attach_defaults (GTK_TABLE (table), GTK_WIDGET (vr->rw[i].rb), 0, 1,
+                                row, row + 1);
+
+
+      gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2,
+                                row, row + 1);
+      ++row;
+
+      if (l->fill)
+       {
+         GtkWidget *fill = l->fill (l, &vr->rw[i]);
+
+         gtk_widget_set_sensitive (fill, FALSE);
+
+         gtk_table_attach_defaults (GTK_TABLE (table), fill, 1, 2,
+                                row, row + 1);
+         ++row;
+
+         g_signal_connect (vr->rw[i].rb, "toggled", G_CALLBACK (set_sensitivity_from_toggle), fill);
+       }
+    }
+
+  gtk_frame_set_shadow_type (GTK_FRAME (vr), GTK_SHADOW_ETCHED_IN);
+
+  gtk_container_add (GTK_CONTAINER (aln), table);
+  gtk_container_add (GTK_CONTAINER (vr), aln);
+
+  gtk_widget_show_all (aln);
+}
+
+
+GtkWidget*
+psppire_val_chooser_new (void)
+{
+  return GTK_WIDGET (g_object_new (psppire_val_chooser_get_type (), NULL));
+}
+
+
+
+static void
+psppire_val_chooser_realize (GtkWidget *w)
+{
+  PsppireValChooser *vr = PSPPIRE_VAL_CHOOSER (w);
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(vr->rw[0].rb), TRUE);
+  gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (vr->rw[0].rb));
+
+  /* Chain up to the parent class */
+  GTK_WIDGET_CLASS (parent_class)->realize (w);
+}
+
+
+\f
+
+/* A boxed type representing a value, or a range of values which may
+   potentially be replaced by something */
+
+
+static struct old_value *
+old_value_copy (struct old_value *ov)
+{
+  struct old_value *copy = g_memdup (ov, sizeof (*copy));
+
+  if ( ov->type == OV_STRING )
+    copy->v.s = g_strdup (ov->v.s);
+
+  return copy;
+}
+
+
+static void
+old_value_free (struct old_value *ov)
+{
+  if (ov->type == OV_STRING)
+    g_free (ov->v.s);
+  g_free (ov);
+}
+
+static void
+old_value_to_string (const GValue *src, GValue *dest)
+{
+  const struct old_value *ov = g_value_get_boxed (src);
+
+  switch (ov->type)
+    {
+    case OV_NUMERIC:
+      {
+       gchar *text = g_strdup_printf ("%g", ov->v.v);
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_STRING:
+      g_value_set_string (dest, ov->v.s);
+      break;
+    case OV_MISSING:
+      g_value_set_string (dest, "MISSING");
+      break;
+    case OV_SYSMIS:
+      g_value_set_string (dest, "SYSMIS");
+      break;
+    case OV_ELSE:
+      g_value_set_string (dest, "ELSE");
+      break;
+    case OV_RANGE:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("%g %s %g",
+                                      ov->v.range[0],
+                                      en_dash,
+                                      ov->v.range[1]);
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_LOW_UP:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("LOWEST %s %g",
+                               en_dash,
+                               ov->v.range[1]);
+
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    case OV_HIGH_DOWN:
+      {
+       gchar *text;
+       char en_dash[6] = {0,0,0,0,0,0};
+
+       g_unichar_to_utf8 (0x2013, en_dash);
+
+       text = g_strdup_printf ("%g %s HIGHEST",
+                               ov->v.range[0],
+                               en_dash);
+
+       g_value_set_string (dest, text);
+       g_free (text);
+      }
+      break;
+    default:
+      g_warning ("Invalid type in old recode value");
+      g_value_set_string (dest, "???");
+      break;
+    };
+}
+
+GType
+old_value_get_type (void)
+{
+  static GType t = 0;
+
+  if (t == 0 )
+    {
+      t = g_boxed_type_register_static  ("psppire-recode-old-values",
+                                        (GBoxedCopyFunc) old_value_copy,
+                                        (GBoxedFreeFunc) old_value_free);
+
+      g_value_register_transform_func     (t, G_TYPE_STRING,
+                                          old_value_to_string);
+    }
+
+  return t;
+}
+
+\f
+
+/* Generate a syntax fragment for NV and append it to STR */
+void
+old_value_append_syntax (GString *str, const struct old_value *ov)
+{
+  switch (ov->type)
+    {
+    case OV_NUMERIC:
+      g_string_append_printf (str, "%g", ov->v.v);
+      break;
+    case OV_STRING:
+      {
+       struct string ds = DS_EMPTY_INITIALIZER;
+       syntax_gen_string (&ds, ss_cstr (ov->v.s));
+       g_string_append (str, ds_cstr (&ds));
+       ds_destroy (&ds);
+      }
+      break;
+    case OV_MISSING:
+      g_string_append (str, "MISSING");
+      break;
+    case OV_SYSMIS:
+      g_string_append (str, "SYSMIS");
+      break;
+    case OV_ELSE:
+      g_string_append (str, "ELSE");
+      break;
+    case OV_RANGE:
+      g_string_append_printf (str, "%g THRU %g",
+                             ov->v.range[0],
+                             ov->v.range[1]);
+      break;
+    case OV_LOW_UP:
+      g_string_append_printf (str, "LOWEST THRU %g",
+                             ov->v.range[1]);
+      break;
+    case OV_HIGH_DOWN:
+      g_string_append_printf (str, "%g THRU HIGHEST",
+                             ov->v.range[0]);
+      break;
+    default:
+      g_warning ("Invalid type in old recode value");
+      g_string_append (str, "???");
+      break;
+    };
+}
+
+
+
+/* Set OV according to the current state of VR */
+void
+psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov)
+{
+  int i;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (vr->rw[i].rb)))
+       {
+         break;
+       }
+    }
+
+  range_opt[i].set (vr, ov, &vr->rw[i]);
+}
+
+/* This might need to be changed to something less naive.
+   In particular, what happends with dates, etc?
+ */
+static gchar *
+num_to_string (gdouble x)
+{
+  return g_strdup_printf ("%g", x);
+}
+
+
+/* Set VR according to the value of OV */
+void
+psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *ov)
+{
+  gint i;
+  if ( !ov )
+    return;
+
+  for (i = 0; i < n_VAL_CHOOSER_BUTTONS; ++i)
+    {
+      if (vr->rw[i].e1)
+       gtk_entry_set_text (vr->rw[i].e1, "");
+
+      if (vr->rw[i].e2)
+       gtk_entry_set_text (vr->rw[i].e2, "");
+    }
+
+  switch (ov->type)
+    {
+    case OV_STRING:
+      gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
+      gtk_entry_set_text (vr->rw[0].e1, ov->v.s);
+      break;
+      
+    case OV_NUMERIC:
+      {
+       gchar *str;
+       gtk_toggle_button_set_active (vr->rw[0].rb, TRUE);
+       
+       str = num_to_string (ov->v.v);
+       
+       gtk_entry_set_text (vr->rw[0].e1, str);
+       g_free (str);
+      }
+      break;
+
+      case OV_SYSMIS:
+       gtk_toggle_button_set_active (vr->rw[1].rb, TRUE);
+       break;
+
+      case OV_MISSING:
+       gtk_toggle_button_set_active (vr->rw[2].rb, TRUE);
+       break;
+
+      case OV_RANGE:
+       {
+         gchar *str = num_to_string (ov->v.range[0]);
+         gtk_toggle_button_set_active (vr->rw[3].rb, TRUE);
+         gtk_entry_set_text (vr->rw[3].e1, str);
+
+         g_free (str);
+
+         str = num_to_string (ov->v.range[1]);
+         gtk_entry_set_text (vr->rw[3].e2, str);
+         g_free (str);
+       }
+       break;
+
+      case OV_LOW_UP:
+       {
+         gchar *str = num_to_string (ov->v.range[1]);
+
+         gtk_toggle_button_set_active (vr->rw[4].rb, TRUE);
+
+         gtk_entry_set_text (vr->rw[4].e1, str);
+
+         g_free (str);
+       }
+       break;
+
+
+      case OV_HIGH_DOWN:
+       {
+         gchar *str = num_to_string (ov->v.range[0]);
+
+         gtk_toggle_button_set_active (vr->rw[5].rb, TRUE);
+
+         gtk_entry_set_text (vr->rw[5].e1, str);
+
+         g_free (str);
+       }
+       break;
+
+      case OV_ELSE:
+       gtk_toggle_button_set_active (vr->rw[6].rb, TRUE);
+       break;
+
+    default:
+      g_warning ("Unknown old value type");
+      break;
+    };
+}
diff --git a/src/ui/gui/psppire-val-chooser.h b/src/ui/gui/psppire-val-chooser.h
new file mode 100644 (file)
index 0000000..6ef546e
--- /dev/null
@@ -0,0 +1,104 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2011  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 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+
+#ifndef __PSPPIRE_VAL_CHOOSER_H__
+#define __PSPPIRE_VAL_CHOOSER_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define PSPPIRE_VAL_CHOOSER_TYPE            (psppire_val_chooser_get_type ())
+#define PSPPIRE_VAL_CHOOSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_VAL_CHOOSER_TYPE, PsppireValChooser))
+#define PSPPIRE_VAL_CHOOSER_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), \
+    PSPPIRE_VAL_CHOOSER_TYPE, PsppireValChooserClass))
+#define PSPPIRE_IS_VAL_CHOOSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+    PSPPIRE_VAL_CHOOSER_TYPE))
+#define PSPPIRE_IS_VAL_CHOOSER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
+    PSPPIRE_VAL_CHOOSER_TYPE))
+
+
+typedef struct _PsppireValChooser       PsppireValChooser;
+typedef struct _PsppireValChooserClass  PsppireValChooserClass;
+
+#define n_VAL_CHOOSER_BUTTONS 7
+
+struct range_widgets
+{
+  GtkToggleButton *rb;
+  GtkEntry *e1;
+  GtkEntry *e2;
+};
+
+struct _PsppireValChooser
+{
+  GtkFrame parent;
+
+  struct range_widgets rw [n_VAL_CHOOSER_BUTTONS];
+  gboolean input_var_is_string;
+};
+
+struct _PsppireValChooserClass
+{
+  GtkTreeViewClass parent_class;
+
+};
+
+GType      psppire_val_chooser_get_type        (void);
+
+
+G_END_DECLS
+
+
+\f
+
+enum old_value_type
+ {
+   OV_NUMERIC,
+   OV_STRING,
+   OV_SYSMIS,
+   OV_MISSING,
+   OV_RANGE,
+   OV_LOW_UP,
+   OV_HIGH_DOWN,
+   OV_ELSE
+ };
+
+struct old_value
+ {
+   enum old_value_type type;
+   union {
+     double v;
+     gchar *s;
+     double range[2];
+   } v;
+ };
+
+GType old_value_get_type (void);
+
+void old_value_append_syntax (GString *str, const struct old_value *ov);
+
+void psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov);
+void psppire_val_chooser_set_status (PsppireValChooser *vr, const struct old_value *ov);
+
+
+
+#endif /* __PSPPIRE_VAL_CHOOSER_H__ */
index 5d97c156c4d9b5175af3295f9e6248679bd4748b..d92517c757a7e5d7cbbb246f10388c5a8a50eb84 100644 (file)
@@ -38,6 +38,8 @@
 #include <ui/gui/psppire-dialog.h>
 #include <ui/gui/psppire-var-store.h>
 
+#include "psppire-val-chooser.h"
+
 #include <ui/syntax-gen.h>
 
 #include "psppire-acr.h"
@@ -143,151 +145,6 @@ new_value_get_type (void)
 }
 
 
-\f
-
-
-/* A boxed type representing a value, or a range of values which may
-   potentially be replaced by something */
-
-enum old_value_type
- {
-   OV_NUMERIC,
-   OV_STRING,
-   OV_SYSMIS,
-   OV_MISSING,
-   OV_RANGE,
-   OV_LOW_UP,
-   OV_HIGH_DOWN,
-   OV_ELSE
- };
-
-struct old_value
- {
-   enum old_value_type type;
-   union {
-     double v;
-     gchar *s;
-     double range[2];
-   } v;
- };
-
-
-static struct old_value *
-old_value_copy (struct old_value *ov)
-{
-  struct old_value *copy = g_memdup (ov, sizeof (*copy));
-
-  if ( ov->type == OV_STRING )
-    copy->v.s = g_strdup (ov->v.s);
-
-  return copy;
-}
-
-
-static void
-old_value_free (struct old_value *ov)
-{
-  if (ov->type == OV_STRING)
-    g_free (ov->v.s);
-  g_free (ov);
-}
-
-static void
-old_value_to_string (const GValue *src, GValue *dest)
-{
-  const struct old_value *ov = g_value_get_boxed (src);
-
-  switch (ov->type)
-    {
-    case OV_NUMERIC:
-      {
-       gchar *text = g_strdup_printf ("%g", ov->v.v);
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_STRING:
-      g_value_set_string (dest, ov->v.s);
-      break;
-    case OV_MISSING:
-      g_value_set_string (dest, "MISSING");
-      break;
-    case OV_SYSMIS:
-      g_value_set_string (dest, "SYSMIS");
-      break;
-    case OV_ELSE:
-      g_value_set_string (dest, "ELSE");
-      break;
-    case OV_RANGE:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("%g %s %g",
-                                      ov->v.range[0],
-                                      en_dash,
-                                      ov->v.range[1]);
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_LOW_UP:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("LOWEST %s %g",
-                               en_dash,
-                               ov->v.range[1]);
-
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    case OV_HIGH_DOWN:
-      {
-       gchar *text;
-       char en_dash[6] = {0,0,0,0,0,0};
-
-       g_unichar_to_utf8 (0x2013, en_dash);
-
-       text = g_strdup_printf ("%g %s HIGHEST",
-                               ov->v.range[0],
-                               en_dash);
-
-       g_value_set_string (dest, text);
-       g_free (text);
-      }
-      break;
-    default:
-      g_warning ("Invalid type in old recode value");
-      g_value_set_string (dest, "???");
-      break;
-    };
-}
-
-static GType
-old_value_get_type (void)
-{
-  static GType t = 0;
-
-  if (t == 0 )
-    {
-      t = g_boxed_type_register_static  ("psppire-recode-old-values",
-                                        (GBoxedCopyFunc) old_value_copy,
-                                        (GBoxedFreeFunc) old_value_free);
-
-      g_value_register_transform_func     (t, G_TYPE_STRING,
-                                          old_value_to_string);
-    }
-
-  return t;
-}
-
 \f
 
 enum
@@ -295,13 +152,6 @@ enum
     BUTTON_NEW_VALUE,
     BUTTON_NEW_COPY,
     BUTTON_NEW_SYSMIS,
-    BUTTON_OLD_VALUE,
-    BUTTON_OLD_SYSMIS,
-    BUTTON_OLD_MISSING,
-    BUTTON_OLD_RANGE,
-    BUTTON_OLD_LOW_UP,
-    BUTTON_OLD_HIGH_DOWN,
-    BUTTON_OLD_ELSE,
     n_BUTTONS
   };
 
@@ -320,13 +170,9 @@ struct recode_dialog
   GtkWidget *convert_button;
   GtkWidget *new_copy_label;
 
-  GtkWidget *ov_value_entry;
   GtkWidget *new_value_entry;
 
-  GtkWidget *ov_range_lower_entry;
-  GtkWidget *ov_range_upper_entry;
-  GtkWidget *ov_low_up_entry;
-  GtkWidget *ov_high_down_entry;
+  GtkWidget *old_value_chooser;
 
   GtkListStore *value_map;
 
@@ -416,11 +262,6 @@ dialog_state_valid (gpointer data)
 static void
 on_old_new_show (struct recode_dialog *rd)
 {
-  gtk_toggle_button_set_active
-    (GTK_TOGGLE_BUTTON (rd->toggle[BUTTON_OLD_VALUE]), TRUE);
-
-  g_signal_emit_by_name (rd->toggle[BUTTON_OLD_VALUE], "toggled");
-
   gtk_toggle_button_set_active
     (GTK_TOGGLE_BUTTON (rd->toggle[BUTTON_NEW_VALUE]), TRUE);
 
@@ -545,101 +386,7 @@ on_acr_selection_change (GtkTreeSelection *selection, gpointer data)
       g_value_unset (&nv_value);
     }
 
-  if ( ov )
-    {
-    switch (ov->type)
-      {
-      case OV_STRING:
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_VALUE]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_value_entry), ov->v.s);
-       break;
-
-      case OV_NUMERIC:
-       {
-         gchar *str;
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_VALUE]), TRUE);
-
-         str = num_to_string (ov->v.v);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_value_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_SYSMIS:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_SYSMIS]), TRUE);
-       break;
-
-      case OV_MISSING:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_MISSING]), TRUE);
-       break;
-
-      case OV_RANGE:
-       {
-         gchar *str;
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_RANGE]), TRUE);
-
-         str = num_to_string (ov->v.range[0]);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_range_lower_entry), str);
-
-         g_free (str);
-
-
-         str = num_to_string (ov->v.range[1]);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_range_upper_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_LOW_UP:
-       {
-         gchar *str = num_to_string (ov->v.range[1]);
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_LOW_UP]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_low_up_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_HIGH_DOWN:
-       {
-         gchar *str = num_to_string (ov->v.range[0]);
-
-         gtk_toggle_button_set_active
-           (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_HIGH_DOWN]), TRUE);
-
-         gtk_entry_set_text (GTK_ENTRY (rd->ov_high_down_entry), str);
-
-         g_free (str);
-       }
-       break;
-
-      case OV_ELSE:
-       gtk_toggle_button_set_active
-         (GTK_TOGGLE_BUTTON (rd->toggle [BUTTON_OLD_ELSE]), TRUE);
-       break;
-
-      default:
-       g_warning ("Unknown old value type");
-       break;
-      };
-    g_value_unset (&ov_value);
-    }
+  psppire_val_chooser_set_status (PSPPIRE_VAL_CHOOSER (rd->old_value_chooser), ov);
 }
 
 /* Name-Label pair */
@@ -929,10 +676,6 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
       g_signal_connect (rd.change_button, "clicked",
                        G_CALLBACK (on_change_clicked),  &rd);
 
-#if 0
-      g_signal_connect (model, "row-inserted",
-                       G_CALLBACK (select_something), &rd);
-#endif
     }
 
   psppire_selector_set_allow (PSPPIRE_SELECTOR (selector), homogeneous_types);
@@ -944,24 +687,14 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
 
     rd.convert_button           = get_widget_assert (builder, "checkbutton2");
 
-    rd.ov_range_lower_entry = get_widget_assert (builder, "entry5");
-    rd.ov_range_upper_entry  = get_widget_assert (builder, "entry3");
-    rd.ov_low_up_entry       = get_widget_assert (builder, "entry6");
-    rd.ov_high_down_entry    = get_widget_assert (builder, "entry7");
+    rd.old_value_chooser = get_widget_assert (builder, "val-chooser");
 
     rd.new_value_entry = get_widget_assert (builder, "entry1");
-    rd.ov_value_entry  = get_widget_assert (builder, "entry2");
+
 
     rd.toggle[BUTTON_NEW_VALUE]  = get_widget_assert (builder, "radiobutton1");
     rd.toggle[BUTTON_NEW_SYSMIS] = get_widget_assert (builder, "radiobutton2");
     rd.toggle[BUTTON_NEW_COPY]   = get_widget_assert (builder, "radiobutton3");
-    rd.toggle[BUTTON_OLD_VALUE]  = get_widget_assert (builder, "radiobutton4");
-    rd.toggle[BUTTON_OLD_SYSMIS] = get_widget_assert (builder, "radiobutton6");
-    rd.toggle[BUTTON_OLD_MISSING]= get_widget_assert (builder, "radiobutton7");
-    rd.toggle[BUTTON_OLD_RANGE]  = get_widget_assert (builder, "radiobutton8");
-    rd.toggle[BUTTON_OLD_LOW_UP] = get_widget_assert (builder, "radiobutton10");
-    rd.toggle[BUTTON_OLD_HIGH_DOWN] = get_widget_assert (builder, "radiobutton5");
-    rd.toggle[BUTTON_OLD_ELSE]   = get_widget_assert (builder, "radiobutton11");
 
     rd.new_copy_label = get_widget_assert (builder, "label3");
     rd.strings_box    = get_widget_assert (builder, "table3");
@@ -1018,23 +751,6 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
     g_signal_connect (rd.toggle[BUTTON_NEW_VALUE], "toggled",
                      G_CALLBACK (toggle_sensitivity), rd.new_value_entry);
 
-    g_signal_connect (rd.toggle[BUTTON_OLD_VALUE], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_value_entry);
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_RANGE], "toggled",
-                     G_CALLBACK (toggle_sensitivity),
-                     get_widget_assert (builder, "entry3"));
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_RANGE], "toggled",
-                     G_CALLBACK (toggle_sensitivity),
-                     get_widget_assert (builder, "entry5"));
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_LOW_UP], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_low_up_entry);
-
-    g_signal_connect (rd.toggle[BUTTON_OLD_HIGH_DOWN], "toggled",
-                     G_CALLBACK (toggle_sensitivity), rd.ov_high_down_entry);
-
     g_signal_connect (rd.string_button, "toggled",
                      G_CALLBACK (toggle_sensitivity), rd.width_entry);
 
@@ -1081,70 +797,11 @@ recode_dialog (PsppireDataWindow *de, gboolean diff)
 static gboolean
 set_old_value (GValue *val, const struct recode_dialog *rd)
 {
-  const gchar *text = NULL;
-  struct old_value ov;
-  if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                    (rd->toggle [BUTTON_OLD_VALUE])))
-    {
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_value_entry));
-      if ( rd->input_var_is_string )
-       {
-         ov.type = OV_STRING;
-         ov.v.s = g_strdup (text);
-       }
-      else
-       {
-         ov.type = OV_NUMERIC;
-         ov.v.v = g_strtod (text, 0);
-       }
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_MISSING])))
-    {
-      ov.type = OV_MISSING;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_SYSMIS])))
-    {
-      ov.type = OV_SYSMIS;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_ELSE])))
-    {
-      ov.type = OV_ELSE;
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_RANGE])))
-    {
-      const gchar *text;
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_range_lower_entry));
-
-      ov.type = OV_RANGE;
-      ov.v.range[0] = g_strtod (text, 0);
+  PsppireValChooser *vc = PSPPIRE_VAL_CHOOSER (rd->old_value_chooser);
 
-      text = gtk_entry_get_text (GTK_ENTRY (rd->ov_range_upper_entry));
-      ov.v.range[1] = g_strtod (text, 0);
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_LOW_UP])))
-    {
-      const gchar *text =
-       gtk_entry_get_text (GTK_ENTRY (rd->ov_low_up_entry));
+  struct old_value ov;
 
-      ov.type = OV_LOW_UP;
-      ov.v.range[1] = g_strtod (text, 0);
-    }
-  else if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
-                                         (rd->toggle [BUTTON_OLD_HIGH_DOWN])))
-    {
-      const gchar *text =
-       gtk_entry_get_text (GTK_ENTRY (rd->ov_high_down_entry));
-
-      ov.type = OV_HIGH_DOWN;
-      ov.v.range[0] = g_strtod (text, 0);
-    }
-  else
-    return FALSE;
+  psppire_val_chooser_get_status (vc, &ov);
 
   g_value_init (val, old_value_get_type ());
   g_value_set_boxed (val, &ov);
@@ -1255,14 +912,8 @@ run_old_and_new_dialog (struct recode_dialog *rd)
 
     rd->input_var_is_string = var_is_alpha (v);
 
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_SYSMIS],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_RANGE],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_LOW_UP],
-                             var_is_numeric (v));
-    gtk_widget_set_sensitive (rd->toggle [BUTTON_OLD_HIGH_DOWN],
-                             var_is_numeric (v));
+    g_object_set (rd->old_value_chooser, "is-string", rd->input_var_is_string, NULL);
+
     gtk_widget_set_sensitive (rd->toggle [BUTTON_NEW_SYSMIS],
                              var_is_numeric (v));
 
@@ -1319,54 +970,6 @@ new_value_append_syntax (GString *str, const struct new_value *nv)
 }
 
 
-/* Generate a syntax fragment for NV and append it to STR */
-static void
-old_value_append_syntax (GString *str, const struct old_value *ov)
-{
-  switch (ov->type)
-    {
-    case OV_NUMERIC:
-      g_string_append_printf (str, "%g", ov->v.v);
-      break;
-    case OV_STRING:
-      {
-       struct string ds = DS_EMPTY_INITIALIZER;
-       syntax_gen_string (&ds, ss_cstr (ov->v.s));
-       g_string_append (str, ds_cstr (&ds));
-       ds_destroy (&ds);
-      }
-      break;
-    case OV_MISSING:
-      g_string_append (str, "MISSING");
-      break;
-    case OV_SYSMIS:
-      g_string_append (str, "SYSMIS");
-      break;
-    case OV_ELSE:
-      g_string_append (str, "ELSE");
-      break;
-    case OV_RANGE:
-      g_string_append_printf (str, "%g THRU %g",
-                             ov->v.range[0],
-                             ov->v.range[1]);
-      break;
-    case OV_LOW_UP:
-      g_string_append_printf (str, "LOWEST THRU %g",
-                             ov->v.range[1]);
-      break;
-    case OV_HIGH_DOWN:
-      g_string_append_printf (str, "%g THRU HIGHEST",
-                             ov->v.range[0]);
-      break;
-    default:
-      g_warning ("Invalid type in old recode value");
-      g_string_append (str, "???");
-      break;
-    };
-}
-
-
-
 static char *
 generate_syntax (const struct recode_dialog *rd)
 {
index 45a3a6cc2c4fea79611996484ae8be214becbefe..f9b758279635b99104d11dcc53b0add4caa22185 100644 (file)
         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
         <property name="spacing">5</property>
         <child>
-          <object class="GtkFrame" id="frame2">
+          <object class="PsppireValChooser" id="val-chooser">
+           <property name="label" translatable="yes">Old Value</property>
             <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="label_xalign">0</property>
-            <child>
-              <object class="GtkAlignment" id="alignment3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="left_padding">12</property>
-                <property name="right_padding">5</property>
-                <child>
-                  <object class="GtkTable" id="table2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="n_rows">11</property>
-                    <property name="n_columns">2</property>
-                    <child>
-                      <object class="GtkAlignment" id="alignment11">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry7">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">9</property>
-                        <property name="bottom_attach">10</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment10">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry6">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton6">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton7">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton8">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton10">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label6">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Value:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label7">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">System Missing</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label8">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">System or User Missing</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkVBox" id="vbox2">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkAlignment" id="alignment9">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="xscale">0</property>
-                            <child>
-                              <object class="GtkEntry" id="entry5">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label9">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">through</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkAlignment" id="alignment7">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="xalign">0</property>
-                            <property name="xscale">0</property>
-                            <child>
-                              <object class="GtkEntry" id="entry3">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label11">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range, LOWEST thru value</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label12">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range, value thru HIGHEST</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">8</property>
-                        <property name="bottom_attach">9</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton11">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">radiobutton4</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                        <property name="x_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label13">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">All other values</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">10</property>
-                        <property name="bottom_attach">11</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkAlignment" id="alignment6">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="xscale">0</property>
-                        <child>
-                          <object class="GtkEntry" id="entry2">
-                            <property name="visible">True</property>
-                            <property name="sensitive">False</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label10">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Range:</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child type="label">
-              <object class="GtkLabel" id="label5">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label" translatable="yes">Old Value</property>
-                <property name="use_markup">True</property>
-              </object>
-            </child>
           </object>
           <packing>
             <property name="position">0</property>
index a1a55d1453a3816bd1a3bdf68c7b0b833bf3bccc..9a634f73f333d005425f630d4283ea946ef587f3 100644 (file)
@@ -11,6 +11,7 @@
 #include "psppire-acr.h"
 #include "psppire-dictview.h"
 #include "psppire-var-view.h"
+#include "psppire-val-chooser.h"
 
 
 /* Any custom widgets which are to be used in GtkBuilder ui files
@@ -19,6 +20,7 @@
 void
 preregister_widgets (void)
 {
+  psppire_val_chooser_get_type ();
   psppire_dialog_get_type ();
   psppire_selector_get_type ();
   psppire_vbutton_box_get_type ();