1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtklistitem.h"
22 #include "gtksignal.h"
32 #define SCROLL_TIME 100
34 static void gtk_list_class_init (GtkListClass *klass);
35 static void gtk_list_init (GtkList *list);
36 static void gtk_list_shutdown (GtkObject *object);
37 static void gtk_list_destroy (GtkObject *object);
38 static void gtk_list_map (GtkWidget *widget);
39 static void gtk_list_unmap (GtkWidget *widget);
40 static void gtk_list_realize (GtkWidget *widget);
41 static void gtk_list_draw (GtkWidget *widget,
43 static gint gtk_list_expose (GtkWidget *widget,
44 GdkEventExpose *event);
45 static gint gtk_list_motion_notify (GtkWidget *widget,
46 GdkEventMotion *event);
47 static gint gtk_list_button_press (GtkWidget *widget,
48 GdkEventButton *event);
49 static gint gtk_list_button_release (GtkWidget *widget,
50 GdkEventButton *event);
51 static void gtk_list_size_request (GtkWidget *widget,
52 GtkRequisition *requisition);
53 static void gtk_list_size_allocate (GtkWidget *widget,
54 GtkAllocation *allocation);
55 static void gtk_list_add (GtkContainer *container,
57 static void gtk_list_remove (GtkContainer *container,
59 static void gtk_list_foreach (GtkContainer *container,
61 gpointer callback_data);
63 static void gtk_real_list_select_child (GtkList *list,
65 static void gtk_real_list_unselect_child (GtkList *list,
69 static void gtk_list_set_anchor (GtkList *list,
72 GtkWidget *undo_focus_child);
73 static void gtk_list_fake_unselect_all (GtkList *list,
75 static void gtk_list_fake_toggle_row (GtkList *list,
77 static void gtk_list_move_focus_child (GtkList *list,
78 GtkScrollType scroll_type,
80 static void gtk_list_update_extended_selection (GtkList *list,
82 static void gtk_list_focus_lost (GtkWidget *item,
85 static void gtk_list_set_focus_child (GtkContainer *container,
87 static gint gtk_list_focus (GtkContainer *container,
88 GtkDirectionType direction);
91 static GtkType gtk_list_child_type (GtkContainer *container);
94 static GtkContainerClass *parent_class = NULL;
95 static guint list_signals[LAST_SIGNAL] = { 0 };
97 static const gchar *vadjustment_key = "gtk-vadjustment";
98 static guint vadjustment_key_id = 0;
99 static const gchar *hadjustment_key = "gtk-hadjustment";
100 static guint hadjustment_key_id = 0;
103 gtk_list_get_type (void)
105 static guint list_type = 0;
109 GtkTypeInfo list_info =
113 sizeof (GtkListClass),
114 (GtkClassInitFunc) gtk_list_class_init,
115 (GtkObjectInitFunc) gtk_list_init,
116 /* reserved_1 */ NULL,
117 /* reserved_2 */ NULL,
118 (GtkClassInitFunc) NULL,
121 list_type = gtk_type_unique (gtk_container_get_type (), &list_info);
128 gtk_list_class_init (GtkListClass *class)
130 GtkObjectClass *object_class;
131 GtkWidgetClass *widget_class;
132 GtkContainerClass *container_class;
134 object_class = (GtkObjectClass*) class;
135 widget_class = (GtkWidgetClass*) class;
136 container_class = (GtkContainerClass*) class;
138 parent_class = gtk_type_class (gtk_container_get_type ());
140 vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
141 hadjustment_key_id = g_quark_from_static_string (hadjustment_key);
143 list_signals[SELECTION_CHANGED] =
144 gtk_signal_new ("selection_changed",
147 GTK_SIGNAL_OFFSET (GtkListClass, selection_changed),
148 gtk_marshal_NONE__NONE,
150 list_signals[SELECT_CHILD] =
151 gtk_signal_new ("select_child",
154 GTK_SIGNAL_OFFSET (GtkListClass, select_child),
155 gtk_marshal_NONE__POINTER,
158 list_signals[UNSELECT_CHILD] =
159 gtk_signal_new ("unselect_child",
162 GTK_SIGNAL_OFFSET (GtkListClass, unselect_child),
163 gtk_marshal_NONE__POINTER,
167 gtk_object_class_add_signals (object_class, list_signals, LAST_SIGNAL);
169 object_class->shutdown = gtk_list_shutdown;
170 object_class->destroy = gtk_list_destroy;
172 widget_class->map = gtk_list_map;
173 widget_class->unmap = gtk_list_unmap;
174 widget_class->realize = gtk_list_realize;
175 widget_class->draw = gtk_list_draw;
176 widget_class->expose_event = gtk_list_expose;
177 widget_class->button_press_event = gtk_list_button_press;
178 widget_class->button_release_event = gtk_list_button_release;
179 widget_class->motion_notify_event = gtk_list_motion_notify;
180 widget_class->size_request = gtk_list_size_request;
181 widget_class->size_allocate = gtk_list_size_allocate;
183 container_class->add = gtk_list_add;
184 container_class->remove = gtk_list_remove;
185 container_class->foreach = gtk_list_foreach;
186 container_class->child_type = gtk_list_child_type;
187 container_class->set_focus_child = gtk_list_set_focus_child;
188 container_class->focus = gtk_list_focus;
190 class->selection_changed = NULL;
191 class->select_child = gtk_real_list_select_child;
192 class->unselect_child = gtk_real_list_unselect_child;
196 gtk_list_child_type (GtkContainer *container)
198 return GTK_TYPE_LIST_ITEM;
202 gtk_list_init (GtkList *list)
204 list->children = NULL;
205 list->selection = NULL;
207 list->undo_selection = NULL;
208 list->undo_unselection = NULL;
210 list->last_focus_child = NULL;
211 list->undo_focus_child = NULL;
218 list->anchor_state = GTK_STATE_SELECTED;
220 list->selection_mode = GTK_SELECTION_SINGLE;
221 list->drag_selection = FALSE;
222 list->add_mode = FALSE;
228 return GTK_WIDGET (gtk_type_new (gtk_list_get_type ()));
232 gtk_list_shutdown (GtkObject *object)
234 gtk_list_clear_items (GTK_LIST (object), 0, -1);
236 GTK_OBJECT_CLASS (parent_class)->shutdown (object);
240 gtk_list_destroy (GtkObject *object)
244 GtkList *list = GTK_LIST (object);
246 for (node = list->children; node; node = node->next)
250 child = (GtkWidget *)node->data;
251 gtk_widget_ref (child);
252 gtk_widget_unparent (child);
253 gtk_widget_destroy (child);
254 gtk_widget_unref (child);
256 g_list_free (list->children);
257 list->children = NULL;
259 for (node = list->selection; node; node = node->next)
263 child = (GtkWidget *)node->data;
264 gtk_widget_unref (child);
266 g_list_free (list->selection);
267 list->selection = NULL;
269 if (GTK_OBJECT_CLASS (parent_class)->destroy)
270 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
274 gtk_list_end_drag_selection (GtkList *list)
276 g_return_if_fail (list != NULL);
277 g_return_if_fail (GTK_IS_LIST (list));
279 list->drag_selection = FALSE;
280 if (GTK_WIDGET_HAS_GRAB (list))
282 gtk_grab_remove (GTK_WIDGET (list));
283 gdk_pointer_ungrab (GDK_CURRENT_TIME);
287 gtk_timeout_remove (list->htimer);
292 gtk_timeout_remove (list->vtimer);
298 gtk_list_insert_items (GtkList *list,
307 g_return_if_fail (list != NULL);
308 g_return_if_fail (GTK_IS_LIST (list));
313 gtk_list_end_drag_selection (list);
314 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
315 gtk_list_end_selection (list);
320 widget = tmp_list->data;
321 tmp_list = tmp_list->next;
323 gtk_widget_set_parent (widget, GTK_WIDGET (list));
324 gtk_signal_connect (GTK_OBJECT (widget), "focus_out_event",
325 GTK_SIGNAL_FUNC (gtk_list_focus_lost), list);
327 if (GTK_WIDGET_VISIBLE (widget->parent))
329 if (GTK_WIDGET_REALIZED (widget->parent) &&
330 !GTK_WIDGET_REALIZED (widget))
331 gtk_widget_realize (widget);
333 if (GTK_WIDGET_MAPPED (widget->parent) &&
334 !GTK_WIDGET_MAPPED (widget))
335 gtk_widget_map (widget);
339 nchildren = g_list_length (list->children);
340 if ((position < 0) || (position > nchildren))
341 position = nchildren;
343 if (position == nchildren)
347 tmp_list = g_list_last (list->children);
348 tmp_list->next = items;
349 items->prev = tmp_list;
353 list->children = items;
358 tmp_list = g_list_nth (list->children, position);
359 last = g_list_last (items);
362 tmp_list->prev->next = items;
363 last->next = tmp_list;
364 items->prev = tmp_list->prev;
365 tmp_list->prev = last;
367 if (tmp_list == list->children)
368 list->children = items;
371 if (list->children && !list->selection &&
372 (list->selection_mode == GTK_SELECTION_BROWSE))
374 widget = list->children->data;
375 gtk_list_select_child (list, widget);
378 if (GTK_WIDGET_VISIBLE (list))
379 gtk_widget_queue_resize (GTK_WIDGET (list));
383 gtk_list_append_items (GtkList *list,
386 g_return_if_fail (list != NULL);
387 g_return_if_fail (GTK_IS_LIST (list));
389 gtk_list_insert_items (list, items, -1);
393 gtk_list_prepend_items (GtkList *list,
396 g_return_if_fail (list != NULL);
397 g_return_if_fail (GTK_IS_LIST (list));
399 gtk_list_insert_items (list, items, 0);
403 gtk_list_remove_items_internal (GtkList *list,
408 GtkWidget *new_focus_child;
409 GtkWidget *old_focus_child;
410 GtkContainer *container;
411 GList *selected_widgets;
414 gboolean grab_focus = FALSE;
416 g_return_if_fail (list != NULL);
417 g_return_if_fail (GTK_IS_LIST (list));
422 container = GTK_CONTAINER (list);
424 gtk_list_end_drag_selection (list);
425 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
426 gtk_list_end_selection (list);
430 selected_widgets = NULL;
432 old_focus_child = new_focus_child = container->focus_child;
436 widget = tmp_list->data;
438 tmp_list = tmp_list->next;
441 gtk_widget_ref (widget);
443 gtk_signal_disconnect_by_func
444 (GTK_OBJECT (widget), GTK_SIGNAL_FUNC (gtk_list_focus_lost), list);
447 if (widget == new_focus_child)
449 work = g_list_find (list->children, widget);
454 new_focus_child = work->next->data;
455 else if (list->children != work && work->prev)
456 new_focus_child = work->prev->data;
458 new_focus_child = NULL;
460 if (GTK_WIDGET_HAS_FOCUS (widget))
465 list->children = g_list_remove (list->children, widget);
467 if (widget->state == GTK_STATE_SELECTED)
468 selected_widgets = g_list_prepend (selected_widgets, widget);
470 gtk_widget_unparent (widget);
473 if (selected_widgets)
475 tmp_list = selected_widgets;
478 widget = tmp_list->data;
479 tmp_list = tmp_list->next;
481 gtk_list_unselect_child (list, widget);
483 gtk_widget_unparent (widget);
486 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
489 g_list_free (selected_widgets);
491 if (new_focus_child && new_focus_child != old_focus_child)
494 gtk_widget_grab_focus (new_focus_child);
496 gtk_container_set_focus_child (container, new_focus_child);
499 if (GTK_WIDGET_VISIBLE (list))
500 gtk_widget_queue_resize (GTK_WIDGET (list));
504 gtk_list_remove_items (GtkList *list,
507 gtk_list_remove_items_internal (list, items, FALSE);
511 gtk_list_remove_items_no_unref (GtkList *list,
514 gtk_list_remove_items_internal (list, items, TRUE);
518 gtk_list_clear_items (GtkList *list,
528 g_return_if_fail (list != NULL);
529 g_return_if_fail (GTK_IS_LIST (list));
531 nchildren = g_list_length (list->children);
535 gboolean selection_changed;
537 if ((end < 0) || (end > nchildren))
543 start_list = g_list_nth (list->children, start);
544 end_list = g_list_nth (list->children, end);
546 gtk_list_end_drag_selection (list);
547 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
548 gtk_list_end_selection (list);
550 if (start_list->prev)
551 start_list->prev->next = end_list;
552 if (end_list && end_list->prev)
553 end_list->prev->next = NULL;
555 end_list->prev = start_list->prev;
556 if (start_list == list->children)
557 list->children = end_list;
559 selection_changed = FALSE;
561 tmp_list = start_list;
565 widget = tmp_list->data;
566 tmp_list = tmp_list->next;
568 if (widget->state == GTK_STATE_SELECTED)
570 gtk_list_unselect_child (list, widget);
571 selection_changed = TRUE;
574 gtk_widget_unparent (widget);
577 g_list_free (start_list);
579 if (list->children && !list->selection &&
580 (list->selection_mode == GTK_SELECTION_BROWSE))
582 widget = list->children->data;
583 gtk_list_select_child (list, widget);
585 else if (selection_changed)
586 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
588 gtk_widget_queue_resize (GTK_WIDGET (list));
593 gtk_list_select_item (GtkList *list,
598 g_return_if_fail (list != NULL);
599 g_return_if_fail (GTK_IS_LIST (list));
601 tmp_list = g_list_nth (list->children, item);
603 gtk_list_select_child (list, GTK_WIDGET (tmp_list->data));
607 gtk_list_unselect_item (GtkList *list,
612 g_return_if_fail (list != NULL);
613 g_return_if_fail (GTK_IS_LIST (list));
615 tmp_list = g_list_nth (list->children, item);
617 gtk_list_unselect_child (list, GTK_WIDGET (tmp_list->data));
621 gtk_list_select_child (GtkList *list,
624 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECT_CHILD], child);
628 gtk_list_unselect_child (GtkList *list,
631 gtk_signal_emit (GTK_OBJECT (list), list_signals[UNSELECT_CHILD], child);
635 gtk_list_child_position (GtkList *list,
641 g_return_val_if_fail (list != NULL, -1);
642 g_return_val_if_fail (GTK_IS_LIST (list), -1);
643 g_return_val_if_fail (child != NULL, -1);
646 children = list->children;
650 if (child == GTK_WIDGET (children->data))
654 children = children->next;
661 gtk_list_set_selection_mode (GtkList *list,
662 GtkSelectionMode mode)
664 g_return_if_fail (list != NULL);
665 g_return_if_fail (GTK_IS_LIST (list));
667 if (list->selection_mode == mode)
670 list->selection_mode = mode;
674 case GTK_SELECTION_SINGLE:
675 case GTK_SELECTION_BROWSE:
676 gtk_list_unselect_all (list);
686 gtk_list_map (GtkWidget *widget)
692 g_return_if_fail (widget != NULL);
693 g_return_if_fail (GTK_IS_LIST (widget));
695 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
696 list = GTK_LIST (widget);
698 gdk_window_show (widget->window);
700 children = list->children;
703 child = children->data;
704 children = children->next;
706 if (GTK_WIDGET_VISIBLE (child) &&
707 !GTK_WIDGET_MAPPED (child))
708 gtk_widget_map (child);
713 gtk_list_unmap (GtkWidget *widget)
715 g_return_if_fail (widget != NULL);
716 g_return_if_fail (GTK_IS_LIST (widget));
718 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
719 gdk_window_hide (widget->window);
723 gtk_list_realize (GtkWidget *widget)
725 GdkWindowAttr attributes;
726 gint attributes_mask;
728 g_return_if_fail (widget != NULL);
729 g_return_if_fail (GTK_IS_LIST (widget));
731 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
733 attributes.window_type = GDK_WINDOW_CHILD;
734 attributes.x = widget->allocation.x;
735 attributes.y = widget->allocation.y;
736 attributes.width = widget->allocation.width;
737 attributes.height = widget->allocation.height;
738 attributes.wclass = GDK_INPUT_OUTPUT;
739 attributes.visual = gtk_widget_get_visual (widget);
740 attributes.colormap = gtk_widget_get_colormap (widget);
741 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
743 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
745 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
746 gdk_window_set_user_data (widget->window, widget);
748 widget->style = gtk_style_attach (widget->style, widget->window);
749 gdk_window_set_background (widget->window,
750 &widget->style->base[GTK_STATE_NORMAL]);
754 gtk_list_draw (GtkWidget *widget,
759 GdkRectangle child_area;
762 g_return_if_fail (widget != NULL);
763 g_return_if_fail (GTK_IS_LIST (widget));
764 g_return_if_fail (area != NULL);
766 if (GTK_WIDGET_DRAWABLE (widget))
768 list = GTK_LIST (widget);
770 children = list->children;
773 child = children->data;
774 children = children->next;
776 if (gtk_widget_intersect (child, area, &child_area))
777 gtk_widget_draw (child, &child_area);
783 gtk_list_expose (GtkWidget *widget,
784 GdkEventExpose *event)
788 GdkEventExpose child_event;
791 g_return_val_if_fail (widget != NULL, FALSE);
792 g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
793 g_return_val_if_fail (event != NULL, FALSE);
795 if (GTK_WIDGET_DRAWABLE (widget))
797 list = GTK_LIST (widget);
799 child_event = *event;
801 children = list->children;
804 child = children->data;
805 children = children->next;
807 if (GTK_WIDGET_NO_WINDOW (child) &&
808 gtk_widget_intersect (child, &event->area, &child_event.area))
809 gtk_widget_event (child, (GdkEvent*) &child_event);
817 move_horizontal (GtkList *list,
825 upper = adj->upper - adj->page_size;
826 adj->value = MIN (adj->value, upper);
827 adj->value = MAX (adj->value, 0.0);
829 gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
833 horizontal_timeout (GtkWidget *list)
836 GdkEventMotion event;
837 GdkModifierType mask;
839 g_return_val_if_fail (GTK_IS_LIST (list), FALSE);
841 GTK_LIST (list)->htimer = 0;
842 gdk_window_get_pointer (list->window, &x, &y, &mask);
849 gtk_list_motion_notify (list, &event);
855 vertical_timeout (GtkWidget *list)
859 GdkEventMotion event;
860 GdkModifierType mask;
862 g_return_val_if_fail (GTK_IS_LIST (list), FALSE);
864 GTK_LIST (list)->vtimer = 0;
865 gdk_window_get_pointer (list->window, &x, &y, &mask);
872 gtk_list_motion_notify (list, &event);
878 gtk_list_motion_notify (GtkWidget *widget,
879 GdkEventMotion *event)
882 GtkWidget *item = NULL;
884 GtkContainer *container;
892 g_return_val_if_fail (widget != NULL, FALSE);
893 g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
894 g_return_val_if_fail (event != NULL, FALSE);
896 list = GTK_LIST (widget);
898 if (!list->drag_selection || !list->children)
901 container = GTK_CONTAINER (widget);
903 if (event->is_hint || event->window != widget->window)
904 gdk_window_get_pointer (widget->window, &x, &y, NULL);
906 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id);
908 /* horizontal autoscrolling */
909 if (adj && widget->allocation.width > adj->page_size &&
910 (x < adj->value || x >= adj->value + adj->page_size))
912 if (list->htimer == 0)
914 list->htimer = gtk_timeout_add
915 (SCROLL_TIME, (GtkFunction) horizontal_timeout, widget);
917 if (!((x < adj->value && adj->value <= 0) ||
918 (x > adj->value + adj->page_size &&
919 adj->value >= adj->upper - adj->page_size)))
922 move_horizontal (list, adj, - 1 + (x - adj->value) / 2 );
924 move_horizontal (list, adj,
925 1 + (x - adj->value - adj->page_size) / 2);
933 /* vertical autoscrolling */
934 for (work = list->children; work; length++, work = work->next)
938 item = GTK_WIDGET (work->data);
939 if (item->allocation.y > y ||
940 (item->allocation.y <= y &&
941 item->allocation.y + item->allocation.height > y))
945 if (work->data == container->focus_child)
952 if (list->vtimer != 0)
955 if (!((y < 0 && focus_row == 0) ||
956 (y > widget->allocation.height && focus_row >= length - 1)))
957 list->vtimer = gtk_timeout_add (SCROLL_TIME,
958 (GtkFunction) vertical_timeout, list);
960 if (row != focus_row)
961 gtk_widget_grab_focus (item);
963 switch (list->selection_mode)
965 case GTK_SELECTION_BROWSE:
966 gtk_list_select_child (list, item);
969 case GTK_SELECTION_EXTENDED:
970 gtk_list_update_extended_selection (list, row);
981 gtk_list_button_press (GtkWidget *widget,
982 GdkEventButton *event)
987 g_return_val_if_fail (widget != NULL, FALSE);
988 g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
989 g_return_val_if_fail (event != NULL, FALSE);
991 if (event->button != 1)
994 list = GTK_LIST (widget);
995 item = gtk_get_event_widget ((GdkEvent*) event);
997 while (item && !GTK_IS_LIST_ITEM (item))
1000 if (item && (item->parent == widget))
1002 gint last_focus_row;
1005 if (event->type == GDK_BUTTON_PRESS)
1007 list->drag_selection = TRUE;
1008 gdk_pointer_grab (widget->window, TRUE,
1009 GDK_POINTER_MOTION_HINT_MASK |
1010 GDK_BUTTON1_MOTION_MASK |
1011 GDK_BUTTON_RELEASE_MASK,
1012 NULL, NULL, event->time);
1013 gtk_grab_add (widget);
1015 else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
1016 gtk_list_end_drag_selection (list);
1018 if (!GTK_WIDGET_HAS_FOCUS(item))
1019 gtk_widget_grab_focus (item);
1023 list->add_mode = FALSE;
1024 gtk_widget_queue_draw (item);
1027 switch (list->selection_mode)
1029 case GTK_SELECTION_SINGLE:
1030 case GTK_SELECTION_MULTIPLE:
1031 if (event->type != GDK_BUTTON_PRESS)
1032 gtk_list_select_child (list, item);
1034 list->undo_focus_child = item;
1037 case GTK_SELECTION_BROWSE:
1040 case GTK_SELECTION_EXTENDED:
1041 focus_row = g_list_index (list->children, item);
1043 if (list->last_focus_child)
1044 last_focus_row = g_list_index (list->children,
1045 list->last_focus_child);
1048 last_focus_row = focus_row;
1049 list->last_focus_child = item;
1052 if (event->type != GDK_BUTTON_PRESS)
1054 if (list->anchor >= 0)
1056 gtk_list_update_extended_selection (list, focus_row);
1057 gtk_list_end_selection (list);
1059 gtk_list_select_child (list, item);
1063 if (event->state & GDK_CONTROL_MASK)
1065 if (event->state & GDK_SHIFT_MASK)
1067 if (list->anchor < 0)
1069 g_list_free (list->undo_selection);
1070 g_list_free (list->undo_unselection);
1071 list->undo_selection = NULL;
1072 list->undo_unselection = NULL;
1074 list->anchor = last_focus_row;
1075 list->drag_pos = last_focus_row;
1076 list->undo_focus_child = list->last_focus_child;
1078 gtk_list_update_extended_selection (list, focus_row);
1082 if (list->anchor < 0)
1083 gtk_list_set_anchor (list, TRUE,
1084 focus_row, list->last_focus_child);
1086 gtk_list_update_extended_selection (list, focus_row);
1091 if (event->state & GDK_SHIFT_MASK)
1093 gtk_list_set_anchor (list, FALSE,
1094 last_focus_row, list->last_focus_child);
1095 gtk_list_update_extended_selection (list, focus_row);
1099 if (list->anchor < 0)
1100 gtk_list_set_anchor (list, FALSE, focus_row,
1101 list->last_focus_child);
1103 gtk_list_update_extended_selection (list, focus_row);
1115 gtk_list_button_release (GtkWidget *widget,
1116 GdkEventButton *event)
1121 g_return_val_if_fail (widget != NULL, FALSE);
1122 g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
1123 g_return_val_if_fail (event != NULL, FALSE);
1125 list = GTK_LIST (widget);
1127 /* we don't handle button 2 and 3 */
1128 if (event->button != 1)
1131 if (list->drag_selection)
1133 gtk_list_end_drag_selection (list);
1135 switch (list->selection_mode)
1137 case GTK_SELECTION_EXTENDED:
1138 if (!(event->state & GDK_SHIFT_MASK))
1139 gtk_list_end_selection (list);
1142 case GTK_SELECTION_SINGLE:
1143 case GTK_SELECTION_MULTIPLE:
1145 item = gtk_get_event_widget ((GdkEvent*) event);
1147 while (item && !GTK_IS_LIST_ITEM (item))
1148 item = item->parent;
1150 if (item && item->parent == widget)
1152 if (list->undo_focus_child == item)
1153 gtk_list_toggle_row (list, item);
1155 list->undo_focus_child = NULL;
1167 gtk_list_size_request (GtkWidget *widget,
1168 GtkRequisition *requisition)
1174 g_return_if_fail (widget != NULL);
1175 g_return_if_fail (GTK_IS_LIST (widget));
1176 g_return_if_fail (requisition != NULL);
1178 list = GTK_LIST (widget);
1179 requisition->width = 0;
1180 requisition->height = 0;
1182 children = list->children;
1185 child = children->data;
1186 children = children->next;
1188 if (GTK_WIDGET_VISIBLE (child))
1190 gtk_widget_size_request (child, &child->requisition);
1192 requisition->width = MAX (requisition->width, child->requisition.width);
1193 requisition->height += child->requisition.height;
1197 requisition->width += GTK_CONTAINER (list)->border_width * 2;
1198 requisition->height += GTK_CONTAINER (list)->border_width * 2;
1200 requisition->width = MAX (requisition->width, 1);
1201 requisition->height = MAX (requisition->height, 1);
1205 gtk_list_size_allocate (GtkWidget *widget,
1206 GtkAllocation *allocation)
1210 GtkAllocation child_allocation;
1213 g_return_if_fail (widget != NULL);
1214 g_return_if_fail (GTK_IS_LIST (widget));
1215 g_return_if_fail (allocation != NULL);
1217 list = GTK_LIST (widget);
1219 widget->allocation = *allocation;
1220 if (GTK_WIDGET_REALIZED (widget))
1221 gdk_window_move_resize (widget->window,
1222 allocation->x, allocation->y,
1223 allocation->width, allocation->height);
1227 child_allocation.x = GTK_CONTAINER (list)->border_width;
1228 child_allocation.y = GTK_CONTAINER (list)->border_width;
1229 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1231 children = list->children;
1235 child = children->data;
1236 children = children->next;
1238 if (GTK_WIDGET_VISIBLE (child))
1240 child_allocation.height = child->requisition.height;
1242 gtk_widget_size_allocate (child, &child_allocation);
1244 child_allocation.y += child_allocation.height;
1251 gtk_list_add (GtkContainer *container,
1256 g_return_if_fail (container != NULL);
1257 g_return_if_fail (GTK_IS_LIST (container));
1258 g_return_if_fail (widget != NULL);
1259 g_return_if_fail (GTK_IS_LIST_ITEM (widget));
1261 item_list = g_list_alloc ();
1262 item_list->data = widget;
1264 gtk_list_append_items (GTK_LIST (container), item_list);
1268 gtk_list_remove (GtkContainer *container,
1273 g_return_if_fail (container != NULL);
1274 g_return_if_fail (GTK_IS_LIST (container));
1275 g_return_if_fail (widget != NULL);
1276 g_return_if_fail (container == GTK_CONTAINER (widget->parent));
1279 item_list = g_list_alloc ();
1280 item_list->data = widget;
1282 gtk_list_remove_items (GTK_LIST (container), item_list);
1284 g_list_free (item_list);
1288 gtk_list_foreach (GtkContainer *container,
1289 GtkCallback callback,
1290 gpointer callback_data)
1296 g_return_if_fail (container != NULL);
1297 g_return_if_fail (GTK_IS_LIST (container));
1298 g_return_if_fail (callback != NULL);
1300 list = GTK_LIST (container);
1301 children = list->children;
1305 child = children->data;
1306 children = children->next;
1308 (* callback) (child, callback_data);
1313 gtk_real_list_select_child (GtkList *list,
1318 GtkWidget *tmp_item;
1320 g_return_if_fail (list != NULL);
1321 g_return_if_fail (GTK_IS_LIST (list));
1322 g_return_if_fail (child != NULL);
1323 g_return_if_fail (GTK_IS_LIST_ITEM (child));
1325 switch (list->selection_mode)
1327 case GTK_SELECTION_SINGLE:
1328 case GTK_SELECTION_BROWSE:
1329 selection = list->selection;
1333 tmp_item = selection->data;
1335 if (tmp_item != child)
1337 tmp_list = selection;
1338 selection = selection->next;
1340 list->selection = g_list_remove_link (list->selection, tmp_list);
1341 g_list_free (tmp_list);
1343 gtk_list_item_deselect (GTK_LIST_ITEM (tmp_item));
1344 gtk_widget_unref (GTK_WIDGET (tmp_item));
1347 selection = selection->next;
1350 if (child->state == GTK_STATE_NORMAL)
1352 list->selection = g_list_prepend (list->selection, child);
1353 gtk_widget_ref (child);
1354 gtk_list_item_select (GTK_LIST_ITEM (child));
1356 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
1359 case GTK_SELECTION_EXTENDED:
1360 if (list->anchor >= 0)
1363 case GTK_SELECTION_MULTIPLE:
1364 if (child->state == GTK_STATE_NORMAL)
1366 list->selection = g_list_prepend (list->selection, child);
1367 gtk_widget_ref (child);
1368 gtk_list_item_select (GTK_LIST_ITEM (child));
1369 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
1376 gtk_real_list_unselect_child (GtkList *list,
1379 g_return_if_fail (list != NULL);
1380 g_return_if_fail (GTK_IS_LIST (list));
1381 g_return_if_fail (child != NULL);
1382 g_return_if_fail (GTK_IS_LIST_ITEM (child));
1384 if (child->state == GTK_STATE_SELECTED)
1386 list->selection = g_list_remove (list->selection, child);
1387 gtk_list_item_deselect (GTK_LIST_ITEM (child));
1388 gtk_widget_unref (child);
1389 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
1394 /***************************************************************************/
1397 gtk_list_set_anchor (GtkList *list,
1400 GtkWidget *undo_focus_child)
1404 g_return_if_fail (list != NULL);
1405 g_return_if_fail (GTK_IS_LIST (list));
1407 if (list->selection_mode != GTK_SELECTION_EXTENDED || list->anchor >= 0)
1410 g_list_free (list->undo_selection);
1411 g_list_free (list->undo_unselection);
1412 list->undo_selection = NULL;
1413 list->undo_unselection = NULL;
1415 if ((work = g_list_nth (list->children, anchor)))
1418 gtk_list_fake_toggle_row (list, GTK_WIDGET (work->data));
1421 gtk_list_fake_unselect_all (list, GTK_WIDGET (work->data));
1422 list->anchor_state = GTK_STATE_SELECTED;
1426 list->anchor = anchor;
1427 list->drag_pos = anchor;
1428 list->undo_focus_child = undo_focus_child;
1432 gtk_list_fake_unselect_all (GtkList *list,
1437 if (item && item->state == GTK_STATE_NORMAL)
1438 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1440 list->undo_selection = list->selection;
1441 list->selection = NULL;
1443 for (work = list->undo_selection; work; work = work->next)
1444 if (work->data != item)
1445 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL);
1449 gtk_list_fake_toggle_row (GtkList *list,
1455 if (item->state == GTK_STATE_NORMAL)
1457 list->anchor_state = GTK_STATE_SELECTED;
1458 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1462 list->anchor_state = GTK_STATE_NORMAL;
1463 gtk_widget_set_state (item, GTK_STATE_NORMAL);
1468 gtk_list_scroll_horizontal (GtkList *list,
1469 GtkScrollType scroll_type,
1474 g_return_if_fail (list != 0);
1475 g_return_if_fail (GTK_IS_LIST (list));
1477 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
1481 gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id)))
1484 switch (scroll_type)
1486 case GTK_SCROLL_STEP_BACKWARD:
1487 adj->value = CLAMP (adj->value - adj->step_increment, adj->lower,
1488 adj->upper - adj->page_size);
1490 case GTK_SCROLL_STEP_FORWARD:
1491 adj->value = CLAMP (adj->value + adj->step_increment, adj->lower,
1492 adj->upper - adj->page_size);
1494 case GTK_SCROLL_PAGE_BACKWARD:
1495 adj->value = CLAMP (adj->value - adj->page_increment, adj->lower,
1496 adj->upper - adj->page_size);
1498 case GTK_SCROLL_PAGE_FORWARD:
1499 adj->value = CLAMP (adj->value + adj->page_increment, adj->lower,
1500 adj->upper - adj->page_size);
1502 case GTK_SCROLL_JUMP:
1503 adj->value = CLAMP (adj->lower + (adj->upper - adj->lower) * position,
1504 adj->lower, adj->upper - adj->page_size);
1509 gtk_adjustment_value_changed (adj);
1513 gtk_list_scroll_vertical (GtkList *list,
1514 GtkScrollType scroll_type,
1517 g_return_if_fail (list != NULL);
1518 g_return_if_fail (GTK_IS_LIST (list));
1520 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
1523 if (list->selection_mode == GTK_SELECTION_EXTENDED)
1525 GtkContainer *container;
1527 if (list->anchor >= 0)
1530 container = GTK_CONTAINER (list);
1531 list->undo_focus_child = container->focus_child;
1532 gtk_list_move_focus_child (list, scroll_type, position);
1533 if (container->focus_child != list->undo_focus_child && !list->add_mode)
1535 gtk_list_unselect_all (list);
1536 gtk_list_select_child (list, container->focus_child);
1540 gtk_list_move_focus_child (list, scroll_type, position);
1544 gtk_list_move_focus_child (GtkList *list,
1545 GtkScrollType scroll_type,
1548 GtkContainer *container;
1554 g_return_if_fail (list != 0);
1555 g_return_if_fail (GTK_IS_LIST (list));
1557 container = GTK_CONTAINER (list);
1559 if (container->focus_child)
1560 work = g_list_find (list->children, container->focus_child);
1562 work = list->children;
1567 switch (scroll_type)
1569 case GTK_SCROLL_STEP_BACKWARD:
1572 gtk_widget_grab_focus (GTK_WIDGET (work->data));
1575 case GTK_SCROLL_STEP_FORWARD:
1578 gtk_widget_grab_focus (GTK_WIDGET (work->data));
1581 case GTK_SCROLL_PAGE_BACKWARD:
1586 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id);
1590 gboolean correct = FALSE;
1592 new_value = adj->value;
1594 if (item->allocation.y <= adj->value)
1596 new_value = MAX (item->allocation.y + item->allocation.height
1597 - adj->page_size, adj->lower);
1601 if (item->allocation.y > new_value)
1602 for (; work; work = work->prev)
1604 item = GTK_WIDGET (work->data);
1605 if (item->allocation.y <= new_value &&
1606 item->allocation.y + item->allocation.height > new_value)
1610 for (; work; work = work->next)
1612 item = GTK_WIDGET (work->data);
1613 if (item->allocation.y <= new_value &&
1614 item->allocation.y + item->allocation.height > new_value)
1618 if (correct && work && work->next && item->allocation.y < new_value)
1619 item = work->next->data;
1622 item = list->children->data;
1624 gtk_widget_grab_focus (item);
1627 case GTK_SCROLL_PAGE_FORWARD:
1632 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id);
1636 gboolean correct = FALSE;
1638 new_value = adj->value;
1640 if (item->allocation.y + item->allocation.height >=
1641 adj->value + adj->page_size)
1643 new_value = item->allocation.y;
1647 new_value = MIN (new_value + adj->page_size, adj->upper);
1649 if (item->allocation.y > new_value)
1650 for (; work; work = work->prev)
1652 item = GTK_WIDGET (work->data);
1653 if (item->allocation.y <= new_value &&
1654 item->allocation.y + item->allocation.height > new_value)
1658 for (; work; work = work->next)
1660 item = GTK_WIDGET (work->data);
1661 if (item->allocation.y <= new_value &&
1662 item->allocation.y + item->allocation.height > new_value)
1666 if (correct && work && work->prev &&
1667 item->allocation.y + item->allocation.height - 1 > new_value)
1668 item = work->prev->data;
1671 item = g_list_last (work)->data;
1673 gtk_widget_grab_focus (item);
1676 case GTK_SCROLL_JUMP:
1677 new_value = GTK_WIDGET(list)->allocation.height * CLAMP (position, 0, 1);
1679 for (item = NULL, work = list->children; work; work =work->next)
1681 item = GTK_WIDGET (work->data);
1682 if (item->allocation.y <= new_value &&
1683 item->allocation.y + item->allocation.height > new_value)
1687 gtk_widget_grab_focus (item);
1696 gtk_list_select_all (GtkList *list)
1698 GtkContainer *container;
1701 g_return_if_fail (list != NULL);
1702 g_return_if_fail (GTK_IS_LIST (list));
1704 if (!list->children)
1707 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
1708 gtk_list_end_drag_selection (list);
1710 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
1711 gtk_list_end_selection (list);
1713 container = GTK_CONTAINER (list);
1715 switch (list->selection_mode)
1717 case GTK_SELECTION_BROWSE:
1718 if (container->focus_child)
1720 gtk_list_select_child (list, container->focus_child);
1725 case GTK_SELECTION_EXTENDED:
1726 g_list_free (list->undo_selection);
1727 g_list_free (list->undo_unselection);
1728 list->undo_selection = NULL;
1729 list->undo_unselection = NULL;
1731 if (list->children &&
1732 GTK_WIDGET_STATE (list->children->data) != GTK_STATE_SELECTED)
1733 gtk_list_fake_toggle_row (list, GTK_WIDGET (list->children->data));
1735 list->anchor_state = GTK_STATE_SELECTED;
1738 list->undo_focus_child = container->focus_child;
1739 gtk_list_update_extended_selection (list, g_list_length(list->children));
1740 gtk_list_end_selection (list);
1743 case GTK_SELECTION_MULTIPLE:
1744 for (work = list->children; work; work = work->next)
1746 if (GTK_WIDGET_STATE (work->data) == GTK_STATE_NORMAL)
1747 gtk_list_select_child (list, GTK_WIDGET (work->data));
1757 gtk_list_unselect_all (GtkList *list)
1759 GtkContainer *container;
1763 g_return_if_fail (list != NULL);
1764 g_return_if_fail (GTK_IS_LIST (list));
1766 if (!list->children)
1769 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
1770 gtk_list_end_drag_selection (list);
1772 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
1773 gtk_list_end_selection (list);
1775 container = GTK_CONTAINER (list);
1777 switch (list->selection_mode)
1779 case GTK_SELECTION_BROWSE:
1780 if (container->focus_child)
1782 gtk_list_select_child (list, container->focus_child);
1787 case GTK_SELECTION_EXTENDED:
1788 g_list_free (list->undo_selection);
1789 g_list_free (list->undo_unselection);
1790 list->undo_selection = NULL;
1791 list->undo_unselection = NULL;
1794 list->drag_pos = -1;
1795 list->undo_focus_child = container->focus_child;
1802 work = list->selection;
1808 gtk_list_unselect_child (list, item);
1813 gtk_list_extend_selection (GtkList *list,
1814 GtkScrollType scroll_type,
1816 gboolean auto_start_selection)
1818 GtkContainer *container;
1820 g_return_if_fail (list != NULL);
1821 g_return_if_fail (GTK_IS_LIST (list));
1823 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
1824 list->selection_mode != GTK_SELECTION_EXTENDED)
1827 container = GTK_CONTAINER (list);
1829 if (auto_start_selection)
1832 focus_row = g_list_index (list->children, container->focus_child);
1833 gtk_list_set_anchor (list, list->add_mode, focus_row,
1834 container->focus_child);
1836 else if (list->anchor < 0)
1839 gtk_list_move_focus_child (list, scroll_type, position);
1840 gtk_list_update_extended_selection
1841 (list, g_list_index (list->children, container->focus_child));
1845 gtk_list_update_extended_selection (GtkList *list,
1859 length = g_list_length (list->children);
1863 if (list->selection_mode != GTK_SELECTION_EXTENDED || !list->anchor < 0)
1866 /* extending downwards */
1867 if (row > list->drag_pos && list->anchor <= list->drag_pos)
1869 s2 = list->drag_pos + 1;
1872 /* extending upwards */
1873 else if (row < list->drag_pos && list->anchor >= list->drag_pos)
1876 e2 = list->drag_pos - 1;
1878 else if (row < list->drag_pos && list->anchor < list->drag_pos)
1880 e1 = list->drag_pos;
1881 /* row and drag_pos on different sides of anchor :
1882 take back the selection between anchor and drag_pos,
1883 select between anchor and row */
1884 if (row < list->anchor)
1886 s1 = list->anchor + 1;
1888 e2 = list->anchor - 1;
1890 /* take back the selection between anchor and drag_pos */
1894 else if (row > list->drag_pos && list->anchor > list->drag_pos)
1896 s1 = list->drag_pos;
1897 /* row and drag_pos on different sides of anchor :
1898 take back the selection between anchor and drag_pos,
1899 select between anchor and row */
1900 if (row > list->anchor)
1902 e1 = list->anchor - 1;
1903 s2 = list->anchor + 1;
1906 /* take back the selection between anchor and drag_pos */
1911 list->drag_pos = row;
1913 /* restore the elements between s1 and e1 */
1916 for (i = s1, work = g_list_nth (list->children, i); i <= e1;
1917 i++, work = work->next)
1919 if (g_list_find (list->selection, work->data))
1920 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_SELECTED);
1922 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL);
1926 /* extend the selection between s2 and e2 */
1929 for (i = s2, work = g_list_nth (list->children, i); i <= e2;
1930 i++, work = work->next)
1931 if (GTK_WIDGET (work->data)->state != list->anchor_state)
1932 gtk_widget_set_state (GTK_WIDGET (work->data), list->anchor_state);
1937 gtk_list_end_selection (GtkList *list)
1945 g_return_if_fail (list != NULL);
1946 g_return_if_fail (GTK_IS_LIST (list));
1948 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
1952 i = MIN (list->anchor, list->drag_pos);
1953 e = MAX (list->anchor, list->drag_pos);
1956 list->drag_pos = -1;
1958 if (list->undo_selection)
1960 work = list->selection;
1961 list->selection = list->undo_selection;
1962 list->undo_selection = work;
1963 work = list->selection;
1968 item_index = g_list_index (list->children, item);
1969 if (item_index < i || item_index > e)
1971 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1972 gtk_list_unselect_child (list, item);
1973 list->undo_selection = g_list_prepend (list->undo_selection,
1979 for (work = g_list_nth (list->children, i); i <= e; i++, work = work->next)
1982 if (g_list_find (list->selection, item))
1984 if (item->state == GTK_STATE_NORMAL)
1986 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1987 gtk_list_unselect_child (list, item);
1988 list->undo_selection = g_list_prepend (list->undo_selection,
1992 else if (item->state == GTK_STATE_SELECTED)
1994 gtk_widget_set_state (item, GTK_STATE_NORMAL);
1995 list->undo_unselection = g_list_prepend (list->undo_unselection,
2000 for (work = list->undo_unselection; work; work = work->next)
2001 gtk_list_select_child (list, GTK_WIDGET (work->data));
2006 gtk_list_start_selection (GtkList *list)
2008 GtkContainer *container;
2011 g_return_if_fail (list != NULL);
2012 g_return_if_fail (GTK_IS_LIST (list));
2014 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
2017 container = GTK_CONTAINER (list);
2019 if ((focus_row = g_list_index (list->selection, container->focus_child))
2021 gtk_list_set_anchor (list, list->add_mode,
2022 focus_row, container->focus_child);
2026 gtk_list_toggle_row (GtkList *list,
2029 g_return_if_fail (list != NULL);
2030 g_return_if_fail (GTK_IS_LIST (list));
2031 g_return_if_fail (item != NULL);
2032 g_return_if_fail (GTK_IS_LIST_ITEM (item));
2034 switch (list->selection_mode)
2036 case GTK_SELECTION_EXTENDED:
2037 case GTK_SELECTION_MULTIPLE:
2038 case GTK_SELECTION_SINGLE:
2040 if (item->state == GTK_STATE_SELECTED)
2042 gtk_list_unselect_child (list, item);
2046 case GTK_SELECTION_BROWSE:
2047 gtk_list_select_child (list, item);
2053 gtk_list_toggle_focus_row (GtkList *list)
2055 GtkContainer *container;
2058 g_return_if_fail (list != 0);
2059 g_return_if_fail (GTK_IS_LIST (list));
2061 container = GTK_CONTAINER (list);
2063 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
2064 !container->focus_child)
2067 switch (list->selection_mode)
2069 case GTK_SELECTION_SINGLE:
2070 case GTK_SELECTION_MULTIPLE:
2072 gtk_list_toggle_row (list, container->focus_child);
2075 case GTK_SELECTION_EXTENDED:
2077 if ((focus_row = g_list_index (list->children, container->focus_child))
2081 g_list_free (list->undo_selection);
2082 g_list_free (list->undo_unselection);
2083 list->undo_selection = NULL;
2084 list->undo_unselection = NULL;
2086 list->anchor = focus_row;
2087 list->drag_pos = focus_row;
2088 list->undo_focus_child = container->focus_child;
2091 gtk_list_fake_toggle_row (list, container->focus_child);
2093 gtk_list_fake_unselect_all (list, container->focus_child);
2095 gtk_list_end_selection (list);
2104 gtk_list_toggle_add_mode (GtkList *list)
2106 GtkContainer *container;
2108 g_return_if_fail (list != 0);
2109 g_return_if_fail (GTK_IS_LIST (list));
2111 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
2112 list->selection_mode != GTK_SELECTION_EXTENDED)
2115 container = GTK_CONTAINER (list);
2119 list->add_mode = FALSE;
2120 list->anchor_state = GTK_STATE_SELECTED;
2123 list->add_mode = TRUE;
2125 if (container->focus_child)
2126 gtk_widget_queue_draw (container->focus_child);
2130 gtk_list_undo_selection (GtkList *list)
2134 g_return_if_fail (list != NULL);
2135 g_return_if_fail (GTK_IS_LIST (list));
2137 if (list->selection_mode != GTK_SELECTION_EXTENDED ||
2138 (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)))
2141 if (list->anchor >= 0)
2142 gtk_list_end_selection (list);
2144 if (!(list->undo_selection || list->undo_unselection))
2146 gtk_list_unselect_all (list);
2150 for (work = list->undo_selection; work; work = work->next)
2151 gtk_list_select_child (list, GTK_WIDGET (work->data));
2153 for (work = list->undo_unselection; work; work = work->next)
2154 gtk_list_unselect_child (list, GTK_WIDGET (work->data));
2156 if (list->undo_focus_child)
2158 GtkContainer *container;
2160 container = GTK_CONTAINER (list);
2162 if (container->focus_child &&
2163 GTK_WIDGET_HAS_FOCUS (container->focus_child))
2164 gtk_widget_grab_focus (list->undo_focus_child);
2166 gtk_container_set_focus_child (container, list->undo_focus_child);
2169 list->undo_focus_child = NULL;
2171 g_list_free (list->undo_selection);
2172 g_list_free (list->undo_unselection);
2173 list->undo_selection = NULL;
2174 list->undo_unselection = NULL;
2178 gtk_list_focus_lost (GtkWidget *item,
2182 g_return_if_fail (list != NULL);
2183 g_return_if_fail (GTK_IS_LIST (list));
2184 g_return_if_fail (item != NULL);
2185 g_return_if_fail (GTK_IS_LIST_ITEM (item));
2187 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0 &&
2188 item == GTK_CONTAINER (list)->focus_child)
2189 gtk_list_end_selection (list);
2193 gtk_list_set_focus_child (GtkContainer *container,
2198 g_return_if_fail (container != NULL);
2199 g_return_if_fail (GTK_IS_LIST (container));
2202 g_return_if_fail (GTK_IS_WIDGET (child));
2204 list = GTK_LIST (container);
2205 list->last_focus_child = container->focus_child;
2207 if (child != container->focus_child)
2209 if (container->focus_child)
2210 gtk_widget_unref (container->focus_child);
2211 container->focus_child = child;
2212 if (container->focus_child)
2213 gtk_widget_ref (container->focus_child);
2216 /* check for v adjustment */
2217 if (container->focus_child)
2219 GtkAdjustment *adjustment;
2221 adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container),
2222 vadjustment_key_id);
2224 gtk_adjustment_clamp_page (adjustment,
2225 container->focus_child->allocation.y,
2226 (container->focus_child->allocation.y +
2227 container->focus_child->allocation.height));
2230 switch (list->selection_mode)
2232 case GTK_SELECTION_BROWSE:
2234 gtk_list_select_child (list, child);
2243 gtk_list_focus (GtkContainer *container,
2244 GtkDirectionType direction)
2246 gint return_val = FALSE;
2248 g_return_val_if_fail (container != NULL, FALSE);
2249 g_return_val_if_fail (GTK_IS_LIST (container), FALSE);
2251 if (!GTK_WIDGET_SENSITIVE (container))
2253 else if (container->focus_child == NULL ||
2254 !GTK_WIDGET_HAS_FOCUS (container->focus_child))
2256 if (*GTK_CONTAINER_CLASS (parent_class)->focus)
2257 return_val = GTK_CONTAINER_CLASS (parent_class)->focus
2258 (container, direction);
2265 list = GTK_LIST (container);
2266 if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
2267 gtk_list_end_selection (list);