1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2012, 2014  Free Software Foundation
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include <config.h>
18 
19 #include "psppire-means-layer.h"
20 #include "psppire-var-view.h"
21 
22 #include <gtk/gtk.h>
23 
24 #include "gettext.h"
25 #define _(msgid) gettext (msgid)
26 #define N_(msgid) msgid
27 
28 
29 static void psppire_means_layer_class_init    (PsppireMeansLayerClass *class);
30 static void psppire_means_layer_init          (PsppireMeansLayer      *window);
31 
32 G_DEFINE_TYPE (PsppireMeansLayer, psppire_means_layer, GTK_TYPE_BOX);
33 
34 static GObjectClass *parent_class = NULL;
35 
36 static void
psppire_means_layer_dispose(GObject * obj)37 psppire_means_layer_dispose (GObject *obj)
38 {
39   PsppireMeansLayer *w = PSPPIRE_MEANS_LAYER (obj);
40 
41   if (w->dispose_has_run)
42     return;
43 
44   /* Make sure dispose does not run twice. */
45   w->dispose_has_run = TRUE;
46 
47   g_ptr_array_unref (w->layer);
48 
49   /* Chain up to the parent class */
50   G_OBJECT_CLASS (parent_class)->dispose (obj);
51 }
52 
53 
54 static void
psppire_means_layer_class_init(PsppireMeansLayerClass * class)55 psppire_means_layer_class_init    (PsppireMeansLayerClass *class)
56 {
57   GObjectClass *object_class = G_OBJECT_CLASS (class);
58   parent_class = g_type_class_peek_parent (class);
59 
60 
61   object_class->dispose = psppire_means_layer_dispose;
62 }
63 
64 
65 static void
refresh_view(PsppireMeansLayer * ml)66 refresh_view (PsppireMeansLayer *ml)
67 {
68   GtkTreeModel *tm;
69   g_return_if_fail (ml->current_layer >= 0);
70   tm = g_ptr_array_index (ml->layer, ml->current_layer);
71   gtk_tree_view_set_model (GTK_TREE_VIEW (ml->var_view), tm);
72 }
73 
74 
75 static void
add_new_layer(PsppireMeansLayer * ml)76 add_new_layer (PsppireMeansLayer *ml)
77 {
78   /* Add a model and take a reference to it */
79   GtkTreeModel *tm = gtk_tree_view_get_model (GTK_TREE_VIEW (ml->var_view));
80   g_ptr_array_add (ml->layer, tm);
81   g_signal_connect_swapped (tm, "row-inserted", G_CALLBACK (refresh_view), ml);
82 
83   g_object_ref (tm);
84 }
85 
86 
87 void
psppire_means_layer_update(PsppireMeansLayer * ml)88 psppire_means_layer_update (PsppireMeansLayer *ml)
89 {
90   gchar *l;
91 
92   if (!gtk_widget_get_realized (GTK_WIDGET (ml)))
93     return;
94 
95   l = g_strdup_printf (_("Layer %d of %d"),
96 			      ml->current_layer + 1, ml->n_layers);
97 
98   gtk_label_set_text (GTK_LABEL (ml->label), l);
99   g_free (l);
100 
101   gtk_widget_set_sensitive (ml->back, ml->current_layer > 0);
102 
103   {
104     GtkTreeIter dummy;
105     GtkTreeModel *tm = g_ptr_array_index (ml->layer, ml->current_layer);
106 
107     g_return_if_fail (GTK_IS_TREE_MODEL (tm));
108 
109     gtk_widget_set_sensitive (ml->forward,
110 			      gtk_tree_model_get_iter_first (tm, &dummy));
111   }
112 }
113 
114 static void
on_forward(PsppireMeansLayer * ml)115 on_forward (PsppireMeansLayer *ml)
116 {
117   if (ml->current_layer + 1 >= ml->n_layers)
118     {
119       psppire_var_view_clear (PSPPIRE_VAR_VIEW (ml->var_view));
120       add_new_layer (ml);
121       ml->n_layers = ml->current_layer + 2;
122     }
123   else
124     {
125       GtkTreeModel *tm = g_ptr_array_index (ml->layer, ml->current_layer + 1);
126       gtk_tree_view_set_model (GTK_TREE_VIEW (ml->var_view), tm);
127     }
128   ml->current_layer++;
129   psppire_means_layer_update (ml);
130 }
131 
132 static void
on_back(PsppireMeansLayer * ml)133 on_back (PsppireMeansLayer *ml)
134 {
135   GtkTreeModel *tm;
136   g_return_if_fail (ml->current_layer > 0);
137   ml->current_layer--;
138 
139   tm = g_ptr_array_index (ml->layer, ml->current_layer);
140   gtk_tree_view_set_model (GTK_TREE_VIEW (ml->var_view), tm);
141 
142   psppire_means_layer_update (ml);
143 }
144 
145 void
psppire_means_layer_clear(PsppireMeansLayer * ml)146 psppire_means_layer_clear (PsppireMeansLayer *ml)
147 {
148   psppire_var_view_clear (PSPPIRE_VAR_VIEW (ml->var_view));
149 
150   ml->n_layers = 1;
151   ml->current_layer = 0;
152   ml->layer = g_ptr_array_new_full (3, g_object_unref);
153 
154   add_new_layer (ml);
155 
156   psppire_means_layer_update (ml);
157 }
158 
159 static void
psppire_means_layer_init(PsppireMeansLayer * ml)160 psppire_means_layer_init  (PsppireMeansLayer      *ml)
161 {
162   GtkWidget *hbox_upper = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
163   GtkWidget *hbox_lower = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
164   GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
165 
166   gtk_orientable_set_orientation (GTK_ORIENTABLE (ml), GTK_ORIENTATION_VERTICAL);
167 
168   ml->dispose_has_run = FALSE;
169   ml->forward = gtk_button_new_with_label (_("Forward"));
170   ml->back = gtk_button_new_with_label (_("Back"));
171   ml->var_view = psppire_var_view_new ();
172   ml->label = gtk_label_new ("");
173 
174   g_signal_connect_swapped (ml->forward, "clicked", G_CALLBACK (on_forward),
175 			    ml);
176 
177   g_signal_connect_swapped (ml->back, "clicked", G_CALLBACK (on_back), ml);
178 
179 
180   g_object_set (ml->var_view, "headers-visible", FALSE, NULL);
181   g_object_set (sw,
182 		"shadow-type", GTK_SHADOW_ETCHED_IN,
183 		"hscrollbar-policy", GTK_POLICY_AUTOMATIC,
184 		NULL);
185 
186   g_signal_connect_swapped (ml->var_view, "notify::model", G_CALLBACK (psppire_means_layer_update), ml);
187 
188   gtk_box_pack_start (GTK_BOX (hbox_upper), ml->back, FALSE, FALSE, 5);
189   gtk_box_pack_start (GTK_BOX (hbox_upper), ml->label, TRUE, FALSE, 5);
190   gtk_box_pack_start (GTK_BOX (hbox_upper), ml->forward, FALSE, FALSE, 5);
191 
192   gtk_box_pack_start (GTK_BOX (hbox_lower), sw, TRUE, TRUE, 5);
193   gtk_container_add (GTK_CONTAINER (sw), ml->var_view);
194 
195   gtk_box_pack_start (GTK_BOX (ml), hbox_upper, FALSE, FALSE, 5);
196   gtk_box_pack_start (GTK_BOX (ml), hbox_lower, TRUE, TRUE, 5);
197 
198   psppire_means_layer_clear (ml);
199 
200   gtk_widget_show_all (hbox_upper);
201   gtk_widget_show_all (hbox_lower);
202 }
203 
204 GtkWidget *
psppire_means_layer_new(void)205 psppire_means_layer_new (void)
206 {
207   return GTK_WIDGET (g_object_new (psppire_means_layer_get_type (), NULL));
208 }
209 
210 
211 
212 
213 GtkTreeModel *
psppire_means_layer_get_model_n(PsppireMeansLayer * ml,gint n)214 psppire_means_layer_get_model_n (PsppireMeansLayer *ml, gint n)
215 {
216   return g_ptr_array_index (ml->layer, n);
217 }
218 
219 
220 GtkTreeModel *
psppire_means_layer_get_model(PsppireMeansLayer * ml)221 psppire_means_layer_get_model (PsppireMeansLayer *ml)
222 {
223   return g_ptr_array_index (ml->layer, ml->current_layer);
224 }
225 
226