1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2009, 2010, 2012 Free Software Foundation
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.
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.
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/>.
19 This module provides a widget, PsppireSelector derived from
22 It contains a GtkArrow, and is used for selecting objects from a
23 GtkTreeView and putting them into a destination widget (often
24 another GtkTreeView). Typically this is used in psppire for
25 selecting variables, thus:
28 +----------------------------------------------------------+
30 | Source Widget Dest Widget |
31 | +----------------+ +----------------+ |
32 | | Variable0 | | Variable2 | |
47 | +----------------+ +----------------+ |
49 +----------------------------------------------------------+
51 The Source Widget is always a GtkTreeView. The Dest Widget may be a
52 GtkTreeView or a GtkEntry (other destination widgets may be
53 supported in the future).
55 Widgets may be source to more than one PsppireSelector.
61 #include "psppire-dictview.h"
62 #include "psppire-var-view.h"
63 #include "psppire-dict.h"
64 #include "psppire-select-dest.h"
68 #include "psppire-selector.h"
70 static void psppire_selector_class_init (PsppireSelectorClass *class);
71 static void psppire_selector_init (PsppireSelector *selector);
74 static void set_direction (PsppireSelector *, enum psppire_selector_dir);
77 enum {SELECTED, /* Emitted when an item is inserted into dest */
78 DE_SELECTED, /* Emitted when an item is removed from dest */
81 static guint signals [n_SIGNALS];
83 /* Callback for when an item disappears from the source list.
84 By implication, this means that the item has been inserted into the
88 on_row_deleted (PsppireSelector *selector)
90 g_signal_emit (selector, signals [SELECTED], 0);
93 /* Callback for when a new item appears in the source list.
94 By implication, this means that an item has been deleted from the
98 on_row_inserted (PsppireSelector *selector)
100 g_signal_emit (selector, signals [DE_SELECTED], 0);
105 psppire_selector_get_type (void)
107 static GType psppire_selector_type = 0;
109 if (!psppire_selector_type)
111 static const GTypeInfo psppire_selector_info =
113 sizeof (PsppireSelectorClass),
114 (GBaseInitFunc) NULL,
115 (GBaseFinalizeFunc) NULL,
116 (GClassInitFunc)psppire_selector_class_init,
117 (GClassFinalizeFunc) NULL,
119 sizeof (PsppireSelector),
121 (GInstanceInitFunc) psppire_selector_init,
124 psppire_selector_type =
125 g_type_register_static (GTK_TYPE_BUTTON, "PsppireSelector",
126 &psppire_selector_info, 0);
129 return psppire_selector_type;
132 static GObjectClass * parent_class = NULL;
136 #define SELECTOR_DEBUGGING 0
139 dump_hash_entry (gpointer key, gpointer value, gpointer obj)
142 g_print ("Source %p; ", key);
144 for (item = g_list_first (value);
146 item = g_list_next (item))
148 g_print ("%p(%p) ", item->data, item);
153 /* This function is for debugging only */
155 psppire_selector_show_map (PsppireSelector *obj)
157 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
159 g_print ("%s %p\n", __FUNCTION__, obj);
160 g_hash_table_foreach (class->source_hash, dump_hash_entry, obj);
166 psppire_selector_dispose (GObject *obj)
168 PsppireSelector *sel = PSPPIRE_SELECTOR (obj);
169 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
172 if (sel->dispose_has_run)
175 /* Make sure dispose does not run twice. */
176 sel->dispose_has_run = TRUE;
178 /* Remove ourself from the source map. If we are the only entry for this source
179 widget, that will result in an empty list for the source. In that case, we
180 remove the entire entry too. */
181 if ((list = g_hash_table_lookup (class->source_hash, sel->source)))
183 GList *newlist = g_list_remove_link (list, sel->source_litem);
184 g_list_free (sel->source_litem);
186 g_hash_table_remove (class->source_hash, sel->source);
188 g_hash_table_replace (class->source_hash, sel->source, newlist);
190 sel->source_litem = NULL;
193 g_object_unref (sel->dest);
194 g_object_unref (sel->source);
196 /* Chain up to the parent class */
197 G_OBJECT_CLASS (parent_class)->dispose (obj);
212 static void on_click (GtkButton *b);
213 static void on_realize (GtkWidget *selector);
216 static void update_subjects (PsppireSelector *selector);
220 psppire_selector_set_property (GObject *object,
225 PsppireSelector *selector = PSPPIRE_SELECTOR (object);
229 case PROP_ORIENTATION:
230 selector->orientation = g_value_get_enum (value);
231 set_direction (selector, selector->direction);
234 selector->primary_requested = TRUE;
235 update_subjects (selector);
237 case PROP_SOURCE_WIDGET:
238 selector->source = g_value_dup_object (value);
239 update_subjects (selector);
241 case PROP_DEST_WIDGET:
242 selector->dest = g_value_dup_object (value);
243 update_subjects (selector);
246 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
253 psppire_selector_get_property (GObject *object,
258 PsppireSelector *selector = PSPPIRE_SELECTOR (object);
262 case PROP_ORIENTATION:
263 g_value_set_enum (value, selector->orientation);
265 case PROP_SOURCE_WIDGET:
266 g_value_take_object (value, selector->source);
268 case PROP_DEST_WIDGET:
269 g_value_take_object (value, selector->dest);
272 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
278 psppire_selector_class_init (PsppireSelectorClass *class)
280 GObjectClass *object_class = G_OBJECT_CLASS (class);
281 GtkButtonClass *button_class = GTK_BUTTON_CLASS (class);
282 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
283 GParamSpec *orientation_spec =
284 g_param_spec_enum ("orientation",
286 "Where the selector is relative to its subjects",
287 PSPPIRE_TYPE_SELECTOR_ORIENTATION,
288 PSPPIRE_SELECT_SOURCE_BEFORE_DEST /* default value */,
289 G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE);
292 /* Meaningfull only if more than one selector shares this selectors source */
293 GParamSpec *primary_spec =
294 g_param_spec_boolean ("primary",
296 "Whether this selector should be the primary selector for the source",
300 GParamSpec *source_widget_spec =
301 g_param_spec_object ("source-widget",
303 "The widget to be used as the source for this selector",
307 GParamSpec *dest_widget_spec =
308 g_param_spec_object ("dest-widget",
309 "Destination Widget",
310 "The widget to be used as the destination for this selector",
315 button_class->clicked = on_click;
316 widget_class->realize = on_realize;
319 object_class->set_property = psppire_selector_set_property;
320 object_class->get_property = psppire_selector_get_property;
322 g_object_class_install_property (object_class,
326 g_object_class_install_property (object_class,
330 g_object_class_install_property (object_class,
334 g_object_class_install_property (object_class,
338 parent_class = g_type_class_peek_parent (class);
341 g_signal_new ("selected",
342 G_TYPE_FROM_CLASS (class),
346 g_cclosure_marshal_VOID__VOID,
350 signals [DE_SELECTED] =
351 g_signal_new ("de-selected",
352 G_TYPE_FROM_CLASS (class),
356 g_cclosure_marshal_VOID__VOID,
360 object_class->dispose = psppire_selector_dispose;
362 class->source_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
363 class->default_selection_funcs = g_hash_table_new (g_direct_hash, g_direct_equal);
367 /* Callback for when the source treeview is activated (double clicked) */
369 on_row_activate (GtkTreeView *tree_view,
371 GtkTreeViewColumn *column,
374 on_click (GTK_BUTTON (data));
377 /* Callback for when the source selection changes */
379 on_source_select (GtkTreeSelection *treeselection, gpointer data)
381 PsppireSelector *selector = data;
383 set_direction (selector, PSPPIRE_SELECTOR_SOURCE_TO_DEST);
385 if ( selector->allow_selection )
387 gtk_widget_set_sensitive (GTK_WIDGET (selector),
388 selector->allow_selection (selector->source, selector->dest));
390 else if ( GTK_IS_ENTRY (selector->dest) )
392 gtk_widget_set_sensitive (GTK_WIDGET (selector),
393 gtk_tree_selection_count_selected_rows
394 (treeselection) <= 1 );
400 on_realize (GtkWidget *w)
402 PsppireSelector *selector = PSPPIRE_SELECTOR (w);
403 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
404 GtkTreeSelection* selection ;
406 GList *list = g_hash_table_lookup (class->source_hash, selector->source);
408 if (GTK_WIDGET_CLASS (parent_class)->realize)
409 GTK_WIDGET_CLASS (parent_class)->realize (w);
414 if ( g_list_first (list)->data == selector)
416 if ( selector->row_activate_id )
417 g_signal_handler_disconnect (selector->source, selector->row_activate_id);
419 selector->row_activate_id =
420 g_signal_connect (selector->source, "row-activated", G_CALLBACK (on_row_activate), selector);
423 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->source));
425 if ( selector->source_select_id )
426 g_signal_handler_disconnect (selection, selector->source_select_id);
428 selector->source_select_id =
429 g_signal_connect (selection, "changed", G_CALLBACK (on_source_select), selector);
434 psppire_selector_init (PsppireSelector *selector)
436 selector->primary_requested = FALSE;
437 selector->select_user_data = NULL;
438 selector->select_items = NULL;
439 selector->allow_selection = NULL;
440 selector->filter = NULL;
442 selector->arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
445 gtk_container_add (GTK_CONTAINER (selector), selector->arrow);
447 gtk_widget_show (selector->arrow);
449 selector->selecting = FALSE;
451 selector->source = NULL;
452 selector->dest = NULL;
453 selector->dispose_has_run = FALSE;
456 selector->row_activate_id = 0;
457 selector->source_select_id = 0;
459 selector->source_litem = NULL;
464 psppire_selector_new (void)
466 return GTK_WIDGET (g_object_new (psppire_selector_get_type (), NULL));
471 set_direction (PsppireSelector *selector, enum psppire_selector_dir d)
473 selector->direction = d;
475 /* FIXME: Need to reverse the arrow direction if an RTL locale is in
477 if ( d == PSPPIRE_SELECTOR_SOURCE_TO_DEST )
479 switch (selector->orientation)
481 case PSPPIRE_SELECT_SOURCE_BEFORE_DEST:
482 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_RIGHT, NULL);
484 case PSPPIRE_SELECT_SOURCE_AFTER_DEST:
485 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_LEFT, NULL);
487 case PSPPIRE_SELECT_SOURCE_ABOVE_DEST:
488 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_DOWN, NULL);
490 case PSPPIRE_SELECT_SOURCE_BELOW_DEST:
491 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_UP, NULL);
494 g_assert_not_reached ();
500 switch (selector->orientation)
502 case PSPPIRE_SELECT_SOURCE_BEFORE_DEST:
503 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_LEFT, NULL);
505 case PSPPIRE_SELECT_SOURCE_AFTER_DEST:
506 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_RIGHT, NULL);
508 case PSPPIRE_SELECT_SOURCE_ABOVE_DEST:
509 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_UP, NULL);
511 case PSPPIRE_SELECT_SOURCE_BELOW_DEST:
512 g_object_set (selector->arrow, "arrow-type", GTK_ARROW_DOWN, NULL);
515 g_assert_not_reached ();
522 /* Callback for when the destination treeview selection changes */
524 on_dest_treeview_select (GtkTreeSelection *treeselection, gpointer data)
526 PsppireSelector *selector = data;
528 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->source)));
530 set_direction (selector, PSPPIRE_SELECTOR_DEST_TO_SOURCE);
533 /* Callback for source deselection, when the dest is GtkEntry */
535 de_select_selection_entry (PsppireSelector *selector)
537 gtk_entry_set_text (GTK_ENTRY (selector->dest), "");
540 /* Callback for source deselection, when the dest is GtkTreeView */
542 de_select_selection_tree_view (PsppireSelector *selector)
546 GtkTreeSelection* selection =
547 gtk_tree_view_get_selection ( GTK_TREE_VIEW (selector->dest));
549 GtkTreeModel *model =
550 gtk_tree_view_get_model (GTK_TREE_VIEW (selector->dest));
552 GList *selected_rows =
553 gtk_tree_selection_get_selected_rows (selection, NULL);
555 g_return_if_fail (selector->select_items);
557 /* Convert paths to RowRefs */
558 for (item = g_list_first (selected_rows);
560 item = g_list_next (item))
562 GtkTreeRowReference* rowref;
563 GtkTreePath *path = item->data;
565 rowref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path);
567 item->data = rowref ;
568 gtk_tree_path_free (path);
571 /* Remove each selected row from the dest widget */
572 for (item = g_list_first (selected_rows);
574 item = g_list_next (item))
577 GtkTreeRowReference *rr = item->data;
579 GtkTreePath *path = gtk_tree_row_reference_get_path (rr);
581 gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
583 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
585 gtk_tree_path_free (path);
588 /* Delete list of RowRefs and its contents */
589 g_list_foreach (selected_rows, (GFunc) gtk_tree_row_reference_free, NULL);
590 g_list_free (selected_rows);
594 /* Callback which causes the filter to be refiltered.
595 Called when the DEST GtkEntry is activated (Enter is pressed), or when it
599 refilter (PsppireSelector *selector)
601 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source));
602 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
606 /* Removes something from the DEST widget */
608 de_select_selection (PsppireSelector *selector)
610 selector->selecting = TRUE;
612 if ( GTK_IS_TREE_VIEW (selector->dest ) )
613 de_select_selection_tree_view (selector);
615 else if ( GTK_IS_ENTRY (selector->dest))
616 de_select_selection_entry (selector);
619 g_assert_not_reached ();
621 selector->selecting = FALSE;
625 g_signal_emit (selector, signals [DE_SELECTED], 0);
629 /* Puts something into the DEST widget */
631 select_selection (PsppireSelector *selector)
634 GtkTreeSelection* selection =
635 gtk_tree_view_get_selection ( GTK_TREE_VIEW (selector->source));
637 GList *selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
639 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source));
641 GtkTreeModel *childmodel = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
643 g_return_if_fail (selector->select_items);
645 if (selector->allow_selection &&
646 ! selector->allow_selection (selector->source, selector->dest))
649 selector->selecting = TRUE;
651 for (item = g_list_first (selected_rows);
653 item = g_list_next (item))
655 GtkTreeIter child_iter;
657 GtkTreePath *path = item->data;
659 g_return_if_fail (model);
661 gtk_tree_model_get_iter (model, &iter, path);
663 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
665 selector->select_items (child_iter,
668 selector->select_user_data
672 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
673 g_list_free (selected_rows);
677 g_signal_emit (selector, signals [SELECTED], 0);
679 selector->selecting = FALSE;
682 /* Callback for when the selector button is clicked,
683 or other event which causes the selector's action to occur.
686 on_click (GtkButton *b)
688 PsppireSelector *selector = PSPPIRE_SELECTOR (b);
690 switch (selector->direction)
692 case PSPPIRE_SELECTOR_SOURCE_TO_DEST:
693 select_selection (selector);
695 case PSPPIRE_SELECTOR_DEST_TO_SOURCE:
696 de_select_selection (selector);
699 g_assert_not_reached ();
703 if (GTK_BUTTON_CLASS (parent_class)->clicked)
704 GTK_BUTTON_CLASS (parent_class)->clicked (b);
708 is_item_in_dest (GtkTreeModel *model, GtkTreeIter *iter, PsppireSelector *selector)
710 gboolean result = FALSE;
711 GtkTreeIter source_iter;
712 GtkTreeModel *source_model;
715 if (GTK_IS_TREE_MODEL_FILTER (model))
717 source_model = gtk_tree_model_filter_get_model
718 (GTK_TREE_MODEL_FILTER (model));
720 gtk_tree_model_filter_convert_iter_to_child_iter
721 (GTK_TREE_MODEL_FILTER (model), &source_iter, iter);
725 source_model = model;
729 gtk_tree_model_get_value (source_model, &source_iter, DICT_TVM_COL_VAR, &value);
731 result = psppire_select_dest_widget_contains_var (PSPPIRE_SELECT_DEST_WIDGET (selector->dest),
734 g_value_unset (&value);
741 /* Visibility function for items in the SOURCE widget.
742 Returns TRUE iff *all* the selectors for which SOURCE is associated
745 is_source_item_visible (GtkTreeModel *childmodel,
746 GtkTreeIter *iter, gpointer data)
748 PsppireSelector *selector = data;
749 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
753 list = g_hash_table_lookup (class->source_hash, selector->source);
757 PsppireSelector *selector = list->data;
759 if ( selector->filter && selector->filter (childmodel, iter, selector))
769 /* set the source widget to SOURCE */
771 set_tree_view_source (PsppireSelector *selector)
775 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
777 if ( ! (list = g_hash_table_lookup (class->source_hash, selector->source)))
779 /* Base case: This widget is currently not the source of
780 any selector. Create a hash entry and make this selector
781 the first selector in the list */
783 list = g_list_append (list, selector);
784 g_hash_table_insert (class->source_hash, selector->source, list);
786 /* Save the list item so that it can be removed later */
787 selector->source_litem = list;
790 { /* Append this selector to the list and push the <source,list>
791 pair onto the hash table */
793 if ( NULL == g_list_find (list, selector) )
795 if ( selector->primary_requested )
797 list = g_list_prepend (list, selector);
798 selector->source_litem = list;
802 list = g_list_append (list, selector);
803 selector->source_litem = g_list_last (list);
805 g_hash_table_replace (class->source_hash, selector->source, list);
812 /* This function is a callback which occurs when the
813 SOURCE's model has changed */
818 PsppireSelector *selector
821 GtkTreeModel *model = gtk_tree_view_get_model (source);
823 g_assert (source == GTK_TREE_VIEW (selector->source));
825 if (model && (model == g_object_get_data (G_OBJECT (source), "model-copy")))
830 GtkTreeModel *new_model = gtk_tree_model_filter_new (model, NULL);
832 g_object_set_data (G_OBJECT (source), "model-copy", new_model);
834 gtk_tree_view_set_model (source, new_model);
836 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (new_model),
837 is_source_item_visible,
841 g_signal_connect_swapped (new_model,
843 G_CALLBACK (on_row_deleted), selector);
845 g_signal_connect_swapped (new_model,
847 G_CALLBACK (on_row_inserted), selector);
849 g_object_unref (new_model);
856 Callback for when the destination treeview's data changes
859 on_dest_data_change (GtkTreeModel *tree_model,
864 PsppireSelector *selector = user_data;
866 if ( selector->selecting) return;
873 on_dest_data_delete (GtkTreeModel *tree_model,
877 PsppireSelector *selector = user_data;
879 if ( selector->selecting ) return;
886 on_dest_model_changed (PsppireSelector *selector)
888 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->dest));
892 g_signal_connect (model, "row-changed", G_CALLBACK (on_dest_data_change),
895 g_signal_connect (model, "row-deleted", G_CALLBACK (on_dest_data_delete),
900 /* Set the destination widget to DEST */
902 set_tree_view_dest (PsppireSelector *selector,
905 GtkTreeSelection* selection = gtk_tree_view_get_selection (dest);
908 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
910 g_signal_connect (selection, "changed", G_CALLBACK (on_dest_treeview_select),
913 on_dest_model_changed (selector);
914 g_signal_connect_swapped (dest, "notify::model",
915 G_CALLBACK (on_dest_model_changed), selector);
921 /* Callback for when the DEST GtkEntry is selected (clicked) */
923 on_entry_dest_select (GtkWidget *widget, GdkEventFocus *event, gpointer data)
925 PsppireSelector * selector = data;
927 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->source)));
928 set_direction (selector, PSPPIRE_SELECTOR_DEST_TO_SOURCE);
935 /* Set DEST to be the destination GtkEntry widget */
937 set_entry_dest (PsppireSelector *selector,
940 g_signal_connect_swapped (dest, "activate", G_CALLBACK (refilter),
943 g_signal_connect_swapped (dest, "changed", G_CALLBACK (refilter),
946 g_signal_connect (dest, "focus-in-event", G_CALLBACK (on_entry_dest_select),
949 g_signal_connect_swapped (dest, "focus-out-event", G_CALLBACK (refilter),
956 set_default_filter (PsppireSelector *selector)
958 if ( selector->filter == NULL)
960 if (GTK_IS_TREE_VIEW (selector->dest))
961 selector->filter = is_item_in_dest;
967 update_subjects (PsppireSelector *selector)
969 if ( NULL == selector->dest )
972 set_default_filter (selector);
974 if ( NULL == selector->source )
977 if ( GTK_IS_TREE_VIEW (selector->source))
979 set_tree_view_source (selector);
981 g_signal_connect (selector->source, "notify::model",
982 G_CALLBACK (update_model), selector);
984 update_model (GTK_TREE_VIEW (selector->source), 0, selector);
987 g_error ("Unsupported source widget: %s", G_OBJECT_TYPE_NAME (selector->source));
989 if ( NULL == selector->dest)
991 else if ( GTK_IS_TREE_VIEW (selector->dest))
993 set_tree_view_dest (selector, GTK_TREE_VIEW (selector->dest));
996 else if ( GTK_IS_ENTRY (selector->dest))
997 set_entry_dest (selector, GTK_ENTRY (selector->dest));
999 else if (GTK_IS_TEXT_VIEW (selector->dest))
1001 /* Nothing to be done */
1004 g_error ("Unsupported destination widget: %s", G_OBJECT_TYPE_NAME (selector->dest));
1007 /* FIXME: Remove this dependency */
1008 if ( PSPPIRE_IS_DICT_VIEW (selector->source) )
1010 GObjectClass *class = G_OBJECT_GET_CLASS (selector);
1011 GType type = G_OBJECT_TYPE (selector->dest);
1013 SelectItemsFunc *func =
1014 g_hash_table_lookup (PSPPIRE_SELECTOR_CLASS (class)->default_selection_funcs, (gpointer) type);
1017 psppire_selector_set_select_func (PSPPIRE_SELECTOR (selector),
1024 psppire_selector_set_default_selection_func (GType type, SelectItemsFunc *func)
1026 GObjectClass *class = g_type_class_ref (PSPPIRE_SELECTOR_TYPE);
1028 g_hash_table_insert (PSPPIRE_SELECTOR_CLASS (class)->default_selection_funcs, (gpointer) type, func);
1030 g_type_class_unref (class);
1036 /* Set FILTER_FUNC for this selector */
1038 psppire_selector_set_filter_func (PsppireSelector *selector,
1039 FilterItemsFunc *filter_func)
1041 selector->filter = filter_func ;
1045 /* Set SELECT_FUNC for this selector */
1047 psppire_selector_set_select_func (PsppireSelector *selector,
1048 SelectItemsFunc *select_func,
1051 selector->select_user_data = user_data;
1052 selector->select_items = select_func;
1058 psppire_selector_set_allow (PsppireSelector *selector, AllowSelectionFunc *allow)
1060 selector->allow_selection = allow;
1065 psppire_selector_orientation_get_type (void)
1067 static GType etype = 0;
1069 static const GEnumValue values[] = {
1070 { PSPPIRE_SELECT_SOURCE_BEFORE_DEST, "PSPPIRE_SELECT_SOURCE_BEFORE_DEST", "source before destination" },
1071 { PSPPIRE_SELECT_SOURCE_AFTER_DEST, "PSPPIRE_SELECT_SOURCE_AFTER_DEST", "source after destination" },
1072 { PSPPIRE_SELECT_SOURCE_ABOVE_DEST, "PSPPIRE_SELECT_SOURCE_ABOVE_DEST", "source above destination" },
1073 { PSPPIRE_SELECT_SOURCE_BELOW_DEST, "PSPPIRE_SELECT_SOURCE_BELOW_DEST", "source below destination" },
1076 etype = g_enum_register_static (g_intern_static_string ("PsppireSelectorOrientation"), values);