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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include <string.h> /* memset */
30 #undef GTK_DISABLE_DEPRECATED
31 #define __GTK_LIST_C__
34 #include "gtklistitem.h"
36 #include "gtksignal.h"
38 #include "gtkmarshalers.h"
55 #define SCROLL_TIME 100
57 /*** GtkList Methods ***/
58 static void gtk_list_class_init (GtkListClass *klass);
59 static void gtk_list_init (GtkList *list);
60 static void gtk_list_set_arg (GtkObject *object,
63 static void gtk_list_get_arg (GtkObject *object,
66 /*** GtkObject Methods ***/
67 static void gtk_list_dispose (GObject *object);
69 /*** GtkWidget Methods ***/
70 static void gtk_list_size_request (GtkWidget *widget,
71 GtkRequisition *requisition);
72 static void gtk_list_size_allocate (GtkWidget *widget,
73 GtkAllocation *allocation);
74 static void gtk_list_realize (GtkWidget *widget);
75 static void gtk_list_unmap (GtkWidget *widget);
76 static void gtk_list_style_set (GtkWidget *widget,
77 GtkStyle *previous_style);
78 static gint gtk_list_motion_notify (GtkWidget *widget,
79 GdkEventMotion *event);
80 static gint gtk_list_button_press (GtkWidget *widget,
81 GdkEventButton *event);
82 static gint gtk_list_button_release (GtkWidget *widget,
83 GdkEventButton *event);
85 static gboolean gtk_list_focus (GtkWidget *widget,
86 GtkDirectionType direction);
88 /*** GtkContainer Methods ***/
89 static void gtk_list_add (GtkContainer *container,
91 static void gtk_list_remove (GtkContainer *container,
93 static void gtk_list_forall (GtkContainer *container,
94 gboolean include_internals,
96 gpointer callback_data);
97 static GtkType gtk_list_child_type (GtkContainer *container);
98 static void gtk_list_set_focus_child (GtkContainer *container,
101 /*** GtkList Private Functions ***/
102 static void gtk_list_move_focus_child (GtkList *list,
103 GtkScrollType scroll_type,
105 static gint gtk_list_horizontal_timeout (GtkWidget *list);
106 static gint gtk_list_vertical_timeout (GtkWidget *list);
107 static void gtk_list_remove_items_internal (GtkList *list,
111 /*** GtkList Selection Methods ***/
112 static void gtk_real_list_select_child (GtkList *list,
114 static void gtk_real_list_unselect_child (GtkList *list,
117 /*** GtkList Selection Functions ***/
118 static void gtk_list_set_anchor (GtkList *list,
121 GtkWidget *undo_focus_child);
122 static void gtk_list_fake_unselect_all (GtkList *list,
124 static void gtk_list_fake_toggle_row (GtkList *list,
126 static void gtk_list_update_extended_selection (GtkList *list,
128 static void gtk_list_reset_extended_selection (GtkList *list);
130 /*** GtkListItem Signal Functions ***/
131 static void gtk_list_signal_drag_begin (GtkWidget *widget,
132 GdkDragContext *context,
134 static void gtk_list_signal_toggle_focus_row (GtkListItem *list_item,
136 static void gtk_list_signal_select_all (GtkListItem *list_item,
138 static void gtk_list_signal_unselect_all (GtkListItem *list_item,
140 static void gtk_list_signal_undo_selection (GtkListItem *list_item,
142 static void gtk_list_signal_start_selection (GtkListItem *list_item,
144 static void gtk_list_signal_end_selection (GtkListItem *list_item,
146 static void gtk_list_signal_extend_selection (GtkListItem *list_item,
147 GtkScrollType scroll_type,
149 gboolean auto_start_selection,
151 static void gtk_list_signal_scroll_horizontal (GtkListItem *list_item,
152 GtkScrollType scroll_type,
155 static void gtk_list_signal_scroll_vertical (GtkListItem *list_item,
156 GtkScrollType scroll_type,
159 static void gtk_list_signal_toggle_add_mode (GtkListItem *list_item,
161 static void gtk_list_signal_item_select (GtkListItem *list_item,
163 static void gtk_list_signal_item_deselect (GtkListItem *list_item,
165 static void gtk_list_signal_item_toggle (GtkListItem *list_item,
169 static void gtk_list_drag_begin (GtkWidget *widget,
170 GdkDragContext *context);
173 static GtkContainerClass *parent_class = NULL;
174 static guint list_signals[LAST_SIGNAL] = { 0 };
176 static const gchar vadjustment_key[] = "gtk-vadjustment";
177 static guint vadjustment_key_id = 0;
178 static const gchar hadjustment_key[] = "gtk-hadjustment";
179 static guint hadjustment_key_id = 0;
182 gtk_list_get_type (void)
184 static GtkType list_type = 0;
188 static const GtkTypeInfo list_info =
192 sizeof (GtkListClass),
193 (GtkClassInitFunc) gtk_list_class_init,
194 (GtkObjectInitFunc) gtk_list_init,
195 /* reserved_1 */ NULL,
196 /* reserved_2 */ NULL,
197 (GtkClassInitFunc) NULL,
201 list_type = gtk_type_unique (GTK_TYPE_CONTAINER, &list_info);
208 gtk_list_class_init (GtkListClass *class)
210 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
211 GtkObjectClass *object_class;
212 GtkWidgetClass *widget_class;
213 GtkContainerClass *container_class;
215 object_class = (GtkObjectClass*) class;
216 widget_class = (GtkWidgetClass*) class;
217 container_class = (GtkContainerClass*) class;
219 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
221 vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
222 hadjustment_key_id = g_quark_from_static_string (hadjustment_key);
224 gobject_class->dispose = gtk_list_dispose;
227 object_class->set_arg = gtk_list_set_arg;
228 object_class->get_arg = gtk_list_get_arg;
230 widget_class->unmap = gtk_list_unmap;
231 widget_class->style_set = gtk_list_style_set;
232 widget_class->realize = gtk_list_realize;
233 widget_class->button_press_event = gtk_list_button_press;
234 widget_class->button_release_event = gtk_list_button_release;
235 widget_class->motion_notify_event = gtk_list_motion_notify;
236 widget_class->size_request = gtk_list_size_request;
237 widget_class->size_allocate = gtk_list_size_allocate;
238 widget_class->drag_begin = gtk_list_drag_begin;
239 widget_class->focus = gtk_list_focus;
241 container_class->add = gtk_list_add;
242 container_class->remove = gtk_list_remove;
243 container_class->forall = gtk_list_forall;
244 container_class->child_type = gtk_list_child_type;
245 container_class->set_focus_child = gtk_list_set_focus_child;
247 class->selection_changed = NULL;
248 class->select_child = gtk_real_list_select_child;
249 class->unselect_child = gtk_real_list_unselect_child;
251 list_signals[SELECTION_CHANGED] =
252 gtk_signal_new (I_("selection-changed"),
254 GTK_CLASS_TYPE (object_class),
255 GTK_SIGNAL_OFFSET (GtkListClass, selection_changed),
256 _gtk_marshal_VOID__VOID,
258 list_signals[SELECT_CHILD] =
259 gtk_signal_new (I_("select-child"),
261 GTK_CLASS_TYPE (object_class),
262 GTK_SIGNAL_OFFSET (GtkListClass, select_child),
263 _gtk_marshal_VOID__OBJECT,
266 list_signals[UNSELECT_CHILD] =
267 gtk_signal_new (I_("unselect-child"),
269 GTK_CLASS_TYPE (object_class),
270 GTK_SIGNAL_OFFSET (GtkListClass, unselect_child),
271 _gtk_marshal_VOID__OBJECT,
275 gtk_object_add_arg_type ("GtkList::selection-mode",
276 GTK_TYPE_SELECTION_MODE,
277 GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
282 gtk_list_init (GtkList *list)
284 list->children = NULL;
285 list->selection = NULL;
287 list->undo_selection = NULL;
288 list->undo_unselection = NULL;
290 list->last_focus_child = NULL;
291 list->undo_focus_child = NULL;
298 list->anchor_state = GTK_STATE_SELECTED;
300 list->selection_mode = GTK_SELECTION_SINGLE;
301 list->drag_selection = FALSE;
302 list->add_mode = FALSE;
306 gtk_list_set_arg (GtkObject *object,
310 GtkList *list = GTK_LIST (object);
314 case ARG_SELECTION_MODE:
315 gtk_list_set_selection_mode (list, GTK_VALUE_ENUM (*arg));
321 gtk_list_get_arg (GtkObject *object,
325 GtkList *list = GTK_LIST (object);
329 case ARG_SELECTION_MODE:
330 GTK_VALUE_ENUM (*arg) = list->selection_mode;
333 arg->type = GTK_TYPE_INVALID;
341 return GTK_WIDGET (gtk_type_new (GTK_TYPE_LIST));
345 /* Private GtkObject Methods :
350 gtk_list_dispose (GObject *object)
352 gtk_list_clear_items (GTK_LIST (object), 0, -1);
354 G_OBJECT_CLASS (parent_class)->dispose (object);
358 /* Private GtkWidget Methods :
360 * gtk_list_size_request
361 * gtk_list_size_allocate
364 * gtk_list_motion_notify
365 * gtk_list_button_press
366 * gtk_list_button_release
369 gtk_list_size_request (GtkWidget *widget,
370 GtkRequisition *requisition)
372 GtkList *list = GTK_LIST (widget);
376 requisition->width = 0;
377 requisition->height = 0;
379 children = list->children;
382 child = children->data;
383 children = children->next;
385 if (gtk_widget_get_visible (child))
387 GtkRequisition child_requisition;
389 gtk_widget_size_request (child, &child_requisition);
391 requisition->width = MAX (requisition->width,
392 child_requisition.width);
393 requisition->height += child_requisition.height;
397 requisition->width += GTK_CONTAINER (list)->border_width * 2;
398 requisition->height += GTK_CONTAINER (list)->border_width * 2;
400 requisition->width = MAX (requisition->width, 1);
401 requisition->height = MAX (requisition->height, 1);
405 gtk_list_size_allocate (GtkWidget *widget,
406 GtkAllocation *allocation)
408 GtkList *list = GTK_LIST (widget);
410 GtkAllocation child_allocation;
413 widget->allocation = *allocation;
414 if (GTK_WIDGET_REALIZED (widget))
415 gdk_window_move_resize (widget->window,
416 allocation->x, allocation->y,
417 allocation->width, allocation->height);
421 child_allocation.x = GTK_CONTAINER (list)->border_width;
422 child_allocation.y = GTK_CONTAINER (list)->border_width;
423 child_allocation.width = MAX (1, (gint)allocation->width -
424 child_allocation.x * 2);
426 children = list->children;
430 child = children->data;
431 children = children->next;
433 if (gtk_widget_get_visible (child))
435 GtkRequisition child_requisition;
436 gtk_widget_get_child_requisition (child, &child_requisition);
438 child_allocation.height = child_requisition.height;
440 gtk_widget_size_allocate (child, &child_allocation);
442 child_allocation.y += child_allocation.height;
449 gtk_list_realize (GtkWidget *widget)
451 GdkWindowAttr attributes;
452 gint attributes_mask;
454 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
456 attributes.window_type = GDK_WINDOW_CHILD;
457 attributes.x = widget->allocation.x;
458 attributes.y = widget->allocation.y;
459 attributes.width = widget->allocation.width;
460 attributes.height = widget->allocation.height;
461 attributes.wclass = GDK_INPUT_OUTPUT;
462 attributes.visual = gtk_widget_get_visual (widget);
463 attributes.colormap = gtk_widget_get_colormap (widget);
464 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
466 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
468 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
469 &attributes, attributes_mask);
470 gdk_window_set_user_data (widget->window, widget);
472 widget->style = gtk_style_attach (widget->style, widget->window);
473 gdk_window_set_background (widget->window,
474 &widget->style->base[GTK_STATE_NORMAL]);
478 list_has_grab (GtkList *list)
480 return (GTK_WIDGET_HAS_GRAB (list) &&
481 gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (list))));
486 gtk_list_unmap (GtkWidget *widget)
488 GtkList *list = GTK_LIST (widget);
490 if (!GTK_WIDGET_MAPPED (widget))
493 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
495 if (list_has_grab (list))
497 gtk_list_end_drag_selection (list);
499 if (list->anchor != -1 && list->selection_mode == GTK_SELECTION_MULTIPLE)
500 gtk_list_end_selection (list);
503 gdk_window_hide (widget->window);
507 gtk_list_motion_notify (GtkWidget *widget,
508 GdkEventMotion *event)
510 GtkList *list = GTK_LIST (widget);
511 GtkWidget *item = NULL;
513 GtkContainer *container;
521 if (!list->drag_selection || !list->children)
524 container = GTK_CONTAINER (widget);
526 if (event->is_hint || event->window != widget->window)
527 gdk_window_get_pointer (widget->window, &x, &y, NULL);
534 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id);
536 /* horizontal autoscrolling */
537 if (adj && widget->allocation.width > adj->page_size &&
538 (x < adj->value || x >= adj->value + adj->page_size))
540 if (list->htimer == 0)
542 list->htimer = gdk_threads_add_timeout
543 (SCROLL_TIME, (GSourceFunc) gtk_list_horizontal_timeout, widget);
545 if (!((x < adj->value && adj->value <= 0) ||
546 (x > adj->value + adj->page_size &&
547 adj->value >= adj->upper - adj->page_size)))
552 value = adj->value + (x - adj->value) / 2 - 1;
554 value = adj->value + 1 + (x - adj->value - adj->page_size) / 2;
556 gtk_adjustment_set_value (adj,
558 adj->upper - adj->page_size));
566 /* vertical autoscrolling */
567 for (work = list->children; work; length++, work = work->next)
571 item = GTK_WIDGET (work->data);
572 if (item->allocation.y > y ||
573 (item->allocation.y <= y &&
574 item->allocation.y + item->allocation.height > y))
578 if (work->data == container->focus_child)
585 if (list->vtimer != 0)
588 if (!((y < 0 && focus_row == 0) ||
589 (y > widget->allocation.height && focus_row >= length - 1)))
590 list->vtimer = gdk_threads_add_timeout (SCROLL_TIME,
591 (GSourceFunc) gtk_list_vertical_timeout,
594 if (row != focus_row)
595 gtk_widget_grab_focus (item);
597 switch (list->selection_mode)
599 case GTK_SELECTION_BROWSE:
600 gtk_list_select_child (list, item);
602 case GTK_SELECTION_MULTIPLE:
603 gtk_list_update_extended_selection (list, row);
613 gtk_list_button_press (GtkWidget *widget,
614 GdkEventButton *event)
616 GtkList *list = GTK_LIST (widget);
619 if (event->button != 1)
622 item = gtk_get_event_widget ((GdkEvent*) event);
624 while (item && !GTK_IS_LIST_ITEM (item))
627 if (item && (item->parent == widget))
632 if (event->type == GDK_BUTTON_PRESS)
634 gtk_grab_add (widget);
635 list->drag_selection = TRUE;
637 else if (list_has_grab (list))
638 gtk_list_end_drag_selection (list);
640 if (!gtk_widget_has_focus(item))
641 gtk_widget_grab_focus (item);
645 list->add_mode = FALSE;
646 gtk_widget_queue_draw (item);
649 switch (list->selection_mode)
651 case GTK_SELECTION_SINGLE:
652 if (event->type != GDK_BUTTON_PRESS)
653 gtk_list_select_child (list, item);
655 list->undo_focus_child = item;
658 case GTK_SELECTION_BROWSE:
661 case GTK_SELECTION_MULTIPLE:
662 focus_row = g_list_index (list->children, item);
664 if (list->last_focus_child)
665 last_focus_row = g_list_index (list->children,
666 list->last_focus_child);
669 last_focus_row = focus_row;
670 list->last_focus_child = item;
673 if (event->type != GDK_BUTTON_PRESS)
675 if (list->anchor >= 0)
677 gtk_list_update_extended_selection (list, focus_row);
678 gtk_list_end_selection (list);
680 gtk_list_select_child (list, item);
684 if (event->state & GDK_CONTROL_MASK)
686 if (event->state & GDK_SHIFT_MASK)
688 if (list->anchor < 0)
690 g_list_free (list->undo_selection);
691 g_list_free (list->undo_unselection);
692 list->undo_selection = NULL;
693 list->undo_unselection = NULL;
695 list->anchor = last_focus_row;
696 list->drag_pos = last_focus_row;
697 list->undo_focus_child = list->last_focus_child;
699 gtk_list_update_extended_selection (list, focus_row);
703 if (list->anchor < 0)
704 gtk_list_set_anchor (list, TRUE,
705 focus_row, list->last_focus_child);
707 gtk_list_update_extended_selection (list, focus_row);
712 if (event->state & GDK_SHIFT_MASK)
714 gtk_list_set_anchor (list, FALSE,
715 last_focus_row, list->last_focus_child);
716 gtk_list_update_extended_selection (list, focus_row);
720 if (list->anchor < 0)
721 gtk_list_set_anchor (list, FALSE, focus_row,
722 list->last_focus_child);
724 gtk_list_update_extended_selection (list, focus_row);
738 gtk_list_button_release (GtkWidget *widget,
739 GdkEventButton *event)
741 GtkList *list = GTK_LIST (widget);
744 /* we don't handle button 2 and 3 */
745 if (event->button != 1)
748 if (list->drag_selection)
750 gtk_list_end_drag_selection (list);
752 switch (list->selection_mode)
754 case GTK_SELECTION_MULTIPLE:
755 if (!(event->state & GDK_SHIFT_MASK))
756 gtk_list_end_selection (list);
759 case GTK_SELECTION_SINGLE:
761 item = gtk_get_event_widget ((GdkEvent*) event);
763 while (item && !GTK_IS_LIST_ITEM (item))
766 if (item && item->parent == widget)
768 if (list->undo_focus_child == item)
769 gtk_list_toggle_row (list, item);
771 list->undo_focus_child = NULL;
785 gtk_list_style_set (GtkWidget *widget,
786 GtkStyle *previous_style)
788 if (previous_style && GTK_WIDGET_REALIZED (widget))
789 gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
792 /* GtkContainer Methods :
796 * gtk_list_child_type
797 * gtk_list_set_focus_child
801 gtk_list_add (GtkContainer *container,
806 g_return_if_fail (GTK_IS_LIST_ITEM (widget));
808 item_list = g_list_alloc ();
809 item_list->data = widget;
811 gtk_list_append_items (GTK_LIST (container), item_list);
815 gtk_list_remove (GtkContainer *container,
820 g_return_if_fail (container == GTK_CONTAINER (widget->parent));
822 item_list = g_list_alloc ();
823 item_list->data = widget;
825 gtk_list_remove_items (GTK_LIST (container), item_list);
827 g_list_free (item_list);
831 gtk_list_forall (GtkContainer *container,
832 gboolean include_internals,
833 GtkCallback callback,
834 gpointer callback_data)
836 GtkList *list = GTK_LIST (container);
840 children = list->children;
844 child = children->data;
845 children = children->next;
847 (* callback) (child, callback_data);
852 gtk_list_child_type (GtkContainer *container)
854 return GTK_TYPE_LIST_ITEM;
858 gtk_list_set_focus_child (GtkContainer *container,
863 g_return_if_fail (GTK_IS_LIST (container));
866 g_return_if_fail (GTK_IS_WIDGET (child));
868 list = GTK_LIST (container);
870 if (child != container->focus_child)
872 if (container->focus_child)
874 list->last_focus_child = container->focus_child;
875 g_object_unref (container->focus_child);
877 container->focus_child = child;
878 if (container->focus_child)
879 g_object_ref (container->focus_child);
882 /* check for v adjustment */
883 if (container->focus_child)
885 GtkAdjustment *adjustment;
887 adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container),
890 gtk_adjustment_clamp_page (adjustment,
891 container->focus_child->allocation.y,
892 (container->focus_child->allocation.y +
893 container->focus_child->allocation.height));
894 switch (list->selection_mode)
896 case GTK_SELECTION_BROWSE:
897 gtk_list_select_child (list, child);
899 case GTK_SELECTION_MULTIPLE:
900 if (!list->last_focus_child && !list->add_mode)
902 list->undo_focus_child = list->last_focus_child;
903 gtk_list_unselect_all (list);
904 gtk_list_select_child (list, child);
914 gtk_list_focus (GtkWidget *widget,
915 GtkDirectionType direction)
917 gint return_val = FALSE;
918 GtkContainer *container;
920 container = GTK_CONTAINER (widget);
922 if (container->focus_child == NULL ||
923 !gtk_widget_has_focus (container->focus_child))
925 if (GTK_LIST (container)->last_focus_child)
926 gtk_container_set_focus_child
927 (container, GTK_LIST (container)->last_focus_child);
929 if (GTK_WIDGET_CLASS (parent_class)->focus)
930 return_val = GTK_WIDGET_CLASS (parent_class)->focus (widget,
938 list = GTK_LIST (container);
939 if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
940 gtk_list_end_selection (list);
942 if (container->focus_child)
943 list->last_focus_child = container->focus_child;
950 /* Public GtkList Methods :
952 * gtk_list_insert_items
953 * gtk_list_append_items
954 * gtk_list_prepend_items
955 * gtk_list_remove_items
956 * gtk_list_remove_items_no_unref
957 * gtk_list_clear_items
959 * gtk_list_child_position
962 gtk_list_insert_items (GtkList *list,
971 g_return_if_fail (GTK_IS_LIST (list));
976 gtk_list_end_drag_selection (list);
977 if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
978 gtk_list_end_selection (list);
983 widget = tmp_list->data;
984 tmp_list = tmp_list->next;
986 gtk_widget_set_parent (widget, GTK_WIDGET (list));
987 gtk_signal_connect (GTK_OBJECT (widget), "drag-begin",
988 G_CALLBACK (gtk_list_signal_drag_begin),
990 gtk_signal_connect (GTK_OBJECT (widget), "toggle-focus-row",
991 G_CALLBACK (gtk_list_signal_toggle_focus_row),
993 gtk_signal_connect (GTK_OBJECT (widget), "select-all",
994 G_CALLBACK (gtk_list_signal_select_all),
996 gtk_signal_connect (GTK_OBJECT (widget), "unselect-all",
997 G_CALLBACK (gtk_list_signal_unselect_all),
999 gtk_signal_connect (GTK_OBJECT (widget), "undo-selection",
1000 G_CALLBACK (gtk_list_signal_undo_selection),
1002 gtk_signal_connect (GTK_OBJECT (widget), "start-selection",
1003 G_CALLBACK (gtk_list_signal_start_selection),
1005 gtk_signal_connect (GTK_OBJECT (widget), "end-selection",
1006 G_CALLBACK (gtk_list_signal_end_selection),
1008 gtk_signal_connect (GTK_OBJECT (widget), "extend-selection",
1009 G_CALLBACK (gtk_list_signal_extend_selection),
1011 gtk_signal_connect (GTK_OBJECT (widget), "scroll-horizontal",
1012 G_CALLBACK (gtk_list_signal_scroll_horizontal),
1014 gtk_signal_connect (GTK_OBJECT (widget), "scroll-vertical",
1015 G_CALLBACK (gtk_list_signal_scroll_vertical),
1017 gtk_signal_connect (GTK_OBJECT (widget), "toggle-add-mode",
1018 G_CALLBACK (gtk_list_signal_toggle_add_mode),
1020 gtk_signal_connect (GTK_OBJECT (widget), "select",
1021 G_CALLBACK (gtk_list_signal_item_select),
1023 gtk_signal_connect (GTK_OBJECT (widget), "deselect",
1024 G_CALLBACK (gtk_list_signal_item_deselect),
1026 gtk_signal_connect (GTK_OBJECT (widget), "toggle",
1027 G_CALLBACK (gtk_list_signal_item_toggle),
1032 nchildren = g_list_length (list->children);
1033 if ((position < 0) || (position > nchildren))
1034 position = nchildren;
1036 if (position == nchildren)
1040 tmp_list = g_list_last (list->children);
1041 tmp_list->next = items;
1042 items->prev = tmp_list;
1046 list->children = items;
1051 tmp_list = g_list_nth (list->children, position);
1052 last = g_list_last (items);
1055 tmp_list->prev->next = items;
1056 last->next = tmp_list;
1057 items->prev = tmp_list->prev;
1058 tmp_list->prev = last;
1060 if (tmp_list == list->children)
1061 list->children = items;
1064 if (list->children && !list->selection &&
1065 (list->selection_mode == GTK_SELECTION_BROWSE))
1067 widget = list->children->data;
1068 gtk_list_select_child (list, widget);
1073 gtk_list_append_items (GtkList *list,
1076 g_return_if_fail (GTK_IS_LIST (list));
1078 gtk_list_insert_items (list, items, -1);
1082 gtk_list_prepend_items (GtkList *list,
1085 g_return_if_fail (GTK_IS_LIST (list));
1087 gtk_list_insert_items (list, items, 0);
1091 gtk_list_remove_items (GtkList *list,
1094 gtk_list_remove_items_internal (list, items, FALSE);
1098 gtk_list_remove_items_no_unref (GtkList *list,
1101 gtk_list_remove_items_internal (list, items, TRUE);
1105 gtk_list_clear_items (GtkList *list,
1109 GtkContainer *container;
1111 GtkWidget *new_focus_child = NULL;
1116 gboolean grab_focus = FALSE;
1118 g_return_if_fail (GTK_IS_LIST (list));
1120 nchildren = g_list_length (list->children);
1125 if ((end < 0) || (end > nchildren))
1131 container = GTK_CONTAINER (list);
1133 gtk_list_end_drag_selection (list);
1134 if (list->selection_mode == GTK_SELECTION_MULTIPLE)
1136 if (list->anchor >= 0)
1137 gtk_list_end_selection (list);
1139 gtk_list_reset_extended_selection (list);
1142 start_list = g_list_nth (list->children, start);
1143 end_list = g_list_nth (list->children, end);
1145 if (start_list->prev)
1146 start_list->prev->next = end_list;
1147 if (end_list && end_list->prev)
1148 end_list->prev->next = NULL;
1150 end_list->prev = start_list->prev;
1151 if (start_list == list->children)
1152 list->children = end_list;
1154 if (container->focus_child)
1156 if (g_list_find (start_list, container->focus_child))
1158 if (start_list->prev)
1159 new_focus_child = start_list->prev->data;
1160 else if (list->children)
1161 new_focus_child = list->children->data;
1163 if (gtk_widget_has_focus (container->focus_child))
1168 tmp_list = start_list;
1171 widget = tmp_list->data;
1172 tmp_list = tmp_list->next;
1174 g_object_ref (widget);
1176 if (widget->state == GTK_STATE_SELECTED)
1177 gtk_list_unselect_child (list, widget);
1179 gtk_signal_disconnect_by_data (GTK_OBJECT (widget), (gpointer) list);
1180 gtk_widget_unparent (widget);
1182 if (widget == list->undo_focus_child)
1183 list->undo_focus_child = NULL;
1184 if (widget == list->last_focus_child)
1185 list->last_focus_child = NULL;
1187 g_object_unref (widget);
1190 g_list_free (start_list);
1192 if (new_focus_child)
1195 gtk_widget_grab_focus (new_focus_child);
1196 else if (container->focus_child)
1197 gtk_container_set_focus_child (container, new_focus_child);
1199 if ((list->selection_mode == GTK_SELECTION_BROWSE ||
1200 list->selection_mode == GTK_SELECTION_MULTIPLE) && !list->selection)
1202 list->last_focus_child = new_focus_child;
1203 gtk_list_select_child (list, new_focus_child);
1207 if (gtk_widget_get_visible (GTK_WIDGET (list)))
1208 gtk_widget_queue_resize (GTK_WIDGET (list));
1212 gtk_list_child_position (GtkList *list,
1218 g_return_val_if_fail (GTK_IS_LIST (list), -1);
1219 g_return_val_if_fail (child != NULL, -1);
1222 children = list->children;
1226 if (child == GTK_WIDGET (children->data))
1230 children = children->next;
1237 /* Private GtkList Insert/Remove Item Functions:
1239 * gtk_list_remove_items_internal
1242 gtk_list_remove_items_internal (GtkList *list,
1247 GtkWidget *new_focus_child;
1248 GtkWidget *old_focus_child;
1249 GtkContainer *container;
1252 gboolean grab_focus = FALSE;
1254 g_return_if_fail (GTK_IS_LIST (list));
1259 container = GTK_CONTAINER (list);
1261 gtk_list_end_drag_selection (list);
1262 if (list->selection_mode == GTK_SELECTION_MULTIPLE)
1264 if (list->anchor >= 0)
1265 gtk_list_end_selection (list);
1267 gtk_list_reset_extended_selection (list);
1273 widget = tmp_list->data;
1274 tmp_list = tmp_list->next;
1276 if (widget->state == GTK_STATE_SELECTED)
1277 gtk_list_unselect_child (list, widget);
1280 if (container->focus_child)
1282 old_focus_child = new_focus_child = container->focus_child;
1283 if (gtk_widget_has_focus (container->focus_child))
1287 old_focus_child = new_focus_child = list->last_focus_child;
1292 widget = tmp_list->data;
1293 tmp_list = tmp_list->next;
1295 g_object_ref (widget);
1297 g_object_ref (widget);
1299 if (widget == new_focus_child)
1301 work = g_list_find (list->children, widget);
1306 new_focus_child = work->next->data;
1307 else if (list->children != work && work->prev)
1308 new_focus_child = work->prev->data;
1310 new_focus_child = NULL;
1314 gtk_signal_disconnect_by_data (GTK_OBJECT (widget), (gpointer) list);
1315 list->children = g_list_remove (list->children, widget);
1316 gtk_widget_unparent (widget);
1318 if (widget == list->undo_focus_child)
1319 list->undo_focus_child = NULL;
1320 if (widget == list->last_focus_child)
1321 list->last_focus_child = NULL;
1323 g_object_unref (widget);
1326 if (new_focus_child && new_focus_child != old_focus_child)
1329 gtk_widget_grab_focus (new_focus_child);
1330 else if (container->focus_child)
1331 gtk_container_set_focus_child (container, new_focus_child);
1333 if (list->selection_mode == GTK_SELECTION_BROWSE && !list->selection)
1335 list->last_focus_child = new_focus_child;
1336 gtk_list_select_child (list, new_focus_child);
1340 if (gtk_widget_get_visible (GTK_WIDGET (list)))
1341 gtk_widget_queue_resize (GTK_WIDGET (list));
1345 /* Public GtkList Selection Methods :
1347 * gtk_list_set_selection_mode
1348 * gtk_list_select_item
1349 * gtk_list_unselect_item
1350 * gtk_list_select_child
1351 * gtk_list_unselect_child
1352 * gtk_list_select_all
1353 * gtk_list_unselect_all
1354 * gtk_list_extend_selection
1355 * gtk_list_end_drag_selection
1356 * gtk_list_start_selection
1357 * gtk_list_end_selection
1358 * gtk_list_toggle_row
1359 * gtk_list_toggle_focus_row
1360 * gtk_list_toggle_add_mode
1361 * gtk_list_undo_selection
1364 gtk_list_set_selection_mode (GtkList *list,
1365 GtkSelectionMode mode)
1367 g_return_if_fail (GTK_IS_LIST (list));
1369 if (list->selection_mode == mode)
1372 list->selection_mode = mode;
1376 case GTK_SELECTION_SINGLE:
1377 case GTK_SELECTION_BROWSE:
1378 gtk_list_unselect_all (list);
1386 gtk_list_select_item (GtkList *list,
1391 g_return_if_fail (GTK_IS_LIST (list));
1393 tmp_list = g_list_nth (list->children, item);
1395 gtk_list_select_child (list, GTK_WIDGET (tmp_list->data));
1399 gtk_list_unselect_item (GtkList *list,
1404 g_return_if_fail (GTK_IS_LIST (list));
1406 tmp_list = g_list_nth (list->children, item);
1408 gtk_list_unselect_child (list, GTK_WIDGET (tmp_list->data));
1412 gtk_list_select_child (GtkList *list,
1415 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECT_CHILD], child);
1419 gtk_list_unselect_child (GtkList *list,
1422 gtk_signal_emit (GTK_OBJECT (list), list_signals[UNSELECT_CHILD], child);
1426 gtk_list_select_all (GtkList *list)
1428 GtkContainer *container;
1430 g_return_if_fail (GTK_IS_LIST (list));
1432 if (!list->children)
1435 if (list_has_grab (list))
1436 gtk_list_end_drag_selection (list);
1438 if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
1439 gtk_list_end_selection (list);
1441 container = GTK_CONTAINER (list);
1443 switch (list->selection_mode)
1445 case GTK_SELECTION_BROWSE:
1446 if (container->focus_child)
1448 gtk_list_select_child (list, container->focus_child);
1452 case GTK_SELECTION_MULTIPLE:
1453 g_list_free (list->undo_selection);
1454 g_list_free (list->undo_unselection);
1455 list->undo_selection = NULL;
1456 list->undo_unselection = NULL;
1458 if (list->children &&
1459 GTK_WIDGET_STATE (list->children->data) != GTK_STATE_SELECTED)
1460 gtk_list_fake_toggle_row (list, GTK_WIDGET (list->children->data));
1462 list->anchor_state = GTK_STATE_SELECTED;
1465 list->undo_focus_child = container->focus_child;
1466 gtk_list_update_extended_selection (list, g_list_length(list->children));
1467 gtk_list_end_selection (list);
1475 gtk_list_unselect_all (GtkList *list)
1477 GtkContainer *container;
1481 g_return_if_fail (GTK_IS_LIST (list));
1483 if (!list->children)
1486 if (list_has_grab (list))
1487 gtk_list_end_drag_selection (list);
1489 if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
1490 gtk_list_end_selection (list);
1492 container = GTK_CONTAINER (list);
1494 switch (list->selection_mode)
1496 case GTK_SELECTION_BROWSE:
1497 if (container->focus_child)
1499 gtk_list_select_child (list, container->focus_child);
1503 case GTK_SELECTION_MULTIPLE:
1504 gtk_list_reset_extended_selection (list);
1510 work = list->selection;
1516 gtk_list_unselect_child (list, item);
1521 gtk_list_extend_selection (GtkList *list,
1522 GtkScrollType scroll_type,
1524 gboolean auto_start_selection)
1526 GtkContainer *container;
1528 g_return_if_fail (GTK_IS_LIST (list));
1530 if (list_has_grab (list) ||
1531 list->selection_mode != GTK_SELECTION_MULTIPLE)
1534 container = GTK_CONTAINER (list);
1536 if (auto_start_selection)
1540 focus_row = g_list_index (list->children, container->focus_child);
1541 gtk_list_set_anchor (list, list->add_mode, focus_row,
1542 container->focus_child);
1544 else if (list->anchor < 0)
1547 gtk_list_move_focus_child (list, scroll_type, position);
1548 gtk_list_update_extended_selection
1549 (list, g_list_index (list->children, container->focus_child));
1553 gtk_list_end_drag_selection (GtkList *list)
1555 g_return_if_fail (GTK_IS_LIST (list));
1557 list->drag_selection = FALSE;
1558 if (GTK_WIDGET_HAS_GRAB (list))
1559 gtk_grab_remove (GTK_WIDGET (list));
1563 g_source_remove (list->htimer);
1568 g_source_remove (list->vtimer);
1574 gtk_list_start_selection (GtkList *list)
1576 GtkContainer *container;
1579 g_return_if_fail (GTK_IS_LIST (list));
1581 if (list_has_grab (list))
1584 container = GTK_CONTAINER (list);
1586 if ((focus_row = g_list_index (list->selection, container->focus_child))
1588 gtk_list_set_anchor (list, list->add_mode,
1589 focus_row, container->focus_child);
1593 gtk_list_end_selection (GtkList *list)
1602 g_return_if_fail (GTK_IS_LIST (list));
1604 if (list_has_grab (list) || list->anchor < 0)
1607 i = MIN (list->anchor, list->drag_pos);
1608 e = MAX (list->anchor, list->drag_pos);
1610 top_down = (list->anchor < list->drag_pos);
1613 list->drag_pos = -1;
1615 if (list->undo_selection)
1617 work = list->selection;
1618 list->selection = list->undo_selection;
1619 list->undo_selection = work;
1620 work = list->selection;
1625 item_index = g_list_index (list->children, item);
1626 if (item_index < i || item_index > e)
1628 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1629 gtk_list_unselect_child (list, item);
1630 list->undo_selection = g_list_prepend (list->undo_selection,
1638 for (work = g_list_nth (list->children, i); i <= e;
1639 i++, work = work->next)
1642 if (g_list_find (list->selection, item))
1644 if (item->state == GTK_STATE_NORMAL)
1646 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1647 gtk_list_unselect_child (list, item);
1648 list->undo_selection = g_list_prepend (list->undo_selection,
1652 else if (item->state == GTK_STATE_SELECTED)
1654 gtk_widget_set_state (item, GTK_STATE_NORMAL);
1655 list->undo_unselection = g_list_prepend (list->undo_unselection,
1662 for (work = g_list_nth (list->children, e); i <= e;
1663 e--, work = work->prev)
1666 if (g_list_find (list->selection, item))
1668 if (item->state == GTK_STATE_NORMAL)
1670 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1671 gtk_list_unselect_child (list, item);
1672 list->undo_selection = g_list_prepend (list->undo_selection,
1676 else if (item->state == GTK_STATE_SELECTED)
1678 gtk_widget_set_state (item, GTK_STATE_NORMAL);
1679 list->undo_unselection = g_list_prepend (list->undo_unselection,
1685 for (work = g_list_reverse (list->undo_unselection); work; work = work->next)
1686 gtk_list_select_child (list, GTK_WIDGET (work->data));
1692 gtk_list_toggle_row (GtkList *list,
1695 g_return_if_fail (GTK_IS_LIST (list));
1696 g_return_if_fail (GTK_IS_LIST_ITEM (item));
1698 switch (list->selection_mode)
1700 case GTK_SELECTION_MULTIPLE:
1701 case GTK_SELECTION_SINGLE:
1702 if (item->state == GTK_STATE_SELECTED)
1704 gtk_list_unselect_child (list, item);
1707 case GTK_SELECTION_BROWSE:
1708 gtk_list_select_child (list, item);
1714 gtk_list_toggle_focus_row (GtkList *list)
1716 GtkContainer *container;
1719 g_return_if_fail (list != 0);
1720 g_return_if_fail (GTK_IS_LIST (list));
1722 container = GTK_CONTAINER (list);
1724 if (list_has_grab (list) || !container->focus_child)
1727 switch (list->selection_mode)
1729 case GTK_SELECTION_SINGLE:
1730 gtk_list_toggle_row (list, container->focus_child);
1732 case GTK_SELECTION_MULTIPLE:
1733 if ((focus_row = g_list_index (list->children, container->focus_child))
1737 g_list_free (list->undo_selection);
1738 g_list_free (list->undo_unselection);
1739 list->undo_selection = NULL;
1740 list->undo_unselection = NULL;
1742 list->anchor = focus_row;
1743 list->drag_pos = focus_row;
1744 list->undo_focus_child = container->focus_child;
1747 gtk_list_fake_toggle_row (list, container->focus_child);
1749 gtk_list_fake_unselect_all (list, container->focus_child);
1751 gtk_list_end_selection (list);
1759 gtk_list_toggle_add_mode (GtkList *list)
1761 GtkContainer *container;
1763 g_return_if_fail (list != 0);
1764 g_return_if_fail (GTK_IS_LIST (list));
1766 if (list_has_grab (list) ||
1767 list->selection_mode != GTK_SELECTION_MULTIPLE)
1770 container = GTK_CONTAINER (list);
1774 list->add_mode = FALSE;
1775 list->anchor_state = GTK_STATE_SELECTED;
1778 list->add_mode = TRUE;
1780 if (container->focus_child)
1781 gtk_widget_queue_draw (container->focus_child);
1785 gtk_list_undo_selection (GtkList *list)
1789 g_return_if_fail (GTK_IS_LIST (list));
1791 if (list->selection_mode != GTK_SELECTION_MULTIPLE ||
1792 list_has_grab (list))
1795 if (list->anchor >= 0)
1796 gtk_list_end_selection (list);
1798 if (!(list->undo_selection || list->undo_unselection))
1800 gtk_list_unselect_all (list);
1804 for (work = list->undo_selection; work; work = work->next)
1805 gtk_list_select_child (list, GTK_WIDGET (work->data));
1807 for (work = list->undo_unselection; work; work = work->next)
1808 gtk_list_unselect_child (list, GTK_WIDGET (work->data));
1810 if (list->undo_focus_child)
1812 GtkContainer *container;
1814 container = GTK_CONTAINER (list);
1816 if (container->focus_child &&
1817 gtk_widget_has_focus (container->focus_child))
1818 gtk_widget_grab_focus (list->undo_focus_child);
1820 gtk_container_set_focus_child (container, list->undo_focus_child);
1823 list->undo_focus_child = NULL;
1825 g_list_free (list->undo_selection);
1826 g_list_free (list->undo_unselection);
1827 list->undo_selection = NULL;
1828 list->undo_unselection = NULL;
1832 /* Private GtkList Selection Methods :
1834 * gtk_real_list_select_child
1835 * gtk_real_list_unselect_child
1838 gtk_real_list_select_child (GtkList *list,
1841 g_return_if_fail (GTK_IS_LIST (list));
1842 g_return_if_fail (GTK_IS_LIST_ITEM (child));
1844 switch (child->state)
1846 case GTK_STATE_SELECTED:
1847 case GTK_STATE_INSENSITIVE:
1850 gtk_list_item_select (GTK_LIST_ITEM (child));
1856 gtk_real_list_unselect_child (GtkList *list,
1859 g_return_if_fail (GTK_IS_LIST (list));
1860 g_return_if_fail (GTK_IS_LIST_ITEM (child));
1862 if (child->state == GTK_STATE_SELECTED)
1863 gtk_list_item_deselect (GTK_LIST_ITEM (child));
1867 /* Private GtkList Selection Functions :
1869 * gtk_list_set_anchor
1870 * gtk_list_fake_unselect_all
1871 * gtk_list_fake_toggle_row
1872 * gtk_list_update_extended_selection
1873 * gtk_list_reset_extended_selection
1876 gtk_list_set_anchor (GtkList *list,
1879 GtkWidget *undo_focus_child)
1883 g_return_if_fail (GTK_IS_LIST (list));
1885 if (list->selection_mode != GTK_SELECTION_MULTIPLE || list->anchor >= 0)
1888 g_list_free (list->undo_selection);
1889 g_list_free (list->undo_unselection);
1890 list->undo_selection = NULL;
1891 list->undo_unselection = NULL;
1893 if ((work = g_list_nth (list->children, anchor)))
1896 gtk_list_fake_toggle_row (list, GTK_WIDGET (work->data));
1899 gtk_list_fake_unselect_all (list, GTK_WIDGET (work->data));
1900 list->anchor_state = GTK_STATE_SELECTED;
1904 list->anchor = anchor;
1905 list->drag_pos = anchor;
1906 list->undo_focus_child = undo_focus_child;
1910 gtk_list_fake_unselect_all (GtkList *list,
1915 if (item && item->state == GTK_STATE_NORMAL)
1916 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1918 list->undo_selection = list->selection;
1919 list->selection = NULL;
1921 for (work = list->undo_selection; work; work = work->next)
1922 if (work->data != item)
1923 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL);
1927 gtk_list_fake_toggle_row (GtkList *list,
1933 if (item->state == GTK_STATE_NORMAL)
1935 list->anchor_state = GTK_STATE_SELECTED;
1936 gtk_widget_set_state (item, GTK_STATE_SELECTED);
1940 list->anchor_state = GTK_STATE_NORMAL;
1941 gtk_widget_set_state (item, GTK_STATE_NORMAL);
1946 gtk_list_update_extended_selection (GtkList *list,
1960 length = g_list_length (list->children);
1964 if (list->selection_mode != GTK_SELECTION_MULTIPLE || !list->anchor < 0)
1967 /* extending downwards */
1968 if (row > list->drag_pos && list->anchor <= list->drag_pos)
1970 s2 = list->drag_pos + 1;
1973 /* extending upwards */
1974 else if (row < list->drag_pos && list->anchor >= list->drag_pos)
1977 e2 = list->drag_pos - 1;
1979 else if (row < list->drag_pos && list->anchor < list->drag_pos)
1981 e1 = list->drag_pos;
1982 /* row and drag_pos on different sides of anchor :
1983 take back the selection between anchor and drag_pos,
1984 select between anchor and row */
1985 if (row < list->anchor)
1987 s1 = list->anchor + 1;
1989 e2 = list->anchor - 1;
1991 /* take back the selection between anchor and drag_pos */
1995 else if (row > list->drag_pos && list->anchor > list->drag_pos)
1997 s1 = list->drag_pos;
1998 /* row and drag_pos on different sides of anchor :
1999 take back the selection between anchor and drag_pos,
2000 select between anchor and row */
2001 if (row > list->anchor)
2003 e1 = list->anchor - 1;
2004 s2 = list->anchor + 1;
2007 /* take back the selection between anchor and drag_pos */
2012 list->drag_pos = row;
2014 /* restore the elements between s1 and e1 */
2017 for (i = s1, work = g_list_nth (list->children, i); i <= e1;
2018 i++, work = work->next)
2020 if (g_list_find (list->selection, work->data))
2021 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_SELECTED);
2023 gtk_widget_set_state (GTK_WIDGET (work->data), GTK_STATE_NORMAL);
2027 /* extend the selection between s2 and e2 */
2030 for (i = s2, work = g_list_nth (list->children, i); i <= e2;
2031 i++, work = work->next)
2032 if (GTK_WIDGET (work->data)->state != list->anchor_state)
2033 gtk_widget_set_state (GTK_WIDGET (work->data), list->anchor_state);
2038 gtk_list_reset_extended_selection (GtkList *list)
2040 g_return_if_fail (list != 0);
2041 g_return_if_fail (GTK_IS_LIST (list));
2043 g_list_free (list->undo_selection);
2044 g_list_free (list->undo_unselection);
2045 list->undo_selection = NULL;
2046 list->undo_unselection = NULL;
2049 list->drag_pos = -1;
2050 list->undo_focus_child = GTK_CONTAINER (list)->focus_child;
2053 /* Public GtkList Scroll Methods :
2055 * gtk_list_scroll_horizontal
2056 * gtk_list_scroll_vertical
2059 gtk_list_scroll_horizontal (GtkList *list,
2060 GtkScrollType scroll_type,
2065 g_return_if_fail (list != 0);
2066 g_return_if_fail (GTK_IS_LIST (list));
2068 if (list_has_grab (list))
2072 gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id)))
2075 switch (scroll_type)
2077 case GTK_SCROLL_STEP_UP:
2078 case GTK_SCROLL_STEP_BACKWARD:
2079 adj->value = CLAMP (adj->value - adj->step_increment, adj->lower,
2080 adj->upper - adj->page_size);
2082 case GTK_SCROLL_STEP_DOWN:
2083 case GTK_SCROLL_STEP_FORWARD:
2084 adj->value = CLAMP (adj->value + adj->step_increment, adj->lower,
2085 adj->upper - adj->page_size);
2087 case GTK_SCROLL_PAGE_UP:
2088 case GTK_SCROLL_PAGE_BACKWARD:
2089 adj->value = CLAMP (adj->value - adj->page_increment, adj->lower,
2090 adj->upper - adj->page_size);
2092 case GTK_SCROLL_PAGE_DOWN:
2093 case GTK_SCROLL_PAGE_FORWARD:
2094 adj->value = CLAMP (adj->value + adj->page_increment, adj->lower,
2095 adj->upper - adj->page_size);
2097 case GTK_SCROLL_JUMP:
2098 adj->value = CLAMP (adj->lower + (adj->upper - adj->lower) * position,
2099 adj->lower, adj->upper - adj->page_size);
2104 gtk_adjustment_value_changed (adj);
2108 gtk_list_scroll_vertical (GtkList *list,
2109 GtkScrollType scroll_type,
2112 g_return_if_fail (GTK_IS_LIST (list));
2114 if (list_has_grab (list))
2117 if (list->selection_mode == GTK_SELECTION_MULTIPLE)
2119 GtkContainer *container;
2121 if (list->anchor >= 0)
2124 container = GTK_CONTAINER (list);
2125 list->undo_focus_child = container->focus_child;
2126 gtk_list_move_focus_child (list, scroll_type, position);
2127 if (container->focus_child != list->undo_focus_child && !list->add_mode)
2129 gtk_list_unselect_all (list);
2130 gtk_list_select_child (list, container->focus_child);
2134 gtk_list_move_focus_child (list, scroll_type, position);
2138 /* Private GtkList Scroll/Focus Functions :
2140 * gtk_list_move_focus_child
2141 * gtk_list_horizontal_timeout
2142 * gtk_list_vertical_timeout
2145 gtk_list_move_focus_child (GtkList *list,
2146 GtkScrollType scroll_type,
2149 GtkContainer *container;
2155 g_return_if_fail (list != 0);
2156 g_return_if_fail (GTK_IS_LIST (list));
2158 container = GTK_CONTAINER (list);
2160 if (container->focus_child)
2161 work = g_list_find (list->children, container->focus_child);
2163 work = list->children;
2168 switch (scroll_type)
2170 case GTK_SCROLL_STEP_BACKWARD:
2173 gtk_widget_grab_focus (GTK_WIDGET (work->data));
2175 case GTK_SCROLL_STEP_FORWARD:
2178 gtk_widget_grab_focus (GTK_WIDGET (work->data));
2180 case GTK_SCROLL_PAGE_BACKWARD:
2185 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id);
2189 gboolean correct = FALSE;
2191 new_value = adj->value;
2193 if (item->allocation.y <= adj->value)
2195 new_value = MAX (item->allocation.y + item->allocation.height
2196 - adj->page_size, adj->lower);
2200 if (item->allocation.y > new_value)
2201 for (; work; work = work->prev)
2203 item = GTK_WIDGET (work->data);
2204 if (item->allocation.y <= new_value &&
2205 item->allocation.y + item->allocation.height > new_value)
2209 for (; work; work = work->next)
2211 item = GTK_WIDGET (work->data);
2212 if (item->allocation.y <= new_value &&
2213 item->allocation.y + item->allocation.height > new_value)
2217 if (correct && work && work->next && item->allocation.y < new_value)
2218 item = work->next->data;
2221 item = list->children->data;
2223 gtk_widget_grab_focus (item);
2225 case GTK_SCROLL_PAGE_FORWARD:
2230 adj = gtk_object_get_data_by_id (GTK_OBJECT (list), vadjustment_key_id);
2234 gboolean correct = FALSE;
2236 new_value = adj->value;
2238 if (item->allocation.y + item->allocation.height >=
2239 adj->value + adj->page_size)
2241 new_value = item->allocation.y;
2245 new_value = MIN (new_value + adj->page_size, adj->upper);
2247 if (item->allocation.y > new_value)
2248 for (; work; work = work->prev)
2250 item = GTK_WIDGET (work->data);
2251 if (item->allocation.y <= new_value &&
2252 item->allocation.y + item->allocation.height > new_value)
2256 for (; work; work = work->next)
2258 item = GTK_WIDGET (work->data);
2259 if (item->allocation.y <= new_value &&
2260 item->allocation.y + item->allocation.height > new_value)
2264 if (correct && work && work->prev &&
2265 item->allocation.y + item->allocation.height - 1 > new_value)
2266 item = work->prev->data;
2269 item = g_list_last (work)->data;
2271 gtk_widget_grab_focus (item);
2273 case GTK_SCROLL_JUMP:
2274 new_value = GTK_WIDGET(list)->allocation.height * CLAMP (position, 0, 1);
2276 for (item = NULL, work = list->children; work; work =work->next)
2278 item = GTK_WIDGET (work->data);
2279 if (item->allocation.y <= new_value &&
2280 item->allocation.y + item->allocation.height > new_value)
2284 gtk_widget_grab_focus (item);
2292 do_fake_motion (GtkWidget *list)
2294 GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
2296 event->motion.send_event = TRUE;
2298 gtk_list_motion_notify (list, (GdkEventMotion *)event);
2299 gdk_event_free (event);
2303 gtk_list_horizontal_timeout (GtkWidget *list)
2305 GTK_LIST (list)->htimer = 0;
2306 do_fake_motion (list);
2312 gtk_list_vertical_timeout (GtkWidget *list)
2314 GTK_LIST (list)->vtimer = 0;
2315 do_fake_motion (list);
2321 /* Private GtkListItem Signal Functions :
2323 * gtk_list_signal_toggle_focus_row
2324 * gtk_list_signal_select_all
2325 * gtk_list_signal_unselect_all
2326 * gtk_list_signal_undo_selection
2327 * gtk_list_signal_start_selection
2328 * gtk_list_signal_end_selection
2329 * gtk_list_signal_extend_selection
2330 * gtk_list_signal_scroll_horizontal
2331 * gtk_list_signal_scroll_vertical
2332 * gtk_list_signal_toggle_add_mode
2333 * gtk_list_signal_item_select
2334 * gtk_list_signal_item_deselect
2335 * gtk_list_signal_item_toggle
2338 gtk_list_signal_toggle_focus_row (GtkListItem *list_item,
2341 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2342 g_return_if_fail (GTK_IS_LIST (list));
2344 gtk_list_toggle_focus_row (list);
2348 gtk_list_signal_select_all (GtkListItem *list_item,
2351 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2352 g_return_if_fail (GTK_IS_LIST (list));
2354 gtk_list_select_all (list);
2358 gtk_list_signal_unselect_all (GtkListItem *list_item,
2361 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2362 g_return_if_fail (GTK_IS_LIST (list));
2364 gtk_list_unselect_all (list);
2368 gtk_list_signal_undo_selection (GtkListItem *list_item,
2371 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2372 g_return_if_fail (GTK_IS_LIST (list));
2374 gtk_list_undo_selection (list);
2378 gtk_list_signal_start_selection (GtkListItem *list_item,
2381 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2382 g_return_if_fail (GTK_IS_LIST (list));
2384 gtk_list_start_selection (list);
2388 gtk_list_signal_end_selection (GtkListItem *list_item,
2391 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2392 g_return_if_fail (GTK_IS_LIST (list));
2394 gtk_list_end_selection (list);
2398 gtk_list_signal_extend_selection (GtkListItem *list_item,
2399 GtkScrollType scroll_type,
2401 gboolean auto_start_selection,
2404 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2405 g_return_if_fail (GTK_IS_LIST (list));
2407 gtk_list_extend_selection (list, scroll_type, position,
2408 auto_start_selection);
2412 gtk_list_signal_scroll_horizontal (GtkListItem *list_item,
2413 GtkScrollType scroll_type,
2417 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2418 g_return_if_fail (GTK_IS_LIST (list));
2420 gtk_list_scroll_horizontal (list, scroll_type, position);
2424 gtk_list_signal_scroll_vertical (GtkListItem *list_item,
2425 GtkScrollType scroll_type,
2429 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2430 g_return_if_fail (GTK_IS_LIST (list));
2432 gtk_list_scroll_vertical (list, scroll_type, position);
2436 gtk_list_signal_toggle_add_mode (GtkListItem *list_item,
2439 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2440 g_return_if_fail (GTK_IS_LIST (list));
2442 gtk_list_toggle_add_mode (list);
2446 gtk_list_signal_item_select (GtkListItem *list_item,
2453 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2454 g_return_if_fail (GTK_IS_LIST (list));
2456 if (GTK_WIDGET (list_item)->state != GTK_STATE_SELECTED)
2459 switch (list->selection_mode)
2461 case GTK_SELECTION_SINGLE:
2462 case GTK_SELECTION_BROWSE:
2464 selection = list->selection;
2468 tmp_list = selection;
2469 selection = selection->next;
2471 if (tmp_list->data == list_item)
2472 sel_list = tmp_list;
2474 gtk_list_item_deselect (GTK_LIST_ITEM (tmp_list->data));
2479 list->selection = g_list_prepend (list->selection, list_item);
2480 g_object_ref (list_item);
2482 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
2484 case GTK_SELECTION_MULTIPLE:
2485 if (list->anchor >= 0)
2491 gtk_list_signal_item_deselect (GtkListItem *list_item,
2496 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2497 g_return_if_fail (GTK_IS_LIST (list));
2499 if (GTK_WIDGET (list_item)->state != GTK_STATE_NORMAL)
2502 node = g_list_find (list->selection, list_item);
2506 list->selection = g_list_remove_link (list->selection, node);
2507 g_list_free_1 (node);
2508 g_object_unref (list_item);
2509 gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
2514 gtk_list_signal_item_toggle (GtkListItem *list_item,
2517 g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
2518 g_return_if_fail (GTK_IS_LIST (list));
2520 if ((list->selection_mode == GTK_SELECTION_BROWSE ||
2521 list->selection_mode == GTK_SELECTION_MULTIPLE) &&
2522 GTK_WIDGET (list_item)->state == GTK_STATE_NORMAL)
2524 gtk_widget_set_state (GTK_WIDGET (list_item), GTK_STATE_SELECTED);
2528 switch (GTK_WIDGET (list_item)->state)
2530 case GTK_STATE_SELECTED:
2531 gtk_list_signal_item_select (list_item, list);
2533 case GTK_STATE_NORMAL:
2534 gtk_list_signal_item_deselect (list_item, list);
2542 gtk_list_signal_drag_begin (GtkWidget *widget,
2543 GdkDragContext *context,
2546 g_return_if_fail (GTK_IS_LIST_ITEM (widget));
2547 g_return_if_fail (GTK_IS_LIST (list));
2549 gtk_list_drag_begin (GTK_WIDGET (list), context);
2553 gtk_list_drag_begin (GtkWidget *widget,
2554 GdkDragContext *context)
2558 g_return_if_fail (GTK_IS_LIST (widget));
2559 g_return_if_fail (context != NULL);
2561 list = GTK_LIST (widget);
2563 if (list->drag_selection)
2565 gtk_list_end_drag_selection (list);
2567 switch (list->selection_mode)
2569 case GTK_SELECTION_MULTIPLE:
2570 gtk_list_end_selection (list);
2572 case GTK_SELECTION_SINGLE:
2573 list->undo_focus_child = NULL;
2581 #include "gtkaliasdef.c"