Added a dialog box for the MEANS command 20120213030503/pspp
authorJohn Darrington <john@darrington.wattle.id.au>
Sun, 12 Feb 2012 10:25:31 +0000 (11:25 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Sun, 12 Feb 2012 10:26:07 +0000 (11:26 +0100)
src/ui/gui/automake.mk
src/ui/gui/data-editor.ui
src/ui/gui/means.ui [new file with mode: 0644]
src/ui/gui/psppire-dialog-action-means.c [new file with mode: 0644]
src/ui/gui/psppire-dialog-action-means.h [new file with mode: 0644]
src/ui/gui/psppire-means-layer.c [new file with mode: 0644]
src/ui/gui/psppire-means-layer.h [new file with mode: 0644]
src/ui/gui/psppire-var-view.c
src/ui/gui/psppire-var-view.h
src/ui/gui/widgets.c

index 560d44af835ea58582dc410611dd5754ef1ef9ef..7dcfa5ed0b247c9b44ef3a450cd6afa2b11972c6 100644 (file)
@@ -21,6 +21,7 @@ UI_FILES = \
        src/ui/gui/k-means.ui \
        src/ui/gui/k-related.ui \
        src/ui/gui/ks-one-sample.ui \
+       src/ui/gui/means.ui \
        src/ui/gui/oneway.ui \
        src/ui/gui/paired-samples.ui \
        src/ui/gui/psppire.ui \
@@ -214,6 +215,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-dialog-action-descriptives.h \
        src/ui/gui/psppire-dialog-action-kmeans.c \
        src/ui/gui/psppire-dialog-action-kmeans.h \
+       src/ui/gui/psppire-dialog-action-means.c \
+       src/ui/gui/psppire-dialog-action-means.h \
        src/ui/gui/psppire-dialog-action-reliability.c \
        src/ui/gui/psppire-dialog-action-reliability.h \
        src/ui/gui/psppire-dialog-action-sort.c \
@@ -232,6 +235,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-keypad.h \
        src/ui/gui/psppire-lex-reader.c \
        src/ui/gui/psppire-lex-reader.h \
+       src/ui/gui/psppire-means-layer.c \
+       src/ui/gui/psppire-means-layer.h \
        src/ui/gui/psppire-output-window.c \
        src/ui/gui/psppire-output-window.h \
        src/ui/gui/psppire-var-view.c \
index 88449fb7039c552dfbcfb8778c0eb7ae4ac540c0..3e9179681292f475b3ace88a938c8c5d6bb3a413 100644 (file)
             <property name="label" translatable="yes">Compare _Means</property>
           </object>
         </child>
+        <child>
+          <object class="PsppireDialogActionMeans" id="means">
+            <property name="name">means</property>
+            <property name="manager">uimanager1</property>
+            <property name="label" translatable="yes">_Means...</property>
+          </object>
+        </child>
         <child>
           <object class="GtkAction" id="one-sample-t-test">
             <property name="name">one-sample-t-test</property>
             <menuitem action="crosstabs"/>
           </menu>
           <menu action="compare-means">
+            <menuitem action="means"/>
             <menuitem action="one-sample-t-test"/>
             <menuitem action="indep-t-test"/>
             <menuitem action="paired-t-test"/>
diff --git a/src/ui/gui/means.ui b/src/ui/gui/means.ui
new file mode 100644 (file)
index 0000000..f0c2138
--- /dev/null
@@ -0,0 +1,177 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="psppire" version="2054.17080"/>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy project-wide -->
+  <object class="PsppireDialog" id="means-dialog">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="title" translatable="yes">Means</property>
+    <property name="modal">True</property>
+    <child internal-child="hbox">
+      <object class="GtkHBox" id="dialog-hbox16">
+        <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="spacing">2</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="top_padding">5</property>
+            <property name="bottom_padding">5</property>
+            <property name="left_padding">5</property>
+            <child>
+              <object class="GtkHBox" id="hbox24">
+                <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>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow16">
+                    <property name="visible">True</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>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">etched-in</property>
+                    <child>
+                      <object class="PsppireDictView" id="all-variables">
+                        <property name="visible">True</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>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment19">
+                    <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="yalign">0.25</property>
+                    <property name="xscale">0</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <object class="PsppireSelector" id="stat-var-selector">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">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="border_width">5</property>
+                        <property name="source_widget">all-variables</property>
+                        <property name="dest_widget">stat-variables</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVPaned" id="vpaned1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkFrame" id="frame1">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment2">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow17">
+                                <property name="visible">True</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>
+                                <property name="hscrollbar_policy">never</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                                <property name="shadow_type">etched-in</property>
+                                <child>
+                                  <object class="PsppireVarView" id="stat-variables">
+                                    <property name="visible">True</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>
+                                    <property name="headers_visible">False</property>
+                                    <property name="headers_clickable">False</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">_Dependent List:</property>
+                            <property name="use_markup">True</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">stat-variables</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">False</property>
+                        <property name="shrink">True</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFrame" id="frame2">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment3">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label2">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">_Independent List:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="resize">True</property>
+                        <property name="shrink">True</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="PsppireVButtonBox" id="psppire-buttonbox6">
+            <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="border_width">5</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/ui/gui/psppire-dialog-action-means.c b/src/ui/gui/psppire-dialog-action-means.c
new file mode 100644 (file)
index 0000000..8d378e2
--- /dev/null
@@ -0,0 +1,136 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2012  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 "psppire-dialog-action-means.h"
+
+#include "psppire-means-layer.h"
+
+#include "psppire-var-view.h"
+#include "psppire-dict.h"
+#include "psppire-dialog.h"
+#include "builder-wrapper.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+static void psppire_dialog_action_means_class_init      (PsppireDialogActionMeansClass *class);
+
+G_DEFINE_TYPE (PsppireDialogActionMeans, psppire_dialog_action_means, PSPPIRE_TYPE_DIALOG_ACTION);
+
+
+static char *
+generate_syntax (PsppireDialogAction *act)
+{
+  gint l;
+  PsppireDialogActionMeans *scd = PSPPIRE_DIALOG_ACTION_MEANS (act);
+  gchar *text;
+  GString *string = g_string_new ("MEANS TABLES = ");
+  PsppireMeansLayer *layer = PSPPIRE_MEANS_LAYER (scd->layer);
+  psppire_var_view_append_names (PSPPIRE_VAR_VIEW (scd->variables), 0, string);
+
+  for (l = 0; l < layer->n_layers; ++l)
+    {
+      gboolean ok;
+      GtkTreeIter iter;
+      PsppireVarView *vv = PSPPIRE_VAR_VIEW (layer->var_view);
+      psppire_var_view_set_current_model (vv, l);
+      g_string_append (string, "\n\tBY");
+      for (ok = psppire_var_view_get_iter_first (vv, &iter);
+          ok;
+          ok = psppire_var_view_get_iter_next (vv, &iter))
+         {
+           const struct variable *var = psppire_var_view_get_variable (vv, 0, &iter);
+           g_string_append (string, " ");
+           g_string_append (string, var_get_name (var));
+         }
+    }
+
+  g_string_append (string, ".");
+  text = string->str;
+
+  g_string_free (string, FALSE);
+
+  return text;
+}
+
+static gboolean
+dialog_state_valid (PsppireDialogAction *da)
+{
+  PsppireDialogActionMeans *pdm  = PSPPIRE_DIALOG_ACTION_MEANS (da);
+  GtkTreeIter notused;
+  GtkTreeModel *vars =
+    gtk_tree_view_get_model (GTK_TREE_VIEW (pdm->variables));
+
+  return gtk_tree_model_get_iter_first (vars, &notused);
+}
+
+static void
+dialog_refresh (PsppireDialogAction *da)
+{
+  PsppireDialogActionMeans *pdm  = PSPPIRE_DIALOG_ACTION_MEANS (da);
+  GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (pdm->variables));
+
+  gtk_list_store_clear (GTK_LIST_STORE (liststore));
+
+  psppire_means_layer_clear (PSPPIRE_MEANS_LAYER (pdm->layer));
+}
+
+static void
+psppire_dialog_action_means_activate (GtkAction *a)
+{
+  PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
+  PsppireDialogActionMeans *act = PSPPIRE_DIALOG_ACTION_MEANS (a);
+
+  GtkBuilder *xml = builder_new ("means.ui");
+
+  GtkWidget *vb =   get_widget_assert   (xml, "alignment3");
+  act->layer = psppire_means_layer_new ();
+  gtk_container_add (GTK_CONTAINER (vb), act->layer);
+  gtk_widget_show (act->layer);
+
+  pda->dialog = get_widget_assert   (xml, "means-dialog");
+  pda->source = get_widget_assert   (xml, "all-variables");
+  act->variables = get_widget_assert   (xml, "stat-variables");
+
+  g_object_set (pda->source,
+               "model", pda->dict,
+               "predicate", var_is_numeric,
+               NULL);
+
+  psppire_means_layer_set_source (PSPPIRE_MEANS_LAYER (act->layer), pda->source);
+
+  psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid);
+  psppire_dialog_action_set_refresh (pda, dialog_refresh);
+
+  PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_means_parent_class)->activate (pda);
+}
+
+static void
+psppire_dialog_action_means_class_init (PsppireDialogActionMeansClass *class)
+{
+  GTK_ACTION_CLASS (class)->activate = psppire_dialog_action_means_activate;
+
+  PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
+}
+
+static void
+psppire_dialog_action_means_init (PsppireDialogActionMeans *act)
+{
+}
diff --git a/src/ui/gui/psppire-dialog-action-means.h b/src/ui/gui/psppire-dialog-action-means.h
new file mode 100644 (file)
index 0000000..80ee7ba
--- /dev/null
@@ -0,0 +1,77 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2012  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_DIALOG_ACTION_MEANS_H__
+#define __PSPPIRE_DIALOG_ACTION_MEANS_H__
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include "psppire-dialog-action.h"
+
+G_BEGIN_DECLS
+
+
+#define PSPPIRE_TYPE_DIALOG_ACTION_MEANS (psppire_dialog_action_means_get_type ())
+
+#define PSPPIRE_DIALOG_ACTION_MEANS(obj)       \
+                     (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                                                 PSPPIRE_TYPE_DIALOG_ACTION_MEANS, PsppireDialogActionMeans))
+
+#define PSPPIRE_DIALOG_ACTION_MEANS_CLASS(klass) \
+                     (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                                PSPPIRE_TYPE_DIALOG_ACTION_MEANS, \
+                                 PsppireDialogActionMeansClass))
+
+
+#define PSPPIRE_IS_DIALOG_ACTION_MEANS(obj) \
+                    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_MEANS))
+
+#define PSPPIRE_IS_DIALOG_ACTION_MEANS_CLASS(klass) \
+                     (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_MEANS))
+
+
+#define PSPPIRE_DIALOG_ACTION_MEANS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                  PSPPIRE_TYPE_DIALOG_ACTION_MEANS, \
+                                  PsppireDialogActionMeansClass))
+
+typedef struct _PsppireDialogActionMeans       PsppireDialogActionMeans;
+typedef struct _PsppireDialogActionMeansClass  PsppireDialogActionMeansClass;
+
+
+struct _PsppireDialogActionMeans
+{
+  PsppireDialogAction parent;
+
+  /*< private >*/
+  GtkWidget *variables;
+
+  GtkWidget *layer;
+};
+
+
+struct _PsppireDialogActionMeansClass
+{
+  PsppireDialogActionClass parent_class;
+};
+
+
+GType psppire_dialog_action_means_get_type (void) ;
+
+G_END_DECLS
+
+#endif /* __PSPPIRE_DIALOG_ACTION_MEANS_H__ */
diff --git a/src/ui/gui/psppire-means-layer.c b/src/ui/gui/psppire-means-layer.c
new file mode 100644 (file)
index 0000000..24178b8
--- /dev/null
@@ -0,0 +1,154 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2012  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 "psppire-means-layer.h"
+#include "psppire-selector.h"
+#include "psppire-var-view.h"
+
+#include <gtk/gtk.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+
+static void psppire_means_layer_class_init    (PsppireMeansLayerClass *class);
+static void psppire_means_layer_init          (PsppireMeansLayer      *window);
+
+G_DEFINE_TYPE (PsppireMeansLayer, psppire_means_layer, GTK_TYPE_VBOX);
+
+
+static void 
+psppire_means_layer_class_init    (PsppireMeansLayerClass *class)
+{
+  //  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+}
+
+static void
+update (PsppireMeansLayer *ml)
+{
+  gchar *l = g_strdup_printf (_("Layer %d of %d"),
+                             ml->current_layer + 1, ml->n_layers);
+  
+  gtk_label_set_text (GTK_LABEL (ml->label), l);
+  g_free (l);
+
+  psppire_var_view_set_current_model (PSPPIRE_VAR_VIEW (ml->var_view),
+                                     ml->current_layer);
+
+  gtk_widget_set_sensitive (ml->back, ml->current_layer > 0);
+  gtk_widget_set_sensitive (ml->forward,
+                           psppire_var_view_get_iter_first (PSPPIRE_VAR_VIEW (ml->var_view), NULL));
+}
+
+static void
+on_forward (PsppireMeansLayer *ml)
+{
+  ml->current_layer++;
+  if (ml->current_layer >= ml->n_layers)
+    {
+      ml->n_layers = ml->current_layer + 1;
+      psppire_var_view_push_model (PSPPIRE_VAR_VIEW (ml->var_view));
+    }
+
+  update (ml);
+}
+
+static void
+on_back (PsppireMeansLayer *ml)
+{
+  g_return_if_fail (ml->current_layer > 0);
+  ml->current_layer--;
+
+  update (ml);
+}
+
+
+static void 
+psppire_means_layer_init  (PsppireMeansLayer      *ml)
+{
+  GtkWidget *hbox_upper = gtk_hbox_new (FALSE, 5);
+  GtkWidget *hbox_lower = gtk_hbox_new (FALSE, 5);
+  GtkWidget *alignment = gtk_alignment_new (0, 0.5, 0, 0);
+  GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
+
+  ml->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
+  ml->back = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
+  ml->var_view = psppire_var_view_new ();
+  ml->selector = psppire_selector_new ();
+  ml->label = gtk_label_new ("");
+
+  g_signal_connect_swapped (ml->forward, "clicked", G_CALLBACK (on_forward),
+                           ml);
+
+  g_signal_connect_swapped (ml->back, "clicked", G_CALLBACK (on_back), ml);
+
+  g_signal_connect_swapped (ml->selector, "selected", G_CALLBACK (update), ml);
+  g_signal_connect_swapped (ml->selector, "de-selected", G_CALLBACK (update),
+                           ml);
+
+  g_object_set (ml->var_view, "headers-visible", FALSE, NULL);
+  g_object_set (sw,
+               "shadow-type", GTK_SHADOW_ETCHED_IN,
+               "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+               NULL);
+
+  g_object_set (ml->selector, "dest-widget", ml->var_view, NULL);
+
+  gtk_box_pack_start (GTK_BOX (hbox_upper), ml->back, FALSE, FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox_upper), ml->label, TRUE, FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox_upper), ml->forward, FALSE, FALSE, 5);
+
+  gtk_box_pack_start (GTK_BOX (hbox_lower), alignment, FALSE, FALSE, 5);
+  gtk_container_add (GTK_CONTAINER (alignment), ml->selector);
+  gtk_box_pack_start (GTK_BOX (hbox_lower), sw, TRUE, TRUE, 5);
+  gtk_container_add (GTK_CONTAINER (sw), ml->var_view);
+
+  gtk_box_pack_start (GTK_BOX (ml), hbox_upper, FALSE, FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (ml), hbox_lower, TRUE, TRUE, 5);
+
+  ml->n_layers = 1;
+  ml->current_layer = 0;
+  update (ml);
+
+  gtk_widget_show_all (hbox_upper);
+  gtk_widget_show_all (hbox_lower);
+}
+
+GtkWidget *
+psppire_means_layer_new (void)
+{
+  return GTK_WIDGET (g_object_new (psppire_means_layer_get_type (), NULL));
+}
+
+
+void
+psppire_means_layer_set_source (PsppireMeansLayer *ml, GtkWidget *w)
+{
+  g_object_set (ml->selector, "source-widget", w, NULL);
+}
+
+
+void
+psppire_means_layer_clear (PsppireMeansLayer *ml)
+{
+  psppire_var_view_clear (PSPPIRE_VAR_VIEW (ml->var_view));
+  ml->n_layers = 1;
+  ml->current_layer = 0;
+  update (ml);
+}
diff --git a/src/ui/gui/psppire-means-layer.h b/src/ui/gui/psppire-means-layer.h
new file mode 100644 (file)
index 0000000..327dc9f
--- /dev/null
@@ -0,0 +1,84 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2012  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/>. */
+
+/*
+  A special purpose widget used in the means dialog.
+*/
+
+#ifndef __PSPPIRE_MEANS_LAYER_H__
+#define __PSPPIRE_MEANS_LAYER_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "psppire-var-view.h"
+
+G_BEGIN_DECLS
+
+
+#define PSPPIRE_TYPE_MEANS_LAYER            (psppire_means_layer_get_type ())
+
+#define PSPPIRE_MEANS_LAYER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+    PSPPIRE_TYPE_MEANS_LAYER, PsppireMeansLayer))
+
+#define PSPPIRE_MEANS_LAYER_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), \
+    PSPPIRE_TYPE_MEANS_LAYER, PsppireMeansLayerClass))
+
+#define PSPPIRE_IS_MEANS_LAYER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+    PSPPIRE_TYPE_MEANS_LAYER))
+
+#define PSPPIRE_IS_MEANS_LAYER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
+    PSPPIRE_TYPE_MEANS_LAYER))
+
+
+typedef struct _PsppireMeansLayer       PsppireMeansLayer;
+typedef struct _PsppireMeansLayerClass  PsppireMeansLayerClass;
+
+
+struct _PsppireMeansLayer
+{
+  GtkVBox parent;
+
+  /* <private> */
+  GtkWidget *var_view;
+  int n_layers;
+  int current_layer;
+  GtkWidget *label;
+  GtkWidget *back;
+  GtkWidget *forward;
+  GtkWidget *selector;
+};
+
+
+struct _PsppireMeansLayerClass
+{
+  GtkVBoxClass parent_class;
+};
+
+GType      psppire_means_layer_get_type        (void);
+GType      psppire_means_layer_model_get_type        (void);
+GtkWidget * psppire_means_layer_new (void);
+
+void       psppire_means_layer_set_source (PsppireMeansLayer *ml, GtkWidget *w);
+
+void       psppire_means_layer_clear (PsppireMeansLayer *ml);
+
+
+G_END_DECLS
+
+#endif /* __PSPPIRE_MEANS_LAYER_H__ */
index 009aad62d03eec6539a22ffaf9a9580452058e2c..5ef5b86dac3d706b6e2864b215d2dc1ef25b2d30 100644 (file)
@@ -100,14 +100,38 @@ psppire_var_view_get_type (void)
   return psppire_var_view_type;
 }
 
+void 
+psppire_var_view_clear (PsppireVarView *vv)
+{
+  gint i;
+  for (i = 0; i < vv->n_lists; ++i)
+    g_object_unref (vv->list[i]);
+
+  g_free (vv->list);
+
+  vv->n_lists = 0;
+  vv->l_idx = -1;
+  vv->list = NULL;
+
+  psppire_var_view_push_model (vv);
+}
+
 
 static void
 psppire_var_view_finalize (GObject *object)
 {
+  gint i;
   PsppireVarView *var_view = PSPPIRE_VAR_VIEW (object);
   g_free (var_view->nums);
+  for (i = 0; i < var_view->n_lists; ++i)
+    g_object_unref (var_view->list[i]);
+
+  g_free (var_view->list);
+  g_free (var_view->cols);
 }
 
+
+
 /* Properties */
 enum
 {
@@ -155,7 +179,7 @@ psppire_var_view_get_property (GObject         *object,
   switch (prop_id)
     {
     case PROP_N_COLS:
-      g_value_set_int (value,  gtk_tree_model_iter_n_children (GTK_TREE_MODEL (var_view->list), NULL));
+      g_value_set_int (value,  var_view->n_cols);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -163,6 +187,64 @@ psppire_var_view_get_property (GObject         *object,
     };
 }
 
+static void
+set_renderers (PsppireVarView *var_view)
+{
+  gint c;
+  var_view->nums = g_malloc (sizeof *var_view->nums * var_view->n_cols);
+  
+  for (c = 0 ; c < var_view->n_cols; ++c)
+    {
+      GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+      GtkTreeViewColumn *col = gtk_tree_view_column_new ();
+      
+      gchar *label = g_strdup_printf (_("Var%d"), c + 1);
+      
+      gtk_tree_view_column_set_min_width (col, 100);
+      gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
+      gtk_tree_view_column_set_resizable (col, TRUE);
+      gtk_tree_view_column_set_title (col, label);
+      
+      g_free (label);
+      
+      var_view->nums[c] = c;
+      
+      gtk_tree_view_column_pack_start (col, renderer, TRUE);
+      gtk_tree_view_column_set_cell_data_func (col, renderer,
+                                              display_cell_var_name,
+                                              &var_view->nums[c], 0);
+      
+      gtk_tree_view_append_column (GTK_TREE_VIEW (var_view), col);
+    }
+}
+
+
+
+
+/* Set a model, which is an GtkListStore of gpointers which point to a variable */
+void
+psppire_var_view_push_model (PsppireVarView *vv)
+{
+  vv->n_lists++;
+  vv->l_idx++;
+  vv->list = xrealloc (vv->list, sizeof (*vv->list) * vv->n_lists);
+  vv->list[vv->l_idx] = gtk_list_store_newv  (vv->n_cols, vv->cols);
+  g_object_ref (vv->list[vv->l_idx]);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (vv), GTK_TREE_MODEL (vv->list[vv->l_idx]));
+}
+
+gboolean
+psppire_var_view_set_current_model (PsppireVarView *vv, gint n)
+{
+  if (n < 0 || n >= vv->n_lists)
+    return FALSE;
+
+  vv->l_idx = n;
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (vv), GTK_TREE_MODEL (vv->list[vv->l_idx]));
+
+  return TRUE;
+}
 
 static void
 psppire_var_view_set_property (GObject         *object,
@@ -176,42 +258,17 @@ psppire_var_view_set_property (GObject         *object,
     {
     case PROP_N_COLS:
       {
-       gint n_cols = g_value_get_int (value);
        gint c;
+       var_view->n_cols = g_value_get_int (value);
 
+       var_view->cols = xrealloc (var_view->cols, sizeof (GType) *  var_view->n_cols);
 
-       GType *array = g_alloca (sizeof (GType) *  n_cols);
-
-       var_view->nums = g_malloc (sizeof *var_view->nums * n_cols);
-
-       for (c = 0 ; c < n_cols; ++c)
-       {
-         GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
-         GtkTreeViewColumn *col = gtk_tree_view_column_new ();
-
-         gchar *label = g_strdup_printf (_("Var%d"), c + 1);
-
-         gtk_tree_view_column_set_min_width (col, 100);
-         gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
-         gtk_tree_view_column_set_resizable (col, TRUE);
-         gtk_tree_view_column_set_title (col, label);
-
-         g_free (label);
-
-         var_view->nums[c] = c;
+       for (c = 0 ; c < var_view->n_cols; ++c)
+         var_view->cols[c] = PSPPIRE_VAR_PTR_TYPE;
 
-         gtk_tree_view_column_pack_start (col, renderer, TRUE);
-         gtk_tree_view_column_set_cell_data_func (col, renderer,
-                                                  display_cell_var_name,
-                                                  &var_view->nums[c], 0);
-
-         gtk_tree_view_append_column (GTK_TREE_VIEW (var_view), col);
-         array[c] = PSPPIRE_VAR_PTR_TYPE;
-       }
+       set_renderers (var_view);
 
-       /* Set a model, which is an GtkListStore of gpointers which point to a variable */
-       var_view->list = gtk_list_store_newv  (n_cols, array);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (var_view), GTK_TREE_MODEL (var_view->list));
+       psppire_var_view_clear (var_view);
       }
       break;
     default:
@@ -246,8 +303,11 @@ psppire_var_view_class_init (PsppireVarViewClass *class)
 static void
 psppire_var_view_base_init (PsppireVarViewClass *class)
 {
+
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
+
+
   object_class->finalize = psppire_var_view_finalize;
 }
 
@@ -262,8 +322,12 @@ psppire_var_view_base_finalize (PsppireVarViewClass *class,
 
 
 static void
-psppire_var_view_init (PsppireVarView *var_view)
+psppire_var_view_init (PsppireVarView *vv)
 {
+  vv->cols = 0;
+  vv->n_lists = 0;
+  vv->l_idx = -1;
+  vv->list = NULL;
 }
 
 
@@ -277,13 +341,20 @@ psppire_var_view_new (void)
 gboolean
 psppire_var_view_get_iter_first (PsppireVarView *vv, GtkTreeIter *iter)
 {
-  return gtk_tree_model_get_iter_first (GTK_TREE_MODEL (vv->list), iter);
+  GtkTreeIter dummy;
+  if ( vv->l_idx < 0)
+    return FALSE;
+
+  return gtk_tree_model_get_iter_first (GTK_TREE_MODEL (vv->list[vv->l_idx]), iter ? iter : &dummy);
 }
 
 gboolean
 psppire_var_view_get_iter_next (PsppireVarView *vv, GtkTreeIter *iter)
 {
-  return gtk_tree_model_iter_next (GTK_TREE_MODEL (vv->list), iter);
+  if ( vv->l_idx < 0)
+    return FALSE;
+
+  return gtk_tree_model_iter_next (GTK_TREE_MODEL (vv->list[vv->l_idx]), iter);
 }
 
 const struct variable *
@@ -291,7 +362,7 @@ psppire_var_view_get_variable (PsppireVarView *vv, gint column, GtkTreeIter *ite
 {
   const struct variable *var = NULL;
   GValue value = {0};
-  gtk_tree_model_get_value (GTK_TREE_MODEL (vv->list), iter, column, &value);
+  gtk_tree_model_get_value (GTK_TREE_MODEL (vv->list[vv->l_idx]), iter, column, &value);
 
   if ( G_VALUE_TYPE (&value) == PSPPIRE_VAR_PTR_TYPE)
     var = g_value_get_boxed (&value);
index 45832eba0e8804a46b7381e48f5079cff9fc1b2c..0029ae22242fd61b288be4e5666ae44670022a5d 100644 (file)
@@ -44,9 +44,14 @@ struct _PsppireVarView
 {
   GtkTreeView parent;
 
-  GtkListStore *list;
+  GtkListStore **list;
   
+  GType *cols;
   gint *nums;
+  gint n_cols;
+
+  gint n_lists;
+  gint l_idx;
 };
 
 struct _PsppireVarViewClass
@@ -65,6 +70,14 @@ gboolean psppire_var_view_get_iter_next (PsppireVarView *vv, GtkTreeIter *iter);
 
 const struct variable * psppire_var_view_get_variable (PsppireVarView *vv, gint column, GtkTreeIter *iter);
 
+void     psppire_var_view_push_model (PsppireVarView *vv);
+
+gboolean psppire_var_view_set_current_model (PsppireVarView *vv, gint n);
+
+void psppire_var_view_clear (PsppireVarView *vv);
+
+GtkWidget* psppire_var_view_new (void);
+
 
 
 G_END_DECLS
index 9f21486f70db0ff376688977b71460827a7dd78a..d131b6469f7c8abad637b2eb13b9d5155e955394 100644 (file)
@@ -16,6 +16,8 @@
 #include "psppire-dialog-action-correlation.h"
 #include "psppire-dialog-action-descriptives.h"
 #include "psppire-dialog-action-kmeans.h"
+#include "psppire-dialog-action-means.h"
+#include "psppire-means-layer.h"
 #include "psppire-dialog-action-reliability.h"
 #include "psppire-dialog-action-roc.h"
 #include "psppire-dialog-action-sort.h"
@@ -41,6 +43,8 @@ preregister_widgets (void)
   psppire_dialog_action_correlation_get_type ();
   psppire_dialog_action_descriptives_get_type ();
   psppire_dialog_action_kmeans_get_type ();
+  psppire_dialog_action_means_get_type ();
+  psppire_means_layer_get_type ();
   psppire_dialog_action_var_info_get_type ();
   psppire_dialog_action_reliability_get_type ();
   psppire_dialog_action_roc_get_type ();