1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald,
3 * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #undef GDK_DISABLE_DEPRECATED
35 #include "gtkbindings.h"
37 #include "gtkmarshalers.h"
38 #include <gdk/gdkkeysyms.h>
40 /* length of button_actions array */
43 /* the number rows memchunk expands at a time */
44 #define CLIST_OPTIMUM_SIZE 64
46 /* the width of the column resize windows */
49 /* minimum allowed width of a column */
50 #define COLUMN_MIN_WIDTH 5
52 /* this defigns the base grid spacing */
53 #define CELL_SPACING 1
55 /* added the horizontal space at the beginning and end of a row*/
56 #define COLUMN_INSET 3
58 /* used for auto-scrolling */
59 #define SCROLL_TIME 100
61 /* gives the top pixel of the given row in context of
62 * the clist's voffset */
63 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
64 (((row) + 1) * CELL_SPACING) + \
67 /* returns the row index from a y pixel location in the
68 * context of the clist's voffset */
69 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
70 ((clist)->row_height + CELL_SPACING))
72 /* gives the left pixel of the given column in context of
73 * the clist's hoffset */
74 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
77 /* returns the column index from a x pixel location in the
78 * context of the clist's hoffset */
80 COLUMN_FROM_XPIXEL (GtkCList * clist,
85 for (i = 0; i < clist->columns; i++)
86 if (clist->column[i].visible)
88 cx = clist->column[i].area.x + clist->hoffset;
90 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
91 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
99 /* returns the top pixel of the given row in the context of
101 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
103 /* returns the left pixel of the given column in the context of
105 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
107 /* returns the total height of the list */
108 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
109 (CELL_SPACING * ((clist)->rows + 1)))
112 /* returns the total width of the list */
114 LIST_WIDTH (GtkCList * clist)
118 for (last_column = clist->columns - 1;
119 last_column >= 0 && !clist->column[last_column].visible; last_column--);
121 if (last_column >= 0)
122 return (clist->column[last_column].area.x +
123 clist->column[last_column].area.width +
124 COLUMN_INSET + CELL_SPACING);
128 /* returns the GList item for the nth row */
129 #define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
130 (clist)->row_list_end : \
131 g_list_nth ((clist)->row_list, (row)))
134 /* redraw the list if it's not frozen */
135 #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
136 #define CLIST_REFRESH(clist) G_STMT_START { \
137 if (CLIST_UNFROZEN (clist)) \
138 GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
180 /* GtkCList Methods */
181 static void gtk_clist_class_init (GtkCListClass *klass);
182 static void gtk_clist_init (GtkCList *clist);
183 static GObject* gtk_clist_constructor (GType type,
184 guint n_construct_properties,
185 GObjectConstructParam *construct_params);
187 /* GtkObject Methods */
188 static void gtk_clist_destroy (GtkObject *object);
189 static void gtk_clist_finalize (GObject *object);
190 static void gtk_clist_set_arg (GtkObject *object,
193 static void gtk_clist_get_arg (GtkObject *object,
197 /* GtkWidget Methods */
198 static void gtk_clist_set_scroll_adjustments (GtkCList *clist,
199 GtkAdjustment *hadjustment,
200 GtkAdjustment *vadjustment);
201 static void gtk_clist_realize (GtkWidget *widget);
202 static void gtk_clist_unrealize (GtkWidget *widget);
203 static void gtk_clist_map (GtkWidget *widget);
204 static void gtk_clist_unmap (GtkWidget *widget);
205 static gint gtk_clist_expose (GtkWidget *widget,
206 GdkEventExpose *event);
207 static gint gtk_clist_button_press (GtkWidget *widget,
208 GdkEventButton *event);
209 static gint gtk_clist_button_release (GtkWidget *widget,
210 GdkEventButton *event);
211 static gint gtk_clist_motion (GtkWidget *widget,
212 GdkEventMotion *event);
213 static void gtk_clist_size_request (GtkWidget *widget,
214 GtkRequisition *requisition);
215 static void gtk_clist_size_allocate (GtkWidget *widget,
216 GtkAllocation *allocation);
217 static void gtk_clist_draw_focus (GtkWidget *widget);
218 static gint gtk_clist_focus_in (GtkWidget *widget,
219 GdkEventFocus *event);
220 static gint gtk_clist_focus_out (GtkWidget *widget,
221 GdkEventFocus *event);
222 static gint gtk_clist_focus (GtkWidget *widget,
223 GtkDirectionType direction);
224 static void gtk_clist_set_focus_child (GtkContainer *container,
226 static void gtk_clist_style_set (GtkWidget *widget,
227 GtkStyle *previous_style);
228 static void gtk_clist_drag_begin (GtkWidget *widget,
229 GdkDragContext *context);
230 static gint gtk_clist_drag_motion (GtkWidget *widget,
231 GdkDragContext *context,
235 static void gtk_clist_drag_leave (GtkWidget *widget,
236 GdkDragContext *context,
238 static void gtk_clist_drag_end (GtkWidget *widget,
239 GdkDragContext *context);
240 static gboolean gtk_clist_drag_drop (GtkWidget *widget,
241 GdkDragContext *context,
245 static void gtk_clist_drag_data_get (GtkWidget *widget,
246 GdkDragContext *context,
247 GtkSelectionData *selection_data,
250 static void gtk_clist_drag_data_received (GtkWidget *widget,
251 GdkDragContext *context,
254 GtkSelectionData *selection_data,
258 /* GtkContainer Methods */
259 static void gtk_clist_forall (GtkContainer *container,
260 gboolean include_internals,
261 GtkCallback callback,
262 gpointer callback_data);
265 static void toggle_row (GtkCList *clist,
269 static void real_select_row (GtkCList *clist,
273 static void real_unselect_row (GtkCList *clist,
277 static void update_extended_selection (GtkCList *clist,
279 static GList *selection_find (GtkCList *clist,
281 GList *row_list_element);
282 static void real_select_all (GtkCList *clist);
283 static void real_unselect_all (GtkCList *clist);
284 static void move_vertical (GtkCList *clist,
287 static void move_horizontal (GtkCList *clist,
289 static void real_undo_selection (GtkCList *clist);
290 static void fake_unselect_all (GtkCList *clist,
292 static void fake_toggle_row (GtkCList *clist,
294 static void resync_selection (GtkCList *clist,
296 static void sync_selection (GtkCList *clist,
299 static void set_anchor (GtkCList *clist,
303 static void start_selection (GtkCList *clist);
304 static void end_selection (GtkCList *clist);
305 static void toggle_add_mode (GtkCList *clist);
306 static void toggle_focus_row (GtkCList *clist);
307 static void extend_selection (GtkCList *clist,
308 GtkScrollType scroll_type,
310 gboolean auto_start_selection);
311 static gint get_selection_info (GtkCList *clist,
318 static void move_focus_row (GtkCList *clist,
319 GtkScrollType scroll_type,
321 static void scroll_horizontal (GtkCList *clist,
322 GtkScrollType scroll_type,
324 static void scroll_vertical (GtkCList *clist,
325 GtkScrollType scroll_type,
327 static void move_horizontal (GtkCList *clist,
329 static void move_vertical (GtkCList *clist,
332 static gint horizontal_timeout (GtkCList *clist);
333 static gint vertical_timeout (GtkCList *clist);
334 static void remove_grab (GtkCList *clist);
338 static void draw_xor_line (GtkCList *clist);
339 static gint new_column_width (GtkCList *clist,
342 static void column_auto_resize (GtkCList *clist,
343 GtkCListRow *clist_row,
346 static void real_resize_column (GtkCList *clist,
349 static void abort_column_resize (GtkCList *clist);
350 static void cell_size_request (GtkCList *clist,
351 GtkCListRow *clist_row,
353 GtkRequisition *requisition);
356 static void column_button_create (GtkCList *clist,
358 static void column_button_clicked (GtkWidget *widget,
362 static void adjust_adjustments (GtkCList *clist,
363 gboolean block_resize);
364 static void vadjustment_changed (GtkAdjustment *adjustment,
366 static void vadjustment_value_changed (GtkAdjustment *adjustment,
368 static void hadjustment_changed (GtkAdjustment *adjustment,
370 static void hadjustment_value_changed (GtkAdjustment *adjustment,
374 static void get_cell_style (GtkCList *clist,
375 GtkCListRow *clist_row,
381 static gint draw_cell_pixmap (GdkWindow *window,
382 GdkRectangle *clip_rectangle,
390 static void draw_row (GtkCList *clist,
393 GtkCListRow *clist_row);
394 static void draw_rows (GtkCList *clist,
396 static void clist_refresh (GtkCList *clist);
397 static void draw_drag_highlight (GtkCList *clist,
398 GtkCListRow *dest_row,
399 gint dest_row_number,
400 GtkCListDragPos drag_pos);
402 /* Size Allocation / Requisition */
403 static void size_allocate_title_buttons (GtkCList *clist);
404 static void size_allocate_columns (GtkCList *clist,
405 gboolean block_resize);
406 static gint list_requisition_width (GtkCList *clist);
408 /* Memory Allocation/Distruction Routines */
409 static GtkCListColumn *columns_new (GtkCList *clist);
410 static void column_title_new (GtkCList *clist,
413 static void columns_delete (GtkCList *clist);
414 static GtkCListRow *row_new (GtkCList *clist);
415 static void row_delete (GtkCList *clist,
416 GtkCListRow *clist_row);
417 static void set_cell_contents (GtkCList *clist,
418 GtkCListRow *clist_row,
425 static gint real_insert_row (GtkCList *clist,
428 static void real_remove_row (GtkCList *clist,
430 static void real_clear (GtkCList *clist);
433 static gint default_compare (GtkCList *clist,
436 static void real_sort_list (GtkCList *clist);
437 static GList *gtk_clist_merge (GtkCList *clist,
440 static GList *gtk_clist_mergesort (GtkCList *clist,
444 static gboolean title_focus_in (GtkCList *clist,
446 static gboolean title_focus_move (GtkCList *clist,
449 static void real_row_move (GtkCList *clist,
452 static gint column_title_passive_func (GtkWidget *widget,
455 static void drag_dest_cell (GtkCList *clist,
458 GtkCListDestInfo *dest_info);
462 static GtkContainerClass *parent_class = NULL;
463 static guint clist_signals[LAST_SIGNAL] = {0};
465 static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
468 gtk_clist_get_type (void)
470 static GtkType clist_type = 0;
474 static const GtkTypeInfo clist_info =
478 sizeof (GtkCListClass),
479 (GtkClassInitFunc) gtk_clist_class_init,
480 (GtkObjectInitFunc) gtk_clist_init,
481 /* reserved_1 */ NULL,
482 /* reserved_2 */ NULL,
483 (GtkClassInitFunc) NULL,
486 clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
493 gtk_clist_class_init (GtkCListClass *klass)
495 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
496 GtkObjectClass *object_class;
497 GtkWidgetClass *widget_class;
498 GtkContainerClass *container_class;
499 GtkBindingSet *binding_set;
501 gobject_class->constructor = gtk_clist_constructor;
503 object_class = (GtkObjectClass *) klass;
504 widget_class = (GtkWidgetClass *) klass;
505 container_class = (GtkContainerClass *) klass;
507 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
509 gobject_class->finalize = gtk_clist_finalize;
511 object_class->set_arg = gtk_clist_set_arg;
512 object_class->get_arg = gtk_clist_get_arg;
513 object_class->destroy = gtk_clist_destroy;
516 widget_class->realize = gtk_clist_realize;
517 widget_class->unrealize = gtk_clist_unrealize;
518 widget_class->map = gtk_clist_map;
519 widget_class->unmap = gtk_clist_unmap;
520 widget_class->button_press_event = gtk_clist_button_press;
521 widget_class->button_release_event = gtk_clist_button_release;
522 widget_class->motion_notify_event = gtk_clist_motion;
523 widget_class->expose_event = gtk_clist_expose;
524 widget_class->size_request = gtk_clist_size_request;
525 widget_class->size_allocate = gtk_clist_size_allocate;
526 widget_class->focus_in_event = gtk_clist_focus_in;
527 widget_class->focus_out_event = gtk_clist_focus_out;
528 widget_class->style_set = gtk_clist_style_set;
529 widget_class->drag_begin = gtk_clist_drag_begin;
530 widget_class->drag_end = gtk_clist_drag_end;
531 widget_class->drag_motion = gtk_clist_drag_motion;
532 widget_class->drag_leave = gtk_clist_drag_leave;
533 widget_class->drag_drop = gtk_clist_drag_drop;
534 widget_class->drag_data_get = gtk_clist_drag_data_get;
535 widget_class->drag_data_received = gtk_clist_drag_data_received;
536 widget_class->focus = gtk_clist_focus;
538 /* container_class->add = NULL; use the default GtkContainerClass warning */
539 /* container_class->remove=NULL; use the default GtkContainerClass warning */
541 container_class->forall = gtk_clist_forall;
542 container_class->set_focus_child = gtk_clist_set_focus_child;
544 klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
545 klass->refresh = clist_refresh;
546 klass->select_row = real_select_row;
547 klass->unselect_row = real_unselect_row;
548 klass->row_move = real_row_move;
549 klass->undo_selection = real_undo_selection;
550 klass->resync_selection = resync_selection;
551 klass->selection_find = selection_find;
552 klass->click_column = NULL;
553 klass->resize_column = real_resize_column;
554 klass->draw_row = draw_row;
555 klass->draw_drag_highlight = draw_drag_highlight;
556 klass->insert_row = real_insert_row;
557 klass->remove_row = real_remove_row;
558 klass->clear = real_clear;
559 klass->sort_list = real_sort_list;
560 klass->select_all = real_select_all;
561 klass->unselect_all = real_unselect_all;
562 klass->fake_unselect_all = fake_unselect_all;
563 klass->scroll_horizontal = scroll_horizontal;
564 klass->scroll_vertical = scroll_vertical;
565 klass->extend_selection = extend_selection;
566 klass->toggle_focus_row = toggle_focus_row;
567 klass->toggle_add_mode = toggle_add_mode;
568 klass->start_selection = start_selection;
569 klass->end_selection = end_selection;
570 klass->abort_column_resize = abort_column_resize;
571 klass->set_cell_contents = set_cell_contents;
572 klass->cell_size_request = cell_size_request;
574 gtk_object_add_arg_type ("GtkCList::n_columns",
576 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
578 gtk_object_add_arg_type ("GtkCList::shadow_type",
579 GTK_TYPE_SHADOW_TYPE,
582 gtk_object_add_arg_type ("GtkCList::selection_mode",
583 GTK_TYPE_SELECTION_MODE,
586 gtk_object_add_arg_type ("GtkCList::row_height",
590 gtk_object_add_arg_type ("GtkCList::reorderable",
594 gtk_object_add_arg_type ("GtkCList::titles_active",
598 gtk_object_add_arg_type ("GtkCList::use_drag_icons",
602 gtk_object_add_arg_type ("GtkCList::sort_type",
607 widget_class->set_scroll_adjustments_signal =
608 gtk_signal_new ("set_scroll_adjustments",
610 GTK_CLASS_TYPE (object_class),
611 GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
612 _gtk_marshal_VOID__OBJECT_OBJECT,
613 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
615 clist_signals[SELECT_ROW] =
616 gtk_signal_new ("select_row",
618 GTK_CLASS_TYPE (object_class),
619 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
620 _gtk_marshal_VOID__INT_INT_BOXED,
624 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
625 clist_signals[UNSELECT_ROW] =
626 gtk_signal_new ("unselect_row",
628 GTK_CLASS_TYPE (object_class),
629 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
630 _gtk_marshal_VOID__INT_INT_BOXED,
631 GTK_TYPE_NONE, 3, GTK_TYPE_INT,
632 GTK_TYPE_INT, GDK_TYPE_EVENT);
633 clist_signals[ROW_MOVE] =
634 gtk_signal_new ("row_move",
636 GTK_CLASS_TYPE (object_class),
637 GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
638 _gtk_marshal_VOID__INT_INT,
639 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
640 clist_signals[CLICK_COLUMN] =
641 gtk_signal_new ("click_column",
643 GTK_CLASS_TYPE (object_class),
644 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
645 _gtk_marshal_VOID__INT,
646 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
647 clist_signals[RESIZE_COLUMN] =
648 gtk_signal_new ("resize_column",
650 GTK_CLASS_TYPE (object_class),
651 GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
652 _gtk_marshal_VOID__INT_INT,
653 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
655 clist_signals[TOGGLE_FOCUS_ROW] =
656 gtk_signal_new ("toggle_focus_row",
657 GTK_RUN_LAST | GTK_RUN_ACTION,
658 GTK_CLASS_TYPE (object_class),
659 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
660 _gtk_marshal_VOID__VOID,
662 clist_signals[SELECT_ALL] =
663 gtk_signal_new ("select_all",
664 GTK_RUN_LAST | GTK_RUN_ACTION,
665 GTK_CLASS_TYPE (object_class),
666 GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
667 _gtk_marshal_VOID__VOID,
669 clist_signals[UNSELECT_ALL] =
670 gtk_signal_new ("unselect_all",
671 GTK_RUN_LAST | GTK_RUN_ACTION,
672 GTK_CLASS_TYPE (object_class),
673 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
674 _gtk_marshal_VOID__VOID,
676 clist_signals[UNDO_SELECTION] =
677 gtk_signal_new ("undo_selection",
678 GTK_RUN_LAST | GTK_RUN_ACTION,
679 GTK_CLASS_TYPE (object_class),
680 GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
681 _gtk_marshal_VOID__VOID,
683 clist_signals[START_SELECTION] =
684 gtk_signal_new ("start_selection",
685 GTK_RUN_LAST | GTK_RUN_ACTION,
686 GTK_CLASS_TYPE (object_class),
687 GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
688 _gtk_marshal_VOID__VOID,
690 clist_signals[END_SELECTION] =
691 gtk_signal_new ("end_selection",
692 GTK_RUN_LAST | GTK_RUN_ACTION,
693 GTK_CLASS_TYPE (object_class),
694 GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
695 _gtk_marshal_VOID__VOID,
697 clist_signals[TOGGLE_ADD_MODE] =
698 gtk_signal_new ("toggle_add_mode",
699 GTK_RUN_LAST | GTK_RUN_ACTION,
700 GTK_CLASS_TYPE (object_class),
701 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
702 _gtk_marshal_VOID__VOID,
704 clist_signals[EXTEND_SELECTION] =
705 gtk_signal_new ("extend_selection",
706 GTK_RUN_LAST | GTK_RUN_ACTION,
707 GTK_CLASS_TYPE (object_class),
708 GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
709 _gtk_marshal_VOID__ENUM_FLOAT_BOOLEAN,
711 GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
712 clist_signals[SCROLL_VERTICAL] =
713 gtk_signal_new ("scroll_vertical",
714 GTK_RUN_LAST | GTK_RUN_ACTION,
715 GTK_CLASS_TYPE (object_class),
716 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
717 _gtk_marshal_VOID__ENUM_FLOAT,
718 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
719 clist_signals[SCROLL_HORIZONTAL] =
720 gtk_signal_new ("scroll_horizontal",
721 GTK_RUN_LAST | GTK_RUN_ACTION,
722 GTK_CLASS_TYPE (object_class),
723 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
724 _gtk_marshal_VOID__ENUM_FLOAT,
725 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
726 clist_signals[ABORT_COLUMN_RESIZE] =
727 gtk_signal_new ("abort_column_resize",
728 GTK_RUN_LAST | GTK_RUN_ACTION,
729 GTK_CLASS_TYPE (object_class),
730 GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
731 _gtk_marshal_VOID__VOID,
734 binding_set = gtk_binding_set_by_class (klass);
735 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
736 "scroll_vertical", 2,
737 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
738 GTK_TYPE_FLOAT, 0.0);
739 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
740 "scroll_vertical", 2,
741 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
742 GTK_TYPE_FLOAT, 0.0);
743 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
744 "scroll_vertical", 2,
745 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
746 GTK_TYPE_FLOAT, 0.0);
747 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
748 "scroll_vertical", 2,
749 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
750 GTK_TYPE_FLOAT, 0.0);
751 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
752 "scroll_vertical", 2,
753 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
754 GTK_TYPE_FLOAT, 0.0);
755 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
756 "scroll_vertical", 2,
757 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
758 GTK_TYPE_FLOAT, 0.0);
759 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
760 "scroll_vertical", 2,
761 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
762 GTK_TYPE_FLOAT, 0.0);
763 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
764 "scroll_vertical", 2,
765 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
766 GTK_TYPE_FLOAT, 0.0);
767 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
768 "scroll_vertical", 2,
769 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
770 GTK_TYPE_FLOAT, 0.0);
771 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
772 "scroll_vertical", 2,
773 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
774 GTK_TYPE_FLOAT, 0.0);
775 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
776 "scroll_vertical", 2,
777 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
778 GTK_TYPE_FLOAT, 1.0);
779 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
780 "scroll_vertical", 2,
781 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
782 GTK_TYPE_FLOAT, 1.0);
784 gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
785 "extend_selection", 3,
786 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
787 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
788 gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, GDK_SHIFT_MASK,
789 "extend_selection", 3,
790 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
791 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
792 gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
793 "extend_selection", 3,
794 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
795 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
796 gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, GDK_SHIFT_MASK,
797 "extend_selection", 3,
798 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
799 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
800 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
801 "extend_selection", 3,
802 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
803 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
804 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_SHIFT_MASK,
805 "extend_selection", 3,
806 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
807 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
808 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
809 "extend_selection", 3,
810 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
811 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
812 gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_SHIFT_MASK,
813 "extend_selection", 3,
814 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
815 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
816 gtk_binding_entry_add_signal (binding_set, GDK_Home,
817 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
818 "extend_selection", 3,
819 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
820 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
821 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home,
822 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
823 "extend_selection", 3,
824 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
825 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
826 gtk_binding_entry_add_signal (binding_set, GDK_End,
827 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
828 "extend_selection", 3,
829 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
830 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
831 gtk_binding_entry_add_signal (binding_set, GDK_KP_End,
832 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
833 "extend_selection", 3,
834 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
835 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
838 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
839 "scroll_horizontal", 2,
840 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
841 GTK_TYPE_FLOAT, 0.0);
842 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
843 "scroll_horizontal", 2,
844 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
845 GTK_TYPE_FLOAT, 0.0);
847 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
848 "scroll_horizontal", 2,
849 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
850 GTK_TYPE_FLOAT, 0.0);
851 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
852 "scroll_horizontal", 2,
853 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
854 GTK_TYPE_FLOAT, 0.0);
856 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
857 "scroll_horizontal", 2,
858 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
859 GTK_TYPE_FLOAT, 0.0);
860 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
861 "scroll_horizontal", 2,
862 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
863 GTK_TYPE_FLOAT, 0.0);
865 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
866 "scroll_horizontal", 2,
867 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
868 GTK_TYPE_FLOAT, 1.0);
869 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
870 "scroll_horizontal", 2,
871 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
872 GTK_TYPE_FLOAT, 1.0);
875 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
876 "undo_selection", 0);
877 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
878 "abort_column_resize", 0);
879 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
880 "toggle_focus_row", 0);
881 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
882 "toggle_focus_row", 0);
883 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
884 "toggle_add_mode", 0);
885 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
886 "toggle_add_mode", 0);
887 gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
889 gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, GDK_CONTROL_MASK,
891 gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
893 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
894 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
896 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
897 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
899 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
900 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
903 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
904 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
910 gtk_clist_set_arg (GtkObject *object,
916 clist = GTK_CLIST (object);
920 case ARG_N_COLUMNS: /* only set at construction time */
921 clist->columns = MAX (1, GTK_VALUE_UINT (*arg));
923 case ARG_SHADOW_TYPE:
924 gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
926 case ARG_SELECTION_MODE:
927 gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
930 gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
932 case ARG_REORDERABLE:
933 gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
935 case ARG_TITLES_ACTIVE:
936 if (GTK_VALUE_BOOL (*arg))
937 gtk_clist_column_titles_active (clist);
939 gtk_clist_column_titles_passive (clist);
941 case ARG_USE_DRAG_ICONS:
942 gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
945 gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
951 gtk_clist_get_arg (GtkObject *object,
957 clist = GTK_CLIST (object);
964 GTK_VALUE_UINT (*arg) = clist->columns;
966 case ARG_SHADOW_TYPE:
967 GTK_VALUE_ENUM (*arg) = clist->shadow_type;
969 case ARG_SELECTION_MODE:
970 GTK_VALUE_ENUM (*arg) = clist->selection_mode;
973 GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
975 case ARG_REORDERABLE:
976 GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
978 case ARG_TITLES_ACTIVE:
979 GTK_VALUE_BOOL (*arg) = TRUE;
980 for (i = 0; i < clist->columns; i++)
981 if (clist->column[i].button &&
982 !GTK_WIDGET_SENSITIVE (clist->column[i].button))
984 GTK_VALUE_BOOL (*arg) = FALSE;
988 case ARG_USE_DRAG_ICONS:
989 GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
992 GTK_VALUE_ENUM (*arg) = clist->sort_type;
995 arg->type = GTK_TYPE_INVALID;
1001 gtk_clist_init (GtkCList *clist)
1005 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
1006 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
1007 GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
1008 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
1010 clist->row_mem_chunk = NULL;
1011 clist->cell_mem_chunk = NULL;
1013 clist->freeze_count = 0;
1016 clist->row_height = 0;
1017 clist->row_list = NULL;
1018 clist->row_list_end = NULL;
1022 clist->title_window = NULL;
1023 clist->column_title_area.x = 0;
1024 clist->column_title_area.y = 0;
1025 clist->column_title_area.width = 1;
1026 clist->column_title_area.height = 1;
1028 clist->clist_window = NULL;
1029 clist->clist_window_width = 1;
1030 clist->clist_window_height = 1;
1035 clist->shadow_type = GTK_SHADOW_IN;
1036 clist->vadjustment = NULL;
1037 clist->hadjustment = NULL;
1039 clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
1040 clist->button_actions[1] = GTK_BUTTON_IGNORED;
1041 clist->button_actions[2] = GTK_BUTTON_IGNORED;
1042 clist->button_actions[3] = GTK_BUTTON_IGNORED;
1043 clist->button_actions[4] = GTK_BUTTON_IGNORED;
1045 clist->cursor_drag = NULL;
1046 clist->xor_gc = NULL;
1047 clist->fg_gc = NULL;
1048 clist->bg_gc = NULL;
1051 clist->selection_mode = GTK_SELECTION_SINGLE;
1052 clist->selection = NULL;
1053 clist->selection_end = NULL;
1054 clist->undo_selection = NULL;
1055 clist->undo_unselection = NULL;
1057 clist->focus_row = -1;
1058 clist->focus_header_column = -1;
1059 clist->undo_anchor = -1;
1062 clist->anchor_state = GTK_STATE_SELECTED;
1063 clist->drag_pos = -1;
1067 clist->click_cell.row = -1;
1068 clist->click_cell.column = -1;
1070 clist->compare = default_compare;
1071 clist->sort_type = GTK_SORT_ASCENDING;
1072 clist->sort_column = 0;
1074 clist->drag_highlight_row = -1;
1079 gtk_clist_constructor (GType type,
1080 guint n_construct_properties,
1081 GObjectConstructParam *construct_properties)
1083 GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
1084 n_construct_properties,
1085 construct_properties);
1086 GtkCList *clist = GTK_CLIST (object);
1088 /* initalize memory chunks, if this has not been done by any
1089 * possibly derived widget
1091 if (!clist->row_mem_chunk)
1092 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
1093 sizeof (GtkCListRow),
1094 sizeof (GtkCListRow) *
1098 if (!clist->cell_mem_chunk)
1099 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
1100 sizeof (GtkCell) * clist->columns,
1101 sizeof (GtkCell) * clist->columns *
1105 /* allocate memory for columns */
1106 clist->column = columns_new (clist);
1108 /* there needs to be at least one column button
1109 * because there is alot of code that will break if it
1112 column_button_create (clist, 0);
1117 /* GTKCLIST PUBLIC INTERFACE
1119 * gtk_clist_new_with_titles
1120 * gtk_clist_set_hadjustment
1121 * gtk_clist_set_vadjustment
1122 * gtk_clist_get_hadjustment
1123 * gtk_clist_get_vadjustment
1124 * gtk_clist_set_shadow_type
1125 * gtk_clist_set_selection_mode
1130 gtk_clist_new (gint columns)
1132 return gtk_clist_new_with_titles (columns, NULL);
1136 gtk_clist_new_with_titles (gint columns,
1141 clist = g_object_new (GTK_TYPE_CLIST,
1142 "n_columns", columns,
1148 for (i = 0; i < clist->columns; i++)
1149 gtk_clist_set_column_title (clist, i, titles[i]);
1150 gtk_clist_column_titles_show (clist);
1153 gtk_clist_column_titles_hide (clist);
1155 return GTK_WIDGET (clist);
1159 gtk_clist_set_hadjustment (GtkCList *clist,
1160 GtkAdjustment *adjustment)
1162 GtkAdjustment *old_adjustment;
1164 g_return_if_fail (GTK_IS_CLIST (clist));
1166 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1168 if (clist->hadjustment == adjustment)
1171 old_adjustment = clist->hadjustment;
1173 if (clist->hadjustment)
1175 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
1176 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
1179 clist->hadjustment = adjustment;
1181 if (clist->hadjustment)
1183 gtk_object_ref (GTK_OBJECT (clist->hadjustment));
1184 gtk_object_sink (GTK_OBJECT (clist->hadjustment));
1186 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
1187 (GtkSignalFunc) hadjustment_changed,
1189 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
1190 (GtkSignalFunc) hadjustment_value_changed,
1194 if (!clist->hadjustment || !old_adjustment)
1195 gtk_widget_queue_resize (GTK_WIDGET (clist));
1199 gtk_clist_get_hadjustment (GtkCList *clist)
1201 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1203 return clist->hadjustment;
1207 gtk_clist_set_vadjustment (GtkCList *clist,
1208 GtkAdjustment *adjustment)
1210 GtkAdjustment *old_adjustment;
1212 g_return_if_fail (GTK_IS_CLIST (clist));
1214 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1216 if (clist->vadjustment == adjustment)
1219 old_adjustment = clist->vadjustment;
1221 if (clist->vadjustment)
1223 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
1224 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
1227 clist->vadjustment = adjustment;
1229 if (clist->vadjustment)
1231 gtk_object_ref (GTK_OBJECT (clist->vadjustment));
1232 gtk_object_sink (GTK_OBJECT (clist->vadjustment));
1234 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
1235 (GtkSignalFunc) vadjustment_changed,
1237 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
1238 (GtkSignalFunc) vadjustment_value_changed,
1242 if (!clist->vadjustment || !old_adjustment)
1243 gtk_widget_queue_resize (GTK_WIDGET (clist));
1247 gtk_clist_get_vadjustment (GtkCList *clist)
1249 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1251 return clist->vadjustment;
1255 gtk_clist_set_scroll_adjustments (GtkCList *clist,
1256 GtkAdjustment *hadjustment,
1257 GtkAdjustment *vadjustment)
1259 if (clist->hadjustment != hadjustment)
1260 gtk_clist_set_hadjustment (clist, hadjustment);
1261 if (clist->vadjustment != vadjustment)
1262 gtk_clist_set_vadjustment (clist, vadjustment);
1266 gtk_clist_set_shadow_type (GtkCList *clist,
1269 g_return_if_fail (GTK_IS_CLIST (clist));
1271 clist->shadow_type = type;
1273 if (GTK_WIDGET_VISIBLE (clist))
1274 gtk_widget_queue_resize (GTK_WIDGET (clist));
1278 gtk_clist_set_selection_mode (GtkCList *clist,
1279 GtkSelectionMode mode)
1281 g_return_if_fail (GTK_IS_CLIST (clist));
1282 g_return_if_fail (mode != GTK_SELECTION_NONE);
1284 if (mode == clist->selection_mode)
1287 clist->selection_mode = mode;
1289 clist->anchor_state = GTK_STATE_SELECTED;
1290 clist->drag_pos = -1;
1291 clist->undo_anchor = clist->focus_row;
1293 g_list_free (clist->undo_selection);
1294 g_list_free (clist->undo_unselection);
1295 clist->undo_selection = NULL;
1296 clist->undo_unselection = NULL;
1300 case GTK_SELECTION_MULTIPLE:
1302 case GTK_SELECTION_BROWSE:
1303 case GTK_SELECTION_SINGLE:
1304 gtk_clist_unselect_all (clist);
1307 /* Someone set it by hand */
1308 g_assert_not_reached ();
1313 gtk_clist_freeze (GtkCList *clist)
1315 g_return_if_fail (GTK_IS_CLIST (clist));
1317 clist->freeze_count++;
1321 gtk_clist_thaw (GtkCList *clist)
1323 g_return_if_fail (GTK_IS_CLIST (clist));
1325 if (clist->freeze_count)
1327 clist->freeze_count--;
1328 CLIST_REFRESH (clist);
1332 /* PUBLIC COLUMN FUNCTIONS
1333 * gtk_clist_column_titles_show
1334 * gtk_clist_column_titles_hide
1335 * gtk_clist_column_title_active
1336 * gtk_clist_column_title_passive
1337 * gtk_clist_column_titles_active
1338 * gtk_clist_column_titles_passive
1339 * gtk_clist_set_column_title
1340 * gtk_clist_get_column_title
1341 * gtk_clist_set_column_widget
1342 * gtk_clist_set_column_justification
1343 * gtk_clist_set_column_visibility
1344 * gtk_clist_set_column_resizeable
1345 * gtk_clist_set_column_auto_resize
1346 * gtk_clist_optimal_column_width
1347 * gtk_clist_set_column_width
1348 * gtk_clist_set_column_min_width
1349 * gtk_clist_set_column_max_width
1352 gtk_clist_column_titles_show (GtkCList *clist)
1354 g_return_if_fail (GTK_IS_CLIST (clist));
1356 if (!GTK_CLIST_SHOW_TITLES(clist))
1358 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1359 if (clist->title_window)
1360 gdk_window_show (clist->title_window);
1361 gtk_widget_queue_resize (GTK_WIDGET (clist));
1366 gtk_clist_column_titles_hide (GtkCList *clist)
1368 g_return_if_fail (GTK_IS_CLIST (clist));
1370 if (GTK_CLIST_SHOW_TITLES(clist))
1372 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1373 if (clist->title_window)
1374 gdk_window_hide (clist->title_window);
1375 gtk_widget_queue_resize (GTK_WIDGET (clist));
1380 gtk_clist_column_title_active (GtkCList *clist,
1383 g_return_if_fail (GTK_IS_CLIST (clist));
1385 if (column < 0 || column >= clist->columns)
1387 if (!clist->column[column].button || !clist->column[column].button_passive)
1390 clist->column[column].button_passive = FALSE;
1392 gtk_signal_disconnect_by_func (GTK_OBJECT (clist->column[column].button),
1393 (GtkSignalFunc) column_title_passive_func,
1396 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
1397 if (GTK_WIDGET_VISIBLE (clist))
1398 gtk_widget_queue_draw (clist->column[column].button);
1402 gtk_clist_column_title_passive (GtkCList *clist,
1407 g_return_if_fail (GTK_IS_CLIST (clist));
1409 if (column < 0 || column >= clist->columns)
1411 if (!clist->column[column].button || clist->column[column].button_passive)
1414 button = GTK_BUTTON (clist->column[column].button);
1416 clist->column[column].button_passive = TRUE;
1418 if (button->button_down)
1419 gtk_button_released (button);
1420 if (button->in_button)
1421 gtk_button_leave (button);
1423 gtk_signal_connect (GTK_OBJECT (clist->column[column].button), "event",
1424 (GtkSignalFunc) column_title_passive_func, NULL);
1426 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
1427 if (GTK_WIDGET_VISIBLE (clist))
1428 gtk_widget_queue_draw (clist->column[column].button);
1432 gtk_clist_column_titles_active (GtkCList *clist)
1436 g_return_if_fail (GTK_IS_CLIST (clist));
1438 for (i = 0; i < clist->columns; i++)
1439 gtk_clist_column_title_active (clist, i);
1443 gtk_clist_column_titles_passive (GtkCList *clist)
1447 g_return_if_fail (GTK_IS_CLIST (clist));
1449 for (i = 0; i < clist->columns; i++)
1450 gtk_clist_column_title_passive (clist, i);
1454 gtk_clist_set_column_title (GtkCList *clist,
1458 gint new_button = 0;
1459 GtkWidget *old_widget;
1460 GtkWidget *alignment = NULL;
1463 g_return_if_fail (GTK_IS_CLIST (clist));
1465 if (column < 0 || column >= clist->columns)
1468 /* if the column button doesn't currently exist,
1469 * it has to be created first */
1470 if (!clist->column[column].button)
1472 column_button_create (clist, column);
1476 column_title_new (clist, column, title);
1478 /* remove and destroy the old widget */
1479 old_widget = GTK_BIN (clist->column[column].button)->child;
1481 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1483 /* create new alignment based no column justification */
1484 switch (clist->column[column].justification)
1486 case GTK_JUSTIFY_LEFT:
1487 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1490 case GTK_JUSTIFY_RIGHT:
1491 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1494 case GTK_JUSTIFY_CENTER:
1495 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1498 case GTK_JUSTIFY_FILL:
1499 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1503 gtk_widget_push_composite_child ();
1504 label = gtk_label_new (clist->column[column].title);
1505 gtk_widget_pop_composite_child ();
1506 gtk_container_add (GTK_CONTAINER (alignment), label);
1507 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1508 gtk_widget_show (label);
1509 gtk_widget_show (alignment);
1511 /* if this button didn't previously exist, then the
1512 * column button positions have to be re-computed */
1513 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1514 size_allocate_title_buttons (clist);
1518 gtk_clist_get_column_title (GtkCList *clist,
1521 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1523 if (column < 0 || column >= clist->columns)
1526 return clist->column[column].title;
1530 gtk_clist_set_column_widget (GtkCList *clist,
1534 gint new_button = 0;
1535 GtkWidget *old_widget;
1537 g_return_if_fail (GTK_IS_CLIST (clist));
1539 if (column < 0 || column >= clist->columns)
1542 /* if the column button doesn't currently exist,
1543 * it has to be created first */
1544 if (!clist->column[column].button)
1546 column_button_create (clist, column);
1550 column_title_new (clist, column, NULL);
1552 /* remove and destroy the old widget */
1553 old_widget = GTK_BIN (clist->column[column].button)->child;
1555 gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
1558 /* add and show the widget */
1561 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1562 gtk_widget_show (widget);
1565 /* if this button didn't previously exist, then the
1566 * column button positions have to be re-computed */
1567 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1568 size_allocate_title_buttons (clist);
1572 gtk_clist_get_column_widget (GtkCList *clist,
1575 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1577 if (column < 0 || column >= clist->columns)
1580 if (clist->column[column].button)
1581 return GTK_BIN (clist->column[column].button)->child;
1587 gtk_clist_set_column_justification (GtkCList *clist,
1589 GtkJustification justification)
1591 GtkWidget *alignment;
1593 g_return_if_fail (GTK_IS_CLIST (clist));
1595 if (column < 0 || column >= clist->columns)
1598 clist->column[column].justification = justification;
1600 /* change the alinment of the button title if it's not a
1602 if (clist->column[column].title)
1604 alignment = GTK_BIN (clist->column[column].button)->child;
1606 switch (clist->column[column].justification)
1608 case GTK_JUSTIFY_LEFT:
1609 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1612 case GTK_JUSTIFY_RIGHT:
1613 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1616 case GTK_JUSTIFY_CENTER:
1617 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1620 case GTK_JUSTIFY_FILL:
1621 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1629 if (CLIST_UNFROZEN (clist))
1630 draw_rows (clist, NULL);
1634 gtk_clist_set_column_visibility (GtkCList *clist,
1638 g_return_if_fail (GTK_IS_CLIST (clist));
1640 if (column < 0 || column >= clist->columns)
1642 if (clist->column[column].visible == visible)
1645 /* don't hide last visible column */
1649 gint vis_columns = 0;
1651 for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
1652 if (clist->column[i].visible)
1655 if (vis_columns < 2)
1659 clist->column[column].visible = visible;
1661 if (clist->column[column].button)
1664 gtk_widget_show (clist->column[column].button);
1666 gtk_widget_hide (clist->column[column].button);
1669 gtk_widget_queue_resize (GTK_WIDGET(clist));
1673 gtk_clist_set_column_resizeable (GtkCList *clist,
1675 gboolean resizeable)
1677 g_return_if_fail (GTK_IS_CLIST (clist));
1679 if (column < 0 || column >= clist->columns)
1681 if (clist->column[column].resizeable == resizeable)
1684 clist->column[column].resizeable = resizeable;
1686 clist->column[column].auto_resize = FALSE;
1688 if (GTK_WIDGET_VISIBLE (clist))
1689 size_allocate_title_buttons (clist);
1693 gtk_clist_set_column_auto_resize (GtkCList *clist,
1695 gboolean auto_resize)
1697 g_return_if_fail (GTK_IS_CLIST (clist));
1699 if (column < 0 || column >= clist->columns)
1701 if (clist->column[column].auto_resize == auto_resize)
1704 clist->column[column].auto_resize = auto_resize;
1707 clist->column[column].resizeable = FALSE;
1708 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
1712 width = gtk_clist_optimal_column_width (clist, column);
1713 gtk_clist_set_column_width (clist, column, width);
1717 if (GTK_WIDGET_VISIBLE (clist))
1718 size_allocate_title_buttons (clist);
1722 gtk_clist_columns_autosize (GtkCList *clist)
1727 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1729 gtk_clist_freeze (clist);
1731 for (i = 0; i < clist->columns; i++)
1733 gtk_clist_set_column_width (clist, i,
1734 gtk_clist_optimal_column_width (clist, i));
1736 width += clist->column[i].width;
1739 gtk_clist_thaw (clist);
1744 gtk_clist_optimal_column_width (GtkCList *clist,
1747 GtkRequisition requisition;
1751 g_return_val_if_fail (GTK_CLIST (clist), 0);
1753 if (column < 0 || column >= clist->columns)
1756 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1757 width = (clist->column[column].button->requisition.width)
1759 (CELL_SPACING + (2 * COLUMN_INSET)))
1765 for (list = clist->row_list; list; list = list->next)
1767 GTK_CLIST_GET_CLASS (clist)->cell_size_request
1768 (clist, GTK_CLIST_ROW (list), column, &requisition);
1769 width = MAX (width, requisition.width);
1776 gtk_clist_set_column_width (GtkCList *clist,
1780 g_return_if_fail (GTK_IS_CLIST (clist));
1782 if (column < 0 || column >= clist->columns)
1785 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
1790 gtk_clist_set_column_min_width (GtkCList *clist,
1794 g_return_if_fail (GTK_IS_CLIST (clist));
1796 if (column < 0 || column >= clist->columns)
1798 if (clist->column[column].min_width == min_width)
1801 if (clist->column[column].max_width >= 0 &&
1802 clist->column[column].max_width < min_width)
1803 clist->column[column].min_width = clist->column[column].max_width;
1805 clist->column[column].min_width = min_width;
1807 if (clist->column[column].area.width < clist->column[column].min_width)
1808 gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
1812 gtk_clist_set_column_max_width (GtkCList *clist,
1816 g_return_if_fail (GTK_IS_CLIST (clist));
1818 if (column < 0 || column >= clist->columns)
1820 if (clist->column[column].max_width == max_width)
1823 if (clist->column[column].min_width >= 0 && max_width >= 0 &&
1824 clist->column[column].min_width > max_width)
1825 clist->column[column].max_width = clist->column[column].min_width;
1827 clist->column[column].max_width = max_width;
1829 if (clist->column[column].area.width > clist->column[column].max_width)
1830 gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
1833 /* PRIVATE COLUMN FUNCTIONS
1834 * column_auto_resize
1835 * real_resize_column
1836 * abort_column_resize
1837 * size_allocate_title_buttons
1838 * size_allocate_columns
1839 * list_requisition_width
1841 * column_button_create
1842 * column_button_clicked
1843 * column_title_passive_func
1846 column_auto_resize (GtkCList *clist,
1847 GtkCListRow *clist_row,
1851 /* resize column if needed for auto_resize */
1852 GtkRequisition requisition;
1854 if (!clist->column[column].auto_resize ||
1855 GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
1859 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
1860 column, &requisition);
1862 requisition.width = 0;
1864 if (requisition.width > clist->column[column].width)
1865 gtk_clist_set_column_width (clist, column, requisition.width);
1866 else if (requisition.width < old_width &&
1867 old_width == clist->column[column].width)
1872 /* run a "gtk_clist_optimal_column_width" but break, if
1873 * the column doesn't shrink */
1874 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1875 new_width = (clist->column[column].button->requisition.width -
1876 (CELL_SPACING + (2 * COLUMN_INSET)));
1880 for (list = clist->row_list; list; list = list->next)
1882 GTK_CLIST_GET_CLASS (clist)->cell_size_request
1883 (clist, GTK_CLIST_ROW (list), column, &requisition);
1884 new_width = MAX (new_width, requisition.width);
1885 if (new_width == clist->column[column].width)
1888 if (new_width < clist->column[column].width)
1889 gtk_clist_set_column_width
1890 (clist, column, MAX (new_width, clist->column[column].min_width));
1895 real_resize_column (GtkCList *clist,
1899 g_return_if_fail (GTK_IS_CLIST (clist));
1901 if (column < 0 || column >= clist->columns)
1904 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
1905 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
1906 if (clist->column[column].max_width >= 0 &&
1907 width > clist->column[column].max_width)
1908 width = clist->column[column].max_width;
1910 clist->column[column].width = width;
1911 clist->column[column].width_set = TRUE;
1913 /* FIXME: this is quite expensive to do if the widget hasn't
1914 * been size_allocated yet, and pointless. Should
1917 size_allocate_columns (clist, TRUE);
1918 size_allocate_title_buttons (clist);
1920 CLIST_REFRESH (clist);
1924 abort_column_resize (GtkCList *clist)
1926 g_return_if_fail (GTK_IS_CLIST (clist));
1928 if (!GTK_CLIST_IN_DRAG(clist))
1931 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
1932 gtk_grab_remove (GTK_WIDGET (clist));
1933 gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
1935 clist->drag_pos = -1;
1937 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
1938 draw_xor_line (clist);
1940 if (GTK_CLIST_ADD_MODE(clist))
1942 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
1943 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
1948 size_allocate_title_buttons (GtkCList *clist)
1950 GtkAllocation button_allocation;
1952 gint last_button = 0;
1955 if (!GTK_WIDGET_REALIZED (clist))
1958 button_allocation.x = clist->hoffset;
1959 button_allocation.y = 0;
1960 button_allocation.width = 0;
1961 button_allocation.height = clist->column_title_area.height;
1963 /* find last visible column */
1964 for (last_column = clist->columns - 1; last_column >= 0; last_column--)
1965 if (clist->column[last_column].visible)
1968 for (i = 0; i < last_column; i++)
1970 if (!clist->column[i].visible)
1972 last_button = i + 1;
1973 gdk_window_hide (clist->column[i].window);
1977 button_allocation.width += (clist->column[i].area.width +
1978 CELL_SPACING + 2 * COLUMN_INSET);
1980 if (!clist->column[i + 1].button)
1982 gdk_window_hide (clist->column[i].window);
1986 gtk_widget_size_allocate (clist->column[last_button].button,
1987 &button_allocation);
1988 button_allocation.x += button_allocation.width;
1989 button_allocation.width = 0;
1991 if (clist->column[last_button].resizeable)
1993 gdk_window_show (clist->column[last_button].window);
1994 gdk_window_move_resize (clist->column[last_button].window,
1995 button_allocation.x - (DRAG_WIDTH / 2),
1997 clist->column_title_area.height);
2000 gdk_window_hide (clist->column[last_button].window);
2002 last_button = i + 1;
2005 button_allocation.width += (clist->column[last_column].area.width +
2006 2 * (CELL_SPACING + COLUMN_INSET));
2007 gtk_widget_size_allocate (clist->column[last_button].button,
2008 &button_allocation);
2010 if (clist->column[last_button].resizeable)
2012 button_allocation.x += button_allocation.width;
2014 gdk_window_show (clist->column[last_button].window);
2015 gdk_window_move_resize (clist->column[last_button].window,
2016 button_allocation.x - (DRAG_WIDTH / 2),
2017 0, DRAG_WIDTH, clist->column_title_area.height);
2020 gdk_window_hide (clist->column[last_button].window);
2024 size_allocate_columns (GtkCList *clist,
2025 gboolean block_resize)
2027 gint xoffset = CELL_SPACING + COLUMN_INSET;
2031 /* find last visible column and calculate correct column width */
2032 for (last_column = clist->columns - 1;
2033 last_column >= 0 && !clist->column[last_column].visible; last_column--);
2035 if (last_column < 0)
2038 for (i = 0; i <= last_column; i++)
2040 if (!clist->column[i].visible)
2042 clist->column[i].area.x = xoffset;
2043 if (clist->column[i].width_set)
2045 if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
2046 clist->column[i].auto_resize && clist->column[i].button)
2050 width = (clist->column[i].button->requisition.width -
2051 (CELL_SPACING + (2 * COLUMN_INSET)));
2053 if (width > clist->column[i].width)
2054 gtk_clist_set_column_width (clist, i, width);
2057 clist->column[i].area.width = clist->column[i].width;
2058 xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
2060 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2062 clist->column[i].area.width =
2063 clist->column[i].button->requisition.width -
2064 (CELL_SPACING + (2 * COLUMN_INSET));
2065 xoffset += clist->column[i].button->requisition.width;
2069 clist->column[last_column].area.width = clist->column[last_column].area.width
2070 + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
2074 list_requisition_width (GtkCList *clist)
2076 gint width = CELL_SPACING;
2079 for (i = clist->columns - 1; i >= 0; i--)
2081 if (!clist->column[i].visible)
2084 if (clist->column[i].width_set)
2085 width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
2086 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2087 width += clist->column[i].button->requisition.width;
2093 /* this function returns the new width of the column being resized given
2094 * the column and x position of the cursor; the x cursor position is passed
2095 * in as a pointer and automagicly corrected if it's beyond min/max limits */
2097 new_column_width (GtkCList *clist,
2101 gint xthickness = GTK_WIDGET (clist)->style->xthickness;
2107 /* first translate the x position from widget->window
2108 * to clist->clist_window */
2109 cx = *x - xthickness;
2111 for (last_column = clist->columns - 1;
2112 last_column >= 0 && !clist->column[last_column].visible; last_column--);
2114 /* calculate new column width making sure it doesn't end up
2115 * less than the minimum width */
2116 dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
2117 (column < last_column) * CELL_SPACING);
2120 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
2122 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
2124 *x = cx + xthickness;
2126 else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
2127 width > clist->column[column].max_width)
2129 width = clist->column[column].max_width;
2130 cx = dx + clist->column[column].max_width;
2131 *x = cx + xthickness;
2134 if (cx < 0 || cx > clist->clist_window_width)
2141 column_button_create (GtkCList *clist,
2146 gtk_widget_push_composite_child ();
2147 button = clist->column[column].button = gtk_button_new ();
2148 gtk_widget_pop_composite_child ();
2150 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
2151 gtk_widget_set_parent_window (clist->column[column].button,
2152 clist->title_window);
2153 gtk_widget_set_parent (button, GTK_WIDGET (clist));
2155 gtk_signal_connect (GTK_OBJECT (button), "clicked",
2156 (GtkSignalFunc) column_button_clicked,
2158 gtk_widget_show (button);
2162 column_button_clicked (GtkWidget *widget,
2168 g_return_if_fail (widget != NULL);
2169 g_return_if_fail (GTK_IS_CLIST (data));
2171 clist = GTK_CLIST (data);
2173 /* find the column who's button was pressed */
2174 for (i = 0; i < clist->columns; i++)
2175 if (clist->column[i].button == widget)
2178 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
2182 column_title_passive_func (GtkWidget *widget,
2186 g_return_val_if_fail (event != NULL, FALSE);
2188 switch (event->type)
2190 case GDK_MOTION_NOTIFY:
2191 case GDK_BUTTON_PRESS:
2192 case GDK_2BUTTON_PRESS:
2193 case GDK_3BUTTON_PRESS:
2194 case GDK_BUTTON_RELEASE:
2195 case GDK_ENTER_NOTIFY:
2196 case GDK_LEAVE_NOTIFY:
2205 /* PUBLIC CELL FUNCTIONS
2206 * gtk_clist_get_cell_type
2207 * gtk_clist_set_text
2208 * gtk_clist_get_text
2209 * gtk_clist_set_pixmap
2210 * gtk_clist_get_pixmap
2211 * gtk_clist_set_pixtext
2212 * gtk_clist_get_pixtext
2213 * gtk_clist_set_shift
2216 gtk_clist_get_cell_type (GtkCList *clist,
2220 GtkCListRow *clist_row;
2222 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2224 if (row < 0 || row >= clist->rows)
2226 if (column < 0 || column >= clist->columns)
2229 clist_row = ROW_ELEMENT (clist, row)->data;
2231 return clist_row->cell[column].type;
2235 gtk_clist_set_text (GtkCList *clist,
2240 GtkCListRow *clist_row;
2242 g_return_if_fail (GTK_IS_CLIST (clist));
2244 if (row < 0 || row >= clist->rows)
2246 if (column < 0 || column >= clist->columns)
2249 clist_row = ROW_ELEMENT (clist, row)->data;
2251 /* if text is null, then the cell is empty */
2252 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
2253 (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
2255 /* redraw the list if it's not frozen */
2256 if (CLIST_UNFROZEN (clist))
2258 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2259 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
2264 gtk_clist_get_text (GtkCList *clist,
2269 GtkCListRow *clist_row;
2271 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2273 if (row < 0 || row >= clist->rows)
2275 if (column < 0 || column >= clist->columns)
2278 clist_row = ROW_ELEMENT (clist, row)->data;
2280 if (clist_row->cell[column].type != GTK_CELL_TEXT)
2284 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
2290 gtk_clist_set_pixmap (GtkCList *clist,
2296 GtkCListRow *clist_row;
2298 g_return_if_fail (GTK_IS_CLIST (clist));
2300 if (row < 0 || row >= clist->rows)
2302 if (column < 0 || column >= clist->columns)
2305 clist_row = ROW_ELEMENT (clist, row)->data;
2307 gdk_pixmap_ref (pixmap);
2309 if (mask) gdk_pixmap_ref (mask);
2311 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
2312 (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
2314 /* redraw the list if it's not frozen */
2315 if (CLIST_UNFROZEN (clist))
2317 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2318 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
2323 gtk_clist_get_pixmap (GtkCList *clist,
2329 GtkCListRow *clist_row;
2331 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2333 if (row < 0 || row >= clist->rows)
2335 if (column < 0 || column >= clist->columns)
2338 clist_row = ROW_ELEMENT (clist, row)->data;
2340 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
2345 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
2346 /* mask can be NULL */
2347 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
2354 gtk_clist_set_pixtext (GtkCList *clist,
2362 GtkCListRow *clist_row;
2364 g_return_if_fail (GTK_IS_CLIST (clist));
2366 if (row < 0 || row >= clist->rows)
2368 if (column < 0 || column >= clist->columns)
2371 clist_row = ROW_ELEMENT (clist, row)->data;
2373 gdk_pixmap_ref (pixmap);
2374 if (mask) gdk_pixmap_ref (mask);
2375 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
2376 (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
2378 /* redraw the list if it's not frozen */
2379 if (CLIST_UNFROZEN (clist))
2381 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2382 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
2387 gtk_clist_get_pixtext (GtkCList *clist,
2395 GtkCListRow *clist_row;
2397 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2399 if (row < 0 || row >= clist->rows)
2401 if (column < 0 || column >= clist->columns)
2404 clist_row = ROW_ELEMENT (clist, row)->data;
2406 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
2410 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
2412 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2414 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
2416 /* mask can be NULL */
2418 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
2424 gtk_clist_set_shift (GtkCList *clist,
2430 GtkRequisition requisition = { 0 };
2431 GtkCListRow *clist_row;
2433 g_return_if_fail (GTK_IS_CLIST (clist));
2435 if (row < 0 || row >= clist->rows)
2437 if (column < 0 || column >= clist->columns)
2440 clist_row = ROW_ELEMENT (clist, row)->data;
2442 if (clist->column[column].auto_resize &&
2443 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2444 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
2445 column, &requisition);
2447 clist_row->cell[column].vertical = vertical;
2448 clist_row->cell[column].horizontal = horizontal;
2450 column_auto_resize (clist, clist_row, column, requisition.width);
2452 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2453 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
2456 /* PRIVATE CELL FUNCTIONS
2461 set_cell_contents (GtkCList *clist,
2462 GtkCListRow *clist_row,
2470 GtkRequisition requisition;
2471 gchar *old_text = NULL;
2472 GdkPixmap *old_pixmap = NULL;
2473 GdkBitmap *old_mask = NULL;
2475 g_return_if_fail (GTK_IS_CLIST (clist));
2476 g_return_if_fail (clist_row != NULL);
2478 if (clist->column[column].auto_resize &&
2479 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2480 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
2481 column, &requisition);
2483 switch (clist_row->cell[column].type)
2485 case GTK_CELL_EMPTY:
2488 old_text = GTK_CELL_TEXT (clist_row->cell[column])->text;
2490 case GTK_CELL_PIXMAP:
2491 old_pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
2492 old_mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
2494 case GTK_CELL_PIXTEXT:
2495 old_text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
2496 old_pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
2497 old_mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
2499 case GTK_CELL_WIDGET:
2506 clist_row->cell[column].type = GTK_CELL_EMPTY;
2508 /* Note that pixmap and mask were already ref'ed by the caller
2515 clist_row->cell[column].type = GTK_CELL_TEXT;
2516 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2519 case GTK_CELL_PIXMAP:
2522 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2523 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2524 /* We set the mask even if it is NULL */
2525 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2528 case GTK_CELL_PIXTEXT:
2531 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2532 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2533 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2534 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2535 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2542 if (clist->column[column].auto_resize &&
2543 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2544 column_auto_resize (clist, clist_row, column, requisition.width);
2549 gdk_pixmap_unref (old_pixmap);
2551 gdk_pixmap_unref (old_mask);
2555 _gtk_clist_create_cell_layout (GtkCList *clist,
2556 GtkCListRow *clist_row,
2559 PangoLayout *layout;
2564 get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
2568 cell = &clist_row->cell[column];
2572 case GTK_CELL_PIXTEXT:
2573 text = ((cell->type == GTK_CELL_PIXTEXT) ?
2574 GTK_CELL_PIXTEXT (*cell)->text :
2575 GTK_CELL_TEXT (*cell)->text);
2580 layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
2581 ((cell->type == GTK_CELL_PIXTEXT) ?
2582 GTK_CELL_PIXTEXT (*cell)->text :
2583 GTK_CELL_TEXT (*cell)->text));
2584 pango_layout_set_font_description (layout, style->font_desc);
2594 cell_size_request (GtkCList *clist,
2595 GtkCListRow *clist_row,
2597 GtkRequisition *requisition)
2601 PangoLayout *layout;
2602 PangoRectangle logical_rect;
2604 g_return_if_fail (GTK_IS_CLIST (clist));
2605 g_return_if_fail (requisition != NULL);
2607 layout = _gtk_clist_create_cell_layout (clist, clist_row, column);
2610 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2612 requisition->width = logical_rect.width;
2613 requisition->height = logical_rect.height;
2615 g_object_unref (G_OBJECT (layout));
2619 requisition->width = 0;
2620 requisition->height = 0;
2623 if (layout && clist_row->cell[column].type == GTK_CELL_PIXTEXT)
2624 requisition->width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2626 switch (clist_row->cell[column].type)
2628 case GTK_CELL_PIXTEXT:
2629 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
2631 requisition->width += width;
2632 requisition->height = MAX (requisition->height, height);
2634 case GTK_CELL_PIXMAP:
2635 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
2637 requisition->width += width;
2638 requisition->height = MAX (requisition->height, height);
2645 requisition->width += clist_row->cell[column].horizontal;
2646 requisition->height += clist_row->cell[column].vertical;
2649 /* PUBLIC INSERT/REMOVE ROW FUNCTIONS
2657 gtk_clist_prepend (GtkCList *clist,
2660 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2661 g_return_val_if_fail (text != NULL, -1);
2663 return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, 0, text);
2667 gtk_clist_append (GtkCList *clist,
2670 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2671 g_return_val_if_fail (text != NULL, -1);
2673 return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, clist->rows, text);
2677 gtk_clist_insert (GtkCList *clist,
2681 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2682 g_return_val_if_fail (text != NULL, -1);
2684 if (row < 0 || row > clist->rows)
2687 return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, row, text);
2691 gtk_clist_remove (GtkCList *clist,
2694 GTK_CLIST_GET_CLASS (clist)->remove_row (clist, row);
2698 gtk_clist_clear (GtkCList *clist)
2700 g_return_if_fail (GTK_IS_CLIST (clist));
2702 GTK_CLIST_GET_CLASS (clist)->clear (clist);
2705 /* PRIVATE INSERT/REMOVE ROW FUNCTIONS
2712 real_insert_row (GtkCList *clist,
2717 GtkCListRow *clist_row;
2719 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2720 g_return_val_if_fail (text != NULL, -1);
2722 /* return if out of bounds */
2723 if (row < 0 || row > clist->rows)
2726 /* create the row */
2727 clist_row = row_new (clist);
2729 /* set the text in the row's columns */
2730 for (i = 0; i < clist->columns; i++)
2732 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
2733 (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
2737 clist->row_list = g_list_append (clist->row_list, clist_row);
2738 clist->row_list_end = clist->row_list;
2742 if (GTK_CLIST_AUTO_SORT(clist)) /* override insertion pos */
2747 work = clist->row_list;
2749 if (clist->sort_type == GTK_SORT_ASCENDING)
2751 while (row < clist->rows &&
2752 clist->compare (clist, clist_row,
2753 GTK_CLIST_ROW (work)) > 0)
2761 while (row < clist->rows &&
2762 clist->compare (clist, clist_row,
2763 GTK_CLIST_ROW (work)) < 0)
2771 /* reset the row end pointer if we're inserting at the end of the list */
2772 if (row == clist->rows)
2773 clist->row_list_end = (g_list_append (clist->row_list_end,
2776 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
2781 if (row < ROW_FROM_YPIXEL (clist, 0))
2782 clist->voffset -= (clist->row_height + CELL_SPACING);
2784 /* syncronize the selection list */
2785 sync_selection (clist, row, SYNC_INSERT);
2787 if (clist->rows == 1)
2789 clist->focus_row = 0;
2790 if (clist->selection_mode == GTK_SELECTION_BROWSE)
2791 gtk_clist_select_row (clist, 0, -1);
2794 /* redraw the list if it isn't frozen */
2795 if (CLIST_UNFROZEN (clist))
2797 adjust_adjustments (clist, FALSE);
2799 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2800 draw_rows (clist, NULL);
2807 real_remove_row (GtkCList *clist,
2810 gint was_visible, was_selected;
2812 GtkCListRow *clist_row;
2814 g_return_if_fail (GTK_IS_CLIST (clist));
2816 /* return if out of bounds */
2817 if (row < 0 || row > (clist->rows - 1))
2820 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
2823 /* get the row we're going to delete */
2824 list = ROW_ELEMENT (clist, row);
2825 g_assert (list != NULL);
2826 clist_row = list->data;
2828 /* if we're removing a selected row, we have to make sure
2829 * it's properly unselected, and then sync up the clist->selected
2830 * list to reflect the deincrimented indexies of rows after the
2832 if (clist_row->state == GTK_STATE_SELECTED)
2833 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2836 sync_selection (clist, row, SYNC_REMOVE);
2838 /* reset the row end pointer if we're removing at the end of the list */
2840 if (clist->row_list == list)
2841 clist->row_list = g_list_next (list);
2842 if (clist->row_list_end == list)
2843 clist->row_list_end = g_list_previous (list);
2844 g_list_remove (list, clist_row);
2846 /*if (clist->focus_row >=0 &&
2847 (row <= clist->focus_row || clist->focus_row >= clist->rows))
2848 clist->focus_row--;*/
2850 if (row < ROW_FROM_YPIXEL (clist, 0))
2851 clist->voffset += clist->row_height + CELL_SPACING;
2853 if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
2854 clist->focus_row >= 0)
2855 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2856 clist->focus_row, -1, NULL);
2859 row_delete (clist, clist_row);
2861 /* redraw the row if it isn't frozen */
2862 if (CLIST_UNFROZEN (clist))
2864 adjust_adjustments (clist, FALSE);
2867 draw_rows (clist, NULL);
2872 real_clear (GtkCList *clist)
2878 g_return_if_fail (GTK_IS_CLIST (clist));
2880 /* free up the selection list */
2881 g_list_free (clist->selection);
2882 g_list_free (clist->undo_selection);
2883 g_list_free (clist->undo_unselection);
2885 clist->selection = NULL;
2886 clist->selection_end = NULL;
2887 clist->undo_selection = NULL;
2888 clist->undo_unselection = NULL;
2890 clist->focus_row = -1;
2892 clist->undo_anchor = -1;
2893 clist->anchor_state = GTK_STATE_SELECTED;
2894 clist->drag_pos = -1;
2896 /* remove all the rows */
2897 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2898 free_list = clist->row_list;
2899 clist->row_list = NULL;
2900 clist->row_list_end = NULL;
2902 for (list = free_list; list; list = list->next)
2903 row_delete (clist, GTK_CLIST_ROW (list));
2904 g_list_free (free_list);
2905 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2906 for (i = 0; i < clist->columns; i++)
2907 if (clist->column[i].auto_resize)
2909 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2910 gtk_clist_set_column_width
2911 (clist, i, (clist->column[i].button->requisition.width -
2912 (CELL_SPACING + (2 * COLUMN_INSET))));
2914 gtk_clist_set_column_width (clist, i, 0);
2916 /* zero-out the scrollbars */
2917 if (clist->vadjustment)
2919 gtk_adjustment_set_value (clist->vadjustment, 0.0);
2920 CLIST_REFRESH (clist);
2923 gtk_widget_queue_resize (GTK_WIDGET (clist));
2927 real_row_move (GtkCList *clist,
2931 GtkCListRow *clist_row;
2936 g_return_if_fail (GTK_IS_CLIST (clist));
2938 if (GTK_CLIST_AUTO_SORT(clist))
2941 if (source_row < 0 || source_row >= clist->rows ||
2942 dest_row < 0 || dest_row >= clist->rows ||
2943 source_row == dest_row)
2946 gtk_clist_freeze (clist);
2948 /* unlink source row */
2949 clist_row = ROW_ELEMENT (clist, source_row)->data;
2950 if (source_row == clist->rows - 1)
2951 clist->row_list_end = clist->row_list_end->prev;
2952 clist->row_list = g_list_remove (clist->row_list, clist_row);
2955 /* relink source row */
2956 clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
2957 if (dest_row == clist->rows)
2958 clist->row_list_end = clist->row_list_end->next;
2961 /* sync selection */
2962 if (source_row > dest_row)
2975 for (list = clist->selection; list; list = list->next)
2977 if (list->data == GINT_TO_POINTER (source_row))
2978 list->data = GINT_TO_POINTER (dest_row);
2979 else if (first <= GPOINTER_TO_INT (list->data) &&
2980 last >= GPOINTER_TO_INT (list->data))
2981 list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
2984 if (clist->focus_row == source_row)
2985 clist->focus_row = dest_row;
2986 else if (clist->focus_row > first)
2987 clist->focus_row += d;
2989 gtk_clist_thaw (clist);
2992 /* PUBLIC ROW FUNCTIONS
2994 * gtk_clist_set_row_height
2995 * gtk_clist_set_row_data
2996 * gtk_clist_set_row_data_full
2997 * gtk_clist_get_row_data
2998 * gtk_clist_find_row_from_data
2999 * gtk_clist_swap_rows
3000 * gtk_clist_row_move
3001 * gtk_clist_row_is_visible
3002 * gtk_clist_set_foreground
3003 * gtk_clist_set_background
3006 gtk_clist_moveto (GtkCList *clist,
3012 g_return_if_fail (GTK_IS_CLIST (clist));
3014 if (row < -1 || row >= clist->rows)
3016 if (column < -1 || column >= clist->columns)
3019 row_align = CLAMP (row_align, 0, 1);
3020 col_align = CLAMP (col_align, 0, 1);
3022 /* adjust horizontal scrollbar */
3023 if (clist->hadjustment && column >= 0)
3027 x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
3028 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
3029 CELL_SPACING - clist->column[column].area.width)));
3031 gtk_adjustment_set_value (clist->hadjustment, 0.0);
3032 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
3033 gtk_adjustment_set_value
3034 (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
3036 gtk_adjustment_set_value (clist->hadjustment, x);
3039 /* adjust vertical scrollbar */
3040 if (clist->vadjustment && row >= 0)
3041 move_vertical (clist, row, row_align);
3045 gtk_clist_set_row_height (GtkCList *clist,
3050 g_return_if_fail (GTK_IS_CLIST (clist));
3052 widget = GTK_WIDGET (clist);
3056 clist->row_height = height;
3057 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
3061 GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
3062 clist->row_height = 0;
3065 if (widget->style->font_desc)
3067 PangoContext *context = gtk_widget_get_pango_context (widget);
3068 PangoFontMetrics *metrics;
3070 metrics = pango_context_get_metrics (context,
3071 widget->style->font_desc,
3072 pango_context_get_language (context));
3074 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
3076 clist->row_height = (pango_font_metrics_get_ascent (metrics) +
3077 pango_font_metrics_get_descent (metrics));
3078 clist->row_height = PANGO_PIXELS (clist->row_height);
3081 pango_font_metrics_unref (metrics);
3084 CLIST_REFRESH (clist);
3088 gtk_clist_set_row_data (GtkCList *clist,
3092 gtk_clist_set_row_data_full (clist, row, data, NULL);
3096 gtk_clist_set_row_data_full (GtkCList *clist,
3099 GtkDestroyNotify destroy)
3101 GtkCListRow *clist_row;
3103 g_return_if_fail (GTK_IS_CLIST (clist));
3105 if (row < 0 || row > (clist->rows - 1))
3108 clist_row = ROW_ELEMENT (clist, row)->data;
3110 if (clist_row->destroy)
3111 clist_row->destroy (clist_row->data);
3113 clist_row->data = data;
3114 clist_row->destroy = destroy;
3118 gtk_clist_get_row_data (GtkCList *clist,
3121 GtkCListRow *clist_row;
3123 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3125 if (row < 0 || row > (clist->rows - 1))
3128 clist_row = ROW_ELEMENT (clist, row)->data;
3129 return clist_row->data;
3133 gtk_clist_find_row_from_data (GtkCList *clist,
3139 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
3141 for (n = 0, list = clist->row_list; list; n++, list = list->next)
3142 if (GTK_CLIST_ROW (list)->data == data)
3149 gtk_clist_swap_rows (GtkCList *clist,
3155 g_return_if_fail (GTK_IS_CLIST (clist));
3156 g_return_if_fail (row1 != row2);
3158 if (GTK_CLIST_AUTO_SORT(clist))
3161 gtk_clist_freeze (clist);
3163 first = MIN (row1, row2);
3164 last = MAX (row1, row2);
3166 gtk_clist_row_move (clist, last, first);
3167 gtk_clist_row_move (clist, first + 1, last);
3169 gtk_clist_thaw (clist);
3173 gtk_clist_row_move (GtkCList *clist,
3177 g_return_if_fail (GTK_IS_CLIST (clist));
3179 if (GTK_CLIST_AUTO_SORT(clist))
3182 if (source_row < 0 || source_row >= clist->rows ||
3183 dest_row < 0 || dest_row >= clist->rows ||
3184 source_row == dest_row)
3187 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE],
3188 source_row, dest_row);
3192 gtk_clist_row_is_visible (GtkCList *clist,
3197 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3199 if (row < 0 || row >= clist->rows)
3200 return GTK_VISIBILITY_NONE;
3202 if (clist->row_height == 0)
3203 return GTK_VISIBILITY_NONE;
3205 if (row < ROW_FROM_YPIXEL (clist, 0))
3206 return GTK_VISIBILITY_NONE;
3208 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
3209 return GTK_VISIBILITY_NONE;
3211 top = ROW_TOP_YPIXEL (clist, row);
3214 || ((top + clist->row_height) >= clist->clist_window_height))
3215 return GTK_VISIBILITY_PARTIAL;
3217 return GTK_VISIBILITY_FULL;
3221 gtk_clist_set_foreground (GtkCList *clist,
3225 GtkCListRow *clist_row;
3227 g_return_if_fail (GTK_IS_CLIST (clist));
3229 if (row < 0 || row >= clist->rows)
3232 clist_row = ROW_ELEMENT (clist, row)->data;
3236 clist_row->foreground = *color;
3237 clist_row->fg_set = TRUE;
3238 if (GTK_WIDGET_REALIZED (clist))
3239 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3240 &clist_row->foreground);
3243 clist_row->fg_set = FALSE;
3245 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3246 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3250 gtk_clist_set_background (GtkCList *clist,
3254 GtkCListRow *clist_row;
3256 g_return_if_fail (GTK_IS_CLIST (clist));
3258 if (row < 0 || row >= clist->rows)
3261 clist_row = ROW_ELEMENT (clist, row)->data;
3265 clist_row->background = *color;
3266 clist_row->bg_set = TRUE;
3267 if (GTK_WIDGET_REALIZED (clist))
3268 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3269 &clist_row->background);
3272 clist_row->bg_set = FALSE;
3274 if (CLIST_UNFROZEN (clist)
3275 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3276 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3279 /* PUBLIC ROW/CELL STYLE FUNCTIONS
3280 * gtk_clist_set_cell_style
3281 * gtk_clist_get_cell_style
3282 * gtk_clist_set_row_style
3283 * gtk_clist_get_row_style
3286 gtk_clist_set_cell_style (GtkCList *clist,
3291 GtkRequisition requisition = { 0 };
3292 GtkCListRow *clist_row;
3294 g_return_if_fail (GTK_IS_CLIST (clist));
3296 if (row < 0 || row >= clist->rows)
3298 if (column < 0 || column >= clist->columns)
3301 clist_row = ROW_ELEMENT (clist, row)->data;
3303 if (clist_row->cell[column].style == style)
3306 if (clist->column[column].auto_resize &&
3307 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3308 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
3309 column, &requisition);
3311 if (clist_row->cell[column].style)
3313 if (GTK_WIDGET_REALIZED (clist))
3314 gtk_style_detach (clist_row->cell[column].style);
3315 g_object_unref (clist_row->cell[column].style);
3318 clist_row->cell[column].style = style;
3320 if (clist_row->cell[column].style)
3322 g_object_ref (clist_row->cell[column].style);
3324 if (GTK_WIDGET_REALIZED (clist))
3325 clist_row->cell[column].style =
3326 gtk_style_attach (clist_row->cell[column].style,
3327 clist->clist_window);
3330 column_auto_resize (clist, clist_row, column, requisition.width);
3332 /* redraw the list if it's not frozen */
3333 if (CLIST_UNFROZEN (clist))
3335 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3336 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3341 gtk_clist_get_cell_style (GtkCList *clist,
3345 GtkCListRow *clist_row;
3347 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3349 if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
3352 clist_row = ROW_ELEMENT (clist, row)->data;
3354 return clist_row->cell[column].style;
3358 gtk_clist_set_row_style (GtkCList *clist,
3362 GtkRequisition requisition;
3363 GtkCListRow *clist_row;
3367 g_return_if_fail (GTK_IS_CLIST (clist));
3369 if (row < 0 || row >= clist->rows)
3372 clist_row = ROW_ELEMENT (clist, row)->data;
3374 if (clist_row->style == style)
3377 old_width = g_new (gint, clist->columns);
3379 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3381 for (i = 0; i < clist->columns; i++)
3382 if (clist->column[i].auto_resize)
3384 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
3386 old_width[i] = requisition.width;
3390 if (clist_row->style)
3392 if (GTK_WIDGET_REALIZED (clist))
3393 gtk_style_detach (clist_row->style);
3394 g_object_unref (clist_row->style);
3397 clist_row->style = style;
3399 if (clist_row->style)
3401 g_object_ref (clist_row->style);
3403 if (GTK_WIDGET_REALIZED (clist))
3404 clist_row->style = gtk_style_attach (clist_row->style,
3405 clist->clist_window);
3408 if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3409 for (i = 0; i < clist->columns; i++)
3410 column_auto_resize (clist, clist_row, i, old_width[i]);
3414 /* redraw the list if it's not frozen */
3415 if (CLIST_UNFROZEN (clist))
3417 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3418 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3423 gtk_clist_get_row_style (GtkCList *clist,
3426 GtkCListRow *clist_row;
3428 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3430 if (row < 0 || row >= clist->rows)
3433 clist_row = ROW_ELEMENT (clist, row)->data;
3435 return clist_row->style;
3438 /* PUBLIC SELECTION FUNCTIONS
3439 * gtk_clist_set_selectable
3440 * gtk_clist_get_selectable
3441 * gtk_clist_select_row
3442 * gtk_clist_unselect_row
3443 * gtk_clist_select_all
3444 * gtk_clist_unselect_all
3445 * gtk_clist_undo_selection
3448 gtk_clist_set_selectable (GtkCList *clist,
3450 gboolean selectable)
3452 GtkCListRow *clist_row;
3454 g_return_if_fail (GTK_IS_CLIST (clist));
3456 if (row < 0 || row >= clist->rows)
3459 clist_row = ROW_ELEMENT (clist, row)->data;
3461 if (selectable == clist_row->selectable)
3464 clist_row->selectable = selectable;
3466 if (!selectable && clist_row->state == GTK_STATE_SELECTED)
3468 if (clist->anchor >= 0 &&
3469 clist->selection_mode == GTK_SELECTION_MULTIPLE)
3471 clist->drag_button = 0;
3472 remove_grab (clist);
3473 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
3475 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3481 gtk_clist_get_selectable (GtkCList *clist,
3484 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
3486 if (row < 0 || row >= clist->rows)
3489 return GTK_CLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
3493 gtk_clist_select_row (GtkCList *clist,
3497 g_return_if_fail (GTK_IS_CLIST (clist));
3499 if (row < 0 || row >= clist->rows)
3501 if (column < -1 || column >= clist->columns)
3504 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3509 gtk_clist_unselect_row (GtkCList *clist,
3513 g_return_if_fail (GTK_IS_CLIST (clist));
3515 if (row < 0 || row >= clist->rows)
3517 if (column < -1 || column >= clist->columns)
3520 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3525 gtk_clist_select_all (GtkCList *clist)
3527 g_return_if_fail (GTK_IS_CLIST (clist));
3529 GTK_CLIST_GET_CLASS (clist)->select_all (clist);
3533 gtk_clist_unselect_all (GtkCList *clist)
3535 g_return_if_fail (GTK_IS_CLIST (clist));
3537 GTK_CLIST_GET_CLASS (clist)->unselect_all (clist);
3541 gtk_clist_undo_selection (GtkCList *clist)
3543 g_return_if_fail (GTK_IS_CLIST (clist));
3545 if (clist->selection_mode == GTK_SELECTION_MULTIPLE &&
3546 (clist->undo_selection || clist->undo_unselection))
3547 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
3550 /* PRIVATE SELECTION FUNCTIONS
3561 * real_undo_selection
3564 * update_extended_selection
3571 selection_find (GtkCList *clist,
3573 GList *row_list_element)
3575 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
3579 toggle_row (GtkCList *clist,
3584 GtkCListRow *clist_row;
3586 switch (clist->selection_mode)
3588 case GTK_SELECTION_MULTIPLE:
3589 case GTK_SELECTION_SINGLE:
3590 clist_row = ROW_ELEMENT (clist, row)->data;
3595 if (clist_row->state == GTK_STATE_SELECTED)
3597 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3598 row, column, event);
3601 case GTK_SELECTION_BROWSE:
3602 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3603 row, column, event);
3606 g_assert_not_reached ();
3611 fake_toggle_row (GtkCList *clist,
3616 work = ROW_ELEMENT (clist, row);
3618 if (!work || !GTK_CLIST_ROW (work)->selectable)
3621 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
3622 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3624 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3626 if (CLIST_UNFROZEN (clist) &&
3627 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3628 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
3629 GTK_CLIST_ROW (work));
3633 clist_has_grab (GtkCList *clist)
3635 return (GTK_WIDGET_HAS_GRAB (clist) &&
3636 gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))));
3640 toggle_focus_row (GtkCList *clist)
3642 g_return_if_fail (clist != 0);
3643 g_return_if_fail (GTK_IS_CLIST (clist));
3645 if (clist_has_grab (clist) ||
3646 clist->focus_row < 0 || clist->focus_row >= clist->rows)
3649 switch (clist->selection_mode)
3651 case GTK_SELECTION_SINGLE:
3652 toggle_row (clist, clist->focus_row, 0, NULL);
3654 case GTK_SELECTION_MULTIPLE:
3655 g_list_free (clist->undo_selection);
3656 g_list_free (clist->undo_unselection);
3657 clist->undo_selection = NULL;
3658 clist->undo_unselection = NULL;
3660 clist->anchor = clist->focus_row;
3661 clist->drag_pos = clist->focus_row;
3662 clist->undo_anchor = clist->focus_row;
3664 if (GTK_CLIST_ADD_MODE(clist))
3665 fake_toggle_row (clist, clist->focus_row);
3667 GTK_CLIST_GET_CLASS (clist)->fake_unselect_all (clist,clist->focus_row);
3669 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
3677 toggle_add_mode (GtkCList *clist)
3679 g_return_if_fail (clist != 0);
3680 g_return_if_fail (GTK_IS_CLIST (clist));
3682 if (clist_has_grab (clist) ||
3683 clist->selection_mode != GTK_SELECTION_MULTIPLE)
3686 gtk_clist_draw_focus (GTK_WIDGET (clist));
3687 if (!GTK_CLIST_ADD_MODE(clist))
3689 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
3690 gdk_gc_set_line_attributes (clist->xor_gc, 1,
3691 GDK_LINE_ON_OFF_DASH, 0, 0);
3692 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
3696 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
3697 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
3698 clist->anchor_state = GTK_STATE_SELECTED;
3700 gtk_clist_draw_focus (GTK_WIDGET (clist));
3704 real_select_row (GtkCList *clist,
3709 GtkCListRow *clist_row;
3712 gboolean row_selected;
3714 g_return_if_fail (GTK_IS_CLIST (clist));
3716 if (row < 0 || row > (clist->rows - 1))
3719 switch (clist->selection_mode)
3721 case GTK_SELECTION_SINGLE:
3722 case GTK_SELECTION_BROWSE:
3724 row_selected = FALSE;
3725 list = clist->selection;
3729 sel_row = GPOINTER_TO_INT (list->data);
3733 row_selected = TRUE;
3735 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3736 sel_row, column, event);
3746 clist_row = ROW_ELEMENT (clist, row)->data;
3748 if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
3751 clist_row->state = GTK_STATE_SELECTED;
3752 if (!clist->selection)
3754 clist->selection = g_list_append (clist->selection,
3755 GINT_TO_POINTER (row));
3756 clist->selection_end = clist->selection;
3759 clist->selection_end =
3760 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
3762 if (CLIST_UNFROZEN (clist)
3763 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3764 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3768 real_unselect_row (GtkCList *clist,
3773 GtkCListRow *clist_row;
3775 g_return_if_fail (GTK_IS_CLIST (clist));
3777 if (row < 0 || row > (clist->rows - 1))
3780 clist_row = ROW_ELEMENT (clist, row)->data;
3782 if (clist_row->state == GTK_STATE_SELECTED)
3784 clist_row->state = GTK_STATE_NORMAL;
3786 if (clist->selection_end &&
3787 clist->selection_end->data == GINT_TO_POINTER (row))
3788 clist->selection_end = clist->selection_end->prev;
3790 clist->selection = g_list_remove (clist->selection,
3791 GINT_TO_POINTER (row));
3793 if (CLIST_UNFROZEN (clist)
3794 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3795 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
3800 real_select_all (GtkCList *clist)
3802 g_return_if_fail (GTK_IS_CLIST (clist));
3804 if (clist_has_grab (clist))
3807 switch (clist->selection_mode)
3809 case GTK_SELECTION_SINGLE:
3810 case GTK_SELECTION_BROWSE:
3813 case GTK_SELECTION_MULTIPLE:
3814 g_list_free (clist->undo_selection);
3815 g_list_free (clist->undo_unselection);
3816 clist->undo_selection = NULL;
3817 clist->undo_unselection = NULL;
3820 ((GtkCListRow *) (clist->row_list->data))->state !=
3822 fake_toggle_row (clist, 0);
3824 clist->anchor_state = GTK_STATE_SELECTED;
3826 clist->drag_pos = 0;
3827 clist->undo_anchor = clist->focus_row;
3828 update_extended_selection (clist, clist->rows);
3829 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
3832 g_assert_not_reached ();
3837 real_unselect_all (GtkCList *clist)
3842 g_return_if_fail (GTK_IS_CLIST (clist));
3844 if (clist_has_grab (clist))
3847 switch (clist->selection_mode)
3849 case GTK_SELECTION_BROWSE:
3850 if (clist->focus_row >= 0)
3852 gtk_signal_emit (GTK_OBJECT (clist),
3853 clist_signals[SELECT_ROW],
3854 clist->focus_row, -1, NULL);
3858 case GTK_SELECTION_MULTIPLE:
3859 g_list_free (clist->undo_selection);
3860 g_list_free (clist->undo_unselection);
3861 clist->undo_selection = NULL;
3862 clist->undo_unselection = NULL;
3865 clist->drag_pos = -1;
3866 clist->undo_anchor = clist->focus_row;
3872 list = clist->selection;
3875 i = GPOINTER_TO_INT (list->data);
3877 gtk_signal_emit (GTK_OBJECT (clist),
3878 clist_signals[UNSELECT_ROW], i, -1, NULL);
3883 fake_unselect_all (GtkCList *clist,
3890 if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
3892 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
3893 GTK_CLIST_ROW (work)->selectable)
3895 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3897 if (CLIST_UNFROZEN (clist) &&
3898 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3899 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
3900 GTK_CLIST_ROW (work));
3904 clist->undo_selection = clist->selection;
3905 clist->selection = NULL;
3906 clist->selection_end = NULL;
3908 for (list = clist->undo_selection; list; list = list->next)
3910 if ((i = GPOINTER_TO_INT (list->data)) == row ||
3911 !(work = g_list_nth (clist->row_list, i)))
3914 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3915 if (CLIST_UNFROZEN (clist) &&
3916 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
3917 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, i,
3918 GTK_CLIST_ROW (work));
3923 real_undo_selection (GtkCList *clist)
3927 g_return_if_fail (GTK_IS_CLIST (clist));
3929 if (clist_has_grab (clist) ||
3930 clist->selection_mode != GTK_SELECTION_MULTIPLE)
3933 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
3935 if (!(clist->undo_selection || clist->undo_unselection))
3937 gtk_clist_unselect_all (clist);
3941 for (work = clist->undo_selection; work; work = work->next)
3942 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3943 GPOINTER_TO_INT (work->data), -1, NULL);
3945 for (work = clist->undo_unselection; work; work = work->next)
3947 /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
3948 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3949 GPOINTER_TO_INT (work->data), -1, NULL);
3952 if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
3954 gtk_clist_draw_focus (GTK_WIDGET (clist));
3955 clist->focus_row = clist->undo_anchor;
3956 gtk_clist_draw_focus (GTK_WIDGET (clist));
3959 clist->focus_row = clist->undo_anchor;
3961 clist->undo_anchor = -1;
3963 g_list_free (clist->undo_selection);
3964 g_list_free (clist->undo_unselection);
3965 clist->undo_selection = NULL;
3966 clist->undo_unselection = NULL;
3968 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
3969 clist->clist_window_height)
3970 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3971 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
3972 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3976 set_anchor (GtkCList *clist,
3981 g_return_if_fail (GTK_IS_CLIST (clist));
3983 if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor >= 0)
3986 g_list_free (clist->undo_selection);
3987 g_list_free (clist->undo_unselection);
3988 clist->undo_selection = NULL;
3989 clist->undo_unselection = NULL;
3992 fake_toggle_row (clist, anchor);
3995 GTK_CLIST_GET_CLASS (clist)->fake_unselect_all (clist, anchor);
3996 clist->anchor_state = GTK_STATE_SELECTED;
3999 clist->anchor = anchor;
4000 clist->drag_pos = anchor;
4001 clist->undo_anchor = undo_anchor;
4005 resync_selection (GtkCList *clist,
4012 GtkCListRow *clist_row;
4014 if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
4017 if (clist->anchor < 0 || clist->drag_pos < 0)
4020 gtk_clist_freeze (clist);
4022 i = MIN (clist->anchor, clist->drag_pos);
4023 e = MAX (clist->anchor, clist->drag_pos);
4025 if (clist->undo_selection)
4027 list = clist->selection;
4028 clist->selection = clist->undo_selection;
4029 clist->selection_end = g_list_last (clist->selection);
4030 clist->undo_selection = list;
4031 list = clist->selection;
4034 row = GPOINTER_TO_INT (list->data);
4036 if (row < i || row > e)
4038 clist_row = g_list_nth (clist->row_list, row)->data;
4039 if (clist_row->selectable)
4041 clist_row->state = GTK_STATE_SELECTED;
4042 gtk_signal_emit (GTK_OBJECT (clist),
4043 clist_signals[UNSELECT_ROW],
4045 clist->undo_selection = g_list_prepend
4046 (clist->undo_selection, GINT_TO_POINTER (row));
4052 if (clist->anchor < clist->drag_pos)
4054 for (list = g_list_nth (clist->row_list, i); i <= e;
4055 i++, list = list->next)
4056 if (GTK_CLIST_ROW (list)->selectable)
4058 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
4060 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
4062 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4063 gtk_signal_emit (GTK_OBJECT (clist),
4064 clist_signals[UNSELECT_ROW],
4066 clist->undo_selection =
4067 g_list_prepend (clist->undo_selection,
4068 GINT_TO_POINTER (i));
4071 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
4073 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4074 clist->undo_unselection =
4075 g_list_prepend (clist->undo_unselection,
4076 GINT_TO_POINTER (i));
4082 for (list = g_list_nth (clist->row_list, e); i <= e;
4083 e--, list = list->prev)
4084 if (GTK_CLIST_ROW (list)->selectable)
4086 if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
4088 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
4090 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4091 gtk_signal_emit (GTK_OBJECT (clist),
4092 clist_signals[UNSELECT_ROW],
4094 clist->undo_selection =
4095 g_list_prepend (clist->undo_selection,
4096 GINT_TO_POINTER (e));
4099 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
4101 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4102 clist->undo_unselection =
4103 g_list_prepend (clist->undo_unselection,
4104 GINT_TO_POINTER (e));
4109 clist->undo_unselection = g_list_reverse (clist->undo_unselection);
4110 for (list = clist->undo_unselection; list; list = list->next)
4111 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
4112 GPOINTER_TO_INT (list->data), -1, event);
4115 clist->drag_pos = -1;
4117 gtk_clist_thaw (clist);
4121 update_extended_selection (GtkCList *clist,
4131 gint y1 = clist->clist_window_height;
4132 gint y2 = clist->clist_window_height;
4137 if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor == -1)
4142 if (row >= clist->rows)
4143 row = clist->rows - 1;
4145 /* extending downwards */
4146 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
4148 s2 = clist->drag_pos + 1;
4151 /* extending upwards */
4152 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
4155 e2 = clist->drag_pos - 1;
4157 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
4159 e1 = clist->drag_pos;
4160 /* row and drag_pos on different sides of anchor :
4161 take back the selection between anchor and drag_pos,
4162 select between anchor and row */
4163 if (row < clist->anchor)
4165 s1 = clist->anchor + 1;
4167 e2 = clist->anchor - 1;
4169 /* take back the selection between anchor and drag_pos */
4173 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
4175 s1 = clist->drag_pos;
4176 /* row and drag_pos on different sides of anchor :
4177 take back the selection between anchor and drag_pos,
4178 select between anchor and row */
4179 if (row > clist->anchor)
4181 e1 = clist->anchor - 1;
4182 s2 = clist->anchor + 1;
4185 /* take back the selection between anchor and drag_pos */
4190 clist->drag_pos = row;
4193 area.width = clist->clist_window_width;
4195 /* restore the elements between s1 and e1 */
4198 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
4199 i++, list = list->next)
4200 if (GTK_CLIST_ROW (list)->selectable)
4202 if (GTK_CLIST_GET_CLASS (clist)->selection_find (clist, i, list))
4203 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4205 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4208 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4210 if (top + clist->row_height <= 0)
4213 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
4214 draw_rows (clist, &area);
4215 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4217 else if (top >= clist->clist_window_height)
4219 area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
4220 area.height = clist->clist_window_height - area.y;
4221 draw_rows (clist, &area);
4222 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4225 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4226 else if (top + clist->row_height > clist->clist_window_height)
4227 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4229 y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
4230 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
4233 /* extend the selection between s2 and e2 */
4236 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
4237 i++, list = list->next)
4238 if (GTK_CLIST_ROW (list)->selectable &&
4239 GTK_CLIST_ROW (list)->state != clist->anchor_state)
4240 GTK_CLIST_ROW (list)->state = clist->anchor_state;
4242 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4244 if (top + clist->row_height <= 0)
4247 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
4248 draw_rows (clist, &area);
4249 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4251 else if (top >= clist->clist_window_height)
4253 area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
4254 area.height = clist->clist_window_height - area.y;
4255 draw_rows (clist, &area);
4256 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4259 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4260 else if (top + clist->row_height > clist->clist_window_height)
4261 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4263 y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
4264 h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
4267 area.y = MAX (0, MIN (y1, y2));
4268 if (area.y > clist->clist_window_height)
4270 area.height = MIN (clist->clist_window_height, h1 + h2);
4271 if (s1 >= 0 && s2 >= 0)
4272 area.height += (clist->row_height + CELL_SPACING);
4273 draw_rows (clist, &area);
4277 start_selection (GtkCList *clist)
4279 g_return_if_fail (GTK_IS_CLIST (clist));
4281 if (clist_has_grab (clist))
4284 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4289 end_selection (GtkCList *clist)
4291 g_return_if_fail (GTK_IS_CLIST (clist));
4293 if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) &&
4294 GTK_WIDGET_HAS_FOCUS (clist))
4297 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
4301 extend_selection (GtkCList *clist,
4302 GtkScrollType scroll_type,
4304 gboolean auto_start_selection)
4306 g_return_if_fail (GTK_IS_CLIST (clist));
4308 if (clist_has_grab (clist) ||
4309 clist->selection_mode != GTK_SELECTION_MULTIPLE)
4312 if (auto_start_selection)
4313 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4315 else if (clist->anchor == -1)
4318 move_focus_row (clist, scroll_type, position);
4320 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
4321 clist->clist_window_height)
4322 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4323 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
4324 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4326 update_extended_selection (clist, clist->focus_row);
4330 sync_selection (GtkCList *clist,
4337 if (mode == SYNC_INSERT)
4342 if (clist->focus_row >= row)
4344 if (d > 0 || clist->focus_row > row)
4345 clist->focus_row += d;
4346 if (clist->focus_row == -1 && clist->rows >= 1)
4347 clist->focus_row = 0;
4348 else if (clist->focus_row >= clist->rows)
4349 clist->focus_row = clist->rows - 1;
4352 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
4354 g_list_free (clist->undo_selection);
4355 g_list_free (clist->undo_unselection);
4356 clist->undo_selection = NULL;
4357 clist->undo_unselection = NULL;
4360 clist->drag_pos = -1;
4361 clist->undo_anchor = clist->focus_row;
4363 list = clist->selection;
4367 if (GPOINTER_TO_INT (list->data) >= row)
4368 list->data = ((gchar*) list->data) + d;
4375 * gtk_clist_finalize
4378 gtk_clist_destroy (GtkObject *object)
4383 g_return_if_fail (GTK_IS_CLIST (object));
4385 clist = GTK_CLIST (object);
4387 /* freeze the list */
4388 clist->freeze_count++;
4390 /* get rid of all the rows */
4391 gtk_clist_clear (clist);
4393 /* Since we don't have a _remove method, unparent the children
4394 * instead of destroying them so the focus will be unset properly.
4395 * (For other containers, the _remove method takes care of the
4396 * unparent) The destroy will happen when the refcount drops
4400 /* unref adjustments */
4401 if (clist->hadjustment)
4403 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
4404 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
4405 clist->hadjustment = NULL;
4407 if (clist->vadjustment)
4409 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
4410 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
4411 clist->vadjustment = NULL;
4414 remove_grab (clist);
4416 /* destroy the column buttons */
4417 for (i = 0; i < clist->columns; i++)
4418 if (clist->column[i].button)
4420 gtk_widget_unparent (clist->column[i].button);
4421 clist->column[i].button = NULL;
4424 if (GTK_OBJECT_CLASS (parent_class)->destroy)
4425 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
4429 gtk_clist_finalize (GObject *object)
4433 g_return_if_fail (GTK_IS_CLIST (object));
4435 clist = GTK_CLIST (object);
4437 columns_delete (clist);
4439 g_mem_chunk_destroy (clist->cell_mem_chunk);
4440 g_mem_chunk_destroy (clist->row_mem_chunk);
4442 G_OBJECT_CLASS (parent_class)->finalize (object);
4447 * gtk_clist_unrealize
4451 * gtk_clist_style_set
4452 * gtk_clist_button_press
4453 * gtk_clist_button_release
4455 * gtk_clist_size_request
4456 * gtk_clist_size_allocate
4459 gtk_clist_realize (GtkWidget *widget)
4462 GdkWindowAttr attributes;
4464 GtkCListRow *clist_row;
4466 gint attributes_mask;
4471 g_return_if_fail (GTK_IS_CLIST (widget));
4473 clist = GTK_CLIST (widget);
4475 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4477 border_width = GTK_CONTAINER (widget)->border_width;
4479 attributes.window_type = GDK_WINDOW_CHILD;
4480 attributes.x = widget->allocation.x + border_width;
4481 attributes.y = widget->allocation.y + border_width;
4482 attributes.width = widget->allocation.width - border_width * 2;
4483 attributes.height = widget->allocation.height - border_width * 2;
4484 attributes.wclass = GDK_INPUT_OUTPUT;
4485 attributes.visual = gtk_widget_get_visual (widget);
4486 attributes.colormap = gtk_widget_get_colormap (widget);
4487 attributes.event_mask = gtk_widget_get_events (widget);
4488 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4489 GDK_BUTTON_PRESS_MASK |
4490 GDK_BUTTON_RELEASE_MASK |
4491 GDK_KEY_RELEASE_MASK);
4492 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
4495 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
4496 &attributes, attributes_mask);
4497 gdk_window_set_user_data (widget->window, clist);
4499 widget->style = gtk_style_attach (widget->style, widget->window);
4501 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4503 /* column-title window */
4505 attributes.x = clist->column_title_area.x;
4506 attributes.y = clist->column_title_area.y;
4507 attributes.width = clist->column_title_area.width;
4508 attributes.height = clist->column_title_area.height;
4510 clist->title_window = gdk_window_new (widget->window, &attributes,
4512 gdk_window_set_user_data (clist->title_window, clist);
4514 gtk_style_set_background (widget->style, clist->title_window,
4516 gdk_window_show (clist->title_window);
4518 /* set things up so column buttons are drawn in title window */
4519 for (i = 0; i < clist->columns; i++)
4520 if (clist->column[i].button)
4521 gtk_widget_set_parent_window (clist->column[i].button,
4522 clist->title_window);
4525 attributes.x = (clist->internal_allocation.x +
4526 widget->style->xthickness);
4527 attributes.y = (clist->internal_allocation.y +
4528 widget->style->ythickness +
4529 clist->column_title_area.height);
4530 attributes.width = clist->clist_window_width;
4531 attributes.height = clist->clist_window_height;
4533 clist->clist_window = gdk_window_new (widget->window, &attributes,
4535 gdk_window_set_user_data (clist->clist_window, clist);
4537 gdk_window_set_background (clist->clist_window,
4538 &widget->style->base[GTK_STATE_NORMAL]);
4539 gdk_window_show (clist->clist_window);
4540 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
4541 &clist->clist_window_height);
4543 /* create resize windows */
4544 attributes.wclass = GDK_INPUT_ONLY;
4545 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
4546 GDK_BUTTON_RELEASE_MASK |
4547 GDK_POINTER_MOTION_MASK |
4548 GDK_POINTER_MOTION_HINT_MASK);
4549 attributes_mask = GDK_WA_CURSOR;
4550 attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
4551 GDK_SB_H_DOUBLE_ARROW);
4552 clist->cursor_drag = attributes.cursor;
4554 attributes.x = LIST_WIDTH (clist) + 1;
4556 attributes.width = 0;
4557 attributes.height = 0;
4559 for (i = 0; i < clist->columns; i++)
4561 clist->column[i].window = gdk_window_new (clist->title_window,
4562 &attributes, attributes_mask);
4563 gdk_window_set_user_data (clist->column[i].window, clist);
4566 /* This is slightly less efficient than creating them with the
4567 * right size to begin with, but easier
4569 size_allocate_title_buttons (clist);
4572 clist->fg_gc = gdk_gc_new (widget->window);
4573 clist->bg_gc = gdk_gc_new (widget->window);
4575 /* We'll use this gc to do scrolling as well */
4576 gdk_gc_set_exposures (clist->fg_gc, TRUE);
4578 values.foreground = (widget->style->white.pixel==0 ?
4579 widget->style->black:widget->style->white);
4580 values.function = GDK_XOR;
4581 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
4582 clist->xor_gc = gdk_gc_new_with_values (widget->window,
4588 /* attach optional row/cell styles, allocate foreground/background colors */
4589 list = clist->row_list;
4590 for (i = 0; i < clist->rows; i++)
4592 clist_row = list->data;
4595 if (clist_row->style)
4596 clist_row->style = gtk_style_attach (clist_row->style,
4597 clist->clist_window);
4599 if (clist_row->fg_set || clist_row->bg_set)
4601 GdkColormap *colormap;
4603 colormap = gtk_widget_get_colormap (widget);
4604 if (clist_row->fg_set)
4605 gdk_color_alloc (colormap, &clist_row->foreground);
4606 if (clist_row->bg_set)
4607 gdk_color_alloc (colormap, &clist_row->background);
4610 for (j = 0; j < clist->columns; j++)
4611 if (clist_row->cell[j].style)
4612 clist_row->cell[j].style =
4613 gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
4618 gtk_clist_unrealize (GtkWidget *widget)
4623 g_return_if_fail (GTK_IS_CLIST (widget));
4625 clist = GTK_CLIST (widget);
4627 /* freeze the list */
4628 clist->freeze_count++;
4630 if (GTK_WIDGET_MAPPED (widget))
4631 gtk_clist_unmap (widget);
4633 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4635 /* detach optional row/cell styles */
4636 if (GTK_WIDGET_REALIZED (widget))
4638 GtkCListRow *clist_row;
4642 list = clist->row_list;
4643 for (i = 0; i < clist->rows; i++)
4645 clist_row = list->data;
4648 if (clist_row->style)
4649 gtk_style_detach (clist_row->style);
4650 for (j = 0; j < clist->columns; j++)
4651 if (clist_row->cell[j].style)
4652 gtk_style_detach (clist_row->cell[j].style);
4656 gdk_cursor_destroy (clist->cursor_drag);
4657 gdk_gc_destroy (clist->xor_gc);
4658 gdk_gc_destroy (clist->fg_gc);
4659 gdk_gc_destroy (clist->bg_gc);
4661 for (i = 0; i < clist->columns; i++)
4663 if (clist->column[i].button)
4664 gtk_widget_unrealize (clist->column[i].button);
4665 if (clist->column[i].window)
4667 gdk_window_set_user_data (clist->column[i].window, NULL);
4668 gdk_window_destroy (clist->column[i].window);
4669 clist->column[i].window = NULL;
4673 gdk_window_set_user_data (clist->clist_window, NULL);
4674 gdk_window_destroy (clist->clist_window);
4675 clist->clist_window = NULL;
4677 gdk_window_set_user_data (clist->title_window, NULL);
4678 gdk_window_destroy (clist->title_window);
4679 clist->title_window = NULL;
4681 clist->cursor_drag = NULL;
4682 clist->xor_gc = NULL;
4683 clist->fg_gc = NULL;
4684 clist->bg_gc = NULL;
4686 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
4687 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4691 gtk_clist_map (GtkWidget *widget)
4696 g_return_if_fail (GTK_IS_CLIST (widget));
4698 clist = GTK_CLIST (widget);
4700 if (!GTK_WIDGET_MAPPED (widget))
4702 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4704 /* map column buttons */
4705 for (i = 0; i < clist->columns; i++)
4707 if (clist->column[i].button &&
4708 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
4709 !GTK_WIDGET_MAPPED (clist->column[i].button))
4710 gtk_widget_map (clist->column[i].button);
4713 for (i = 0; i < clist->columns; i++)
4714 if (clist->column[i].window && clist->column[i].button)
4716 gdk_window_raise (clist->column[i].window);
4717 gdk_window_show (clist->column[i].window);
4720 gdk_window_show (clist->title_window);
4721 gdk_window_show (clist->clist_window);
4722 gdk_window_show (widget->window);
4724 /* unfreeze the list */
4725 clist->freeze_count = 0;
4730 gtk_clist_unmap (GtkWidget *widget)
4735 g_return_if_fail (GTK_IS_CLIST (widget));
4737 clist = GTK_CLIST (widget);
4739 if (GTK_WIDGET_MAPPED (widget))
4741 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4743 if (clist_has_grab (clist))
4745 remove_grab (clist);
4747 GTK_CLIST_GET_CLASS (widget)->resync_selection (clist, NULL);
4749 clist->click_cell.row = -1;
4750 clist->click_cell.column = -1;
4751 clist->drag_button = 0;
4753 if (GTK_CLIST_IN_DRAG(clist))
4757 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
4758 drag_data = gtk_object_get_data (GTK_OBJECT (clist),
4761 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
4766 for (i = 0; i < clist->columns; i++)
4767 if (clist->column[i].window)
4768 gdk_window_hide (clist->column[i].window);
4770 gdk_window_hide (clist->clist_window);
4771 gdk_window_hide (clist->title_window);
4772 gdk_window_hide (widget->window);
4774 /* unmap column buttons */
4775 for (i = 0; i < clist->columns; i++)
4776 if (clist->column[i].button &&
4777 GTK_WIDGET_MAPPED (clist->column[i].button))
4778 gtk_widget_unmap (clist->column[i].button);
4780 /* freeze the list */
4781 clist->freeze_count++;
4786 gtk_clist_expose (GtkWidget *widget,
4787 GdkEventExpose *event)
4791 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4792 g_return_val_if_fail (event != NULL, FALSE);
4794 if (GTK_WIDGET_DRAWABLE (widget))
4796 clist = GTK_CLIST (widget);
4799 if (event->window == widget->window)
4800 gtk_draw_shadow (widget->style, widget->window,
4801 GTK_STATE_NORMAL, clist->shadow_type,
4803 clist->clist_window_width +
4804 (2 * widget->style->xthickness),
4805 clist->clist_window_height +
4806 (2 * widget->style->ythickness) +
4807 clist->column_title_area.height);
4809 /* exposure events on the list */
4810 if (event->window == clist->clist_window)
4811 draw_rows (clist, &event->area);
4813 if (event->window == clist->clist_window &&
4814 clist->drag_highlight_row >= 0)
4815 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
4816 (clist, g_list_nth (clist->row_list,
4817 clist->drag_highlight_row)->data,
4818 clist->drag_highlight_row, clist->drag_highlight_pos);
4820 if (event->window == clist->title_window)
4824 for (i = 0; i < clist->columns; i++)
4826 if (clist->column[i].button)
4827 gtk_container_propagate_expose (GTK_CONTAINER (clist),
4828 clist->column[i].button,
4838 gtk_clist_style_set (GtkWidget *widget,
4839 GtkStyle *previous_style)
4843 g_return_if_fail (GTK_IS_CLIST (widget));
4845 if (GTK_WIDGET_CLASS (parent_class)->style_set)
4846 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
4848 clist = GTK_CLIST (widget);
4850 if (GTK_WIDGET_REALIZED (widget))
4852 gtk_style_set_background (widget->style, widget->window, widget->state);
4853 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
4854 gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
4857 /* Fill in data after widget has correct style */
4859 /* text properties */
4860 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
4861 /* Reset clist->row_height */
4862 gtk_clist_set_row_height (clist, 0);
4865 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
4870 for (i = 0; i < clist->columns; i++)
4871 if (clist->column[i].auto_resize)
4873 width = gtk_clist_optimal_column_width (clist, i);
4874 if (width != clist->column[i].width)
4875 gtk_clist_set_column_width (clist, i, width);
4881 gtk_clist_button_press (GtkWidget *widget,
4882 GdkEventButton *event)
4890 gint button_actions;
4892 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4893 g_return_val_if_fail (event != NULL, FALSE);
4895 clist = GTK_CLIST (widget);
4897 button_actions = clist->button_actions[event->button - 1];
4899 if (button_actions == GTK_BUTTON_IGNORED)
4902 /* selections on the list */
4903 if (event->window == clist->clist_window)
4908 if (get_selection_info (clist, x, y, &row, &column))
4910 gint old_row = clist->focus_row;
4912 if (clist->focus_row == -1)
4915 if (event->type == GDK_BUTTON_PRESS)
4917 GdkEventMask mask = ((1 << (4 + event->button)) |
4918 GDK_POINTER_MOTION_HINT_MASK |
4919 GDK_BUTTON_RELEASE_MASK);
4921 if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
4922 NULL, NULL, event->time))
4924 gtk_grab_add (widget);
4926 clist->click_cell.row = row;
4927 clist->click_cell.column = column;
4928 clist->drag_button = event->button;
4932 clist->click_cell.row = -1;
4933 clist->click_cell.column = -1;
4935 clist->drag_button = 0;
4936 remove_grab (clist);
4939 if (button_actions & GTK_BUTTON_SELECTS)
4941 if (GTK_CLIST_ADD_MODE(clist))
4943 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
4944 if (GTK_WIDGET_HAS_FOCUS(widget))
4946 gtk_clist_draw_focus (widget);
4947 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4948 GDK_LINE_SOLID, 0, 0);
4949 clist->focus_row = row;
4950 gtk_clist_draw_focus (widget);
4954 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4955 GDK_LINE_SOLID, 0, 0);
4956 clist->focus_row = row;
4959 else if (row != clist->focus_row)
4961 if (GTK_WIDGET_HAS_FOCUS(widget))
4963 gtk_clist_draw_focus (widget);
4964 clist->focus_row = row;
4965 gtk_clist_draw_focus (widget);
4968 clist->focus_row = row;
4972 if (!GTK_WIDGET_HAS_FOCUS(widget))
4973 gtk_widget_grab_focus (widget);
4975 if (button_actions & GTK_BUTTON_SELECTS)
4977 switch (clist->selection_mode)
4979 case GTK_SELECTION_SINGLE:
4980 if (event->type != GDK_BUTTON_PRESS)
4982 gtk_signal_emit (GTK_OBJECT (clist),
4983 clist_signals[SELECT_ROW],
4984 row, column, event);
4988 clist->anchor = row;
4990 case GTK_SELECTION_BROWSE:
4991 gtk_signal_emit (GTK_OBJECT (clist),
4992 clist_signals[SELECT_ROW],
4993 row, column, event);
4995 case GTK_SELECTION_MULTIPLE:
4996 if (event->type != GDK_BUTTON_PRESS)
4998 if (clist->anchor != -1)
5000 update_extended_selection (clist, clist->focus_row);
5001 GTK_CLIST_GET_CLASS (clist)->resync_selection
5002 (clist, (GdkEvent *) event);
5004 gtk_signal_emit (GTK_OBJECT (clist),
5005 clist_signals[SELECT_ROW],
5006 row, column, event);
5010 if (event->state & GDK_CONTROL_MASK)
5012 if (event->state & GDK_SHIFT_MASK)
5014 if (clist->anchor < 0)
5016 g_list_free (clist->undo_selection);
5017 g_list_free (clist->undo_unselection);
5018 clist->undo_selection = NULL;
5019 clist->undo_unselection = NULL;
5020 clist->anchor = old_row;
5021 clist->drag_pos = old_row;
5022 clist->undo_anchor = old_row;
5024 update_extended_selection (clist, clist->focus_row);
5028 if (clist->anchor == -1)
5029 set_anchor (clist, TRUE, row, old_row);
5031 update_extended_selection (clist,
5037 if (event->state & GDK_SHIFT_MASK)
5039 set_anchor (clist, FALSE, old_row, old_row);
5040 update_extended_selection (clist, clist->focus_row);
5044 if (clist->anchor == -1)
5045 set_anchor (clist, FALSE, row, old_row);
5047 update_extended_selection (clist, clist->focus_row);
5057 /* press on resize windows */
5058 for (i = 0; i < clist->columns; i++)
5059 if (clist->column[i].resizeable && clist->column[i].window &&
5060 event->window == clist->column[i].window)
5064 if (gdk_pointer_grab (clist->column[i].window, FALSE,
5065 GDK_POINTER_MOTION_HINT_MASK |
5066 GDK_BUTTON1_MOTION_MASK |
5067 GDK_BUTTON_RELEASE_MASK,
5068 NULL, NULL, event->time))
5071 gtk_grab_add (widget);
5072 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
5074 /* block attached dnd signal handler */
5075 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5077 gtk_signal_handler_block_by_data (GTK_OBJECT (clist), drag_data);
5079 if (!GTK_WIDGET_HAS_FOCUS(widget))
5080 gtk_widget_grab_focus (widget);
5082 clist->drag_pos = i;
5083 clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
5084 clist->column[i].area.width + CELL_SPACING);
5086 if (GTK_CLIST_ADD_MODE(clist))
5087 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
5088 draw_xor_line (clist);
5097 gtk_clist_button_release (GtkWidget *widget,
5098 GdkEventButton *event)
5101 gint button_actions;
5103 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5104 g_return_val_if_fail (event != NULL, FALSE);
5106 clist = GTK_CLIST (widget);
5108 button_actions = clist->button_actions[event->button - 1];
5109 if (button_actions == GTK_BUTTON_IGNORED)
5112 /* release on resize windows */
5113 if (GTK_CLIST_IN_DRAG(clist))
5120 i = clist->drag_pos;
5121 clist->drag_pos = -1;
5123 /* unblock attached dnd signal handler */
5124 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5126 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
5128 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5129 gtk_widget_get_pointer (widget, &x, NULL);
5130 gtk_grab_remove (widget);
5131 gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time);
5133 if (clist->x_drag >= 0)
5134 draw_xor_line (clist);
5136 if (GTK_CLIST_ADD_MODE(clist))
5138 gdk_gc_set_line_attributes (clist->xor_gc, 1,
5139 GDK_LINE_ON_OFF_DASH, 0, 0);
5140 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5143 width = new_column_width (clist, i, &x);
5144 gtk_clist_set_column_width (clist, i, width);
5149 if (clist->drag_button == event->button)
5154 clist->drag_button = 0;
5155 clist->click_cell.row = -1;
5156 clist->click_cell.column = -1;
5158 remove_grab (clist);
5160 if (button_actions & GTK_BUTTON_SELECTS)
5162 switch (clist->selection_mode)
5164 case GTK_SELECTION_MULTIPLE:
5165 if (!(event->state & GDK_SHIFT_MASK) ||
5166 !GTK_WIDGET_CAN_FOCUS (widget) ||
5167 event->x < 0 || event->x >= clist->clist_window_width ||
5168 event->y < 0 || event->y >= clist->clist_window_height)
5169 GTK_CLIST_GET_CLASS (clist)->resync_selection
5170 (clist, (GdkEvent *) event);
5172 case GTK_SELECTION_SINGLE:
5173 if (get_selection_info (clist, event->x, event->y,
5176 if (row >= 0 && row < clist->rows && clist->anchor == row)
5177 toggle_row (clist, row, column, (GdkEvent *) event);
5193 gtk_clist_motion (GtkWidget *widget,
5194 GdkEventMotion *event)
5201 gint button_actions = 0;
5203 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5205 clist = GTK_CLIST (widget);
5206 if (!clist_has_grab (clist))
5209 if (clist->drag_button > 0)
5210 button_actions = clist->button_actions[clist->drag_button - 1];
5212 if (GTK_CLIST_IN_DRAG(clist))
5214 if (event->is_hint || event->window != widget->window)
5215 gtk_widget_get_pointer (widget, &x, NULL);
5219 new_width = new_column_width (clist, clist->drag_pos, &x);
5220 if (x != clist->x_drag)
5222 /* x_drag < 0 indicates that the xor line is already invisible */
5223 if (clist->x_drag >= 0)
5224 draw_xor_line (clist);
5228 if (clist->x_drag >= 0)
5229 draw_xor_line (clist);
5232 if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
5233 clist->column[clist->drag_pos].min_width + 1))
5235 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
5236 gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
5239 if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
5240 new_width >= clist->column[clist->drag_pos].max_width)
5242 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
5243 clist->clist_window_width && x < 0)
5244 move_horizontal (clist,
5245 COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
5246 new_width - clist->clist_window_width +
5247 COLUMN_INSET + CELL_SPACING);
5252 if (event->is_hint || event->window != clist->clist_window)
5253 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
5260 if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
5262 /* delayed drag start */
5263 if (event->window == clist->clist_window &&
5264 clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
5265 (y < 0 || y >= clist->clist_window_height ||
5266 x < 0 || x >= clist->clist_window_width ||
5267 y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
5268 y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
5269 clist->row_height) ||
5270 x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
5271 x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) +
5272 clist->column[clist->click_cell.column].area.width)))
5274 GtkTargetList *target_list;
5276 target_list = gtk_target_list_new (&clist_target_table, 1);
5277 gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
5278 clist->drag_button, (GdkEvent *)event);
5284 /* horizontal autoscrolling */
5285 if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
5286 (x < 0 || x >= clist->clist_window_width))
5291 clist->htimer = gtk_timeout_add
5292 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
5294 if (!((x < 0 && clist->hadjustment->value == 0) ||
5295 (x >= clist->clist_window_width &&
5296 clist->hadjustment->value ==
5297 LIST_WIDTH (clist) - clist->clist_window_width)))
5300 move_horizontal (clist, -1 + (x/2));
5302 move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
5306 if (GTK_CLIST_IN_DRAG(clist))
5309 /* vertical autoscrolling */
5310 row = ROW_FROM_YPIXEL (clist, y);
5312 /* don't scroll on last pixel row if it's a cell spacing */
5313 if (y == clist->clist_window_height - 1 &&
5314 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
5317 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
5318 (y < 0 || y >= clist->clist_window_height))
5323 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
5324 (GtkFunction) vertical_timeout, clist);
5326 if (clist->drag_button &&
5327 ((y < 0 && clist->focus_row == 0) ||
5328 (y >= clist->clist_window_height &&
5329 clist->focus_row == clist->rows - 1)))
5333 row = CLAMP (row, 0, clist->rows - 1);
5335 if (button_actions & GTK_BUTTON_SELECTS &
5336 !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
5338 if (row == clist->focus_row)
5341 gtk_clist_draw_focus (widget);
5342 clist->focus_row = row;
5343 gtk_clist_draw_focus (widget);
5345 switch (clist->selection_mode)
5347 case GTK_SELECTION_BROWSE:
5348 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5349 clist->focus_row, -1, event);
5351 case GTK_SELECTION_MULTIPLE:
5352 update_extended_selection (clist, clist->focus_row);
5359 if (ROW_TOP_YPIXEL(clist, row) < 0)
5360 move_vertical (clist, row, 0);
5361 else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
5362 clist->clist_window_height)
5363 move_vertical (clist, row, 1);
5369 gtk_clist_size_request (GtkWidget *widget,
5370 GtkRequisition *requisition)
5375 g_return_if_fail (GTK_IS_CLIST (widget));
5376 g_return_if_fail (requisition != NULL);
5378 clist = GTK_CLIST (widget);
5380 requisition->width = 0;
5381 requisition->height = 0;
5383 /* compute the size of the column title (title) area */
5384 clist->column_title_area.height = 0;
5385 if (GTK_CLIST_SHOW_TITLES(clist))
5386 for (i = 0; i < clist->columns; i++)
5387 if (clist->column[i].button)
5389 GtkRequisition child_requisition;
5391 gtk_widget_size_request (clist->column[i].button,
5392 &child_requisition);
5393 clist->column_title_area.height =
5394 MAX (clist->column_title_area.height,
5395 child_requisition.height);
5398 requisition->width += (widget->style->xthickness +
5399 GTK_CONTAINER (widget)->border_width) * 2;
5400 requisition->height += (clist->column_title_area.height +
5401 (widget->style->ythickness +
5402 GTK_CONTAINER (widget)->border_width) * 2);
5404 /* if (!clist->hadjustment) */
5405 requisition->width += list_requisition_width (clist);
5406 /* if (!clist->vadjustment) */
5407 requisition->height += LIST_HEIGHT (clist);
5411 gtk_clist_size_allocate (GtkWidget *widget,
5412 GtkAllocation *allocation)
5415 GtkAllocation clist_allocation;
5418 g_return_if_fail (GTK_IS_CLIST (widget));
5419 g_return_if_fail (allocation != NULL);
5421 clist = GTK_CLIST (widget);
5422 widget->allocation = *allocation;
5423 border_width = GTK_CONTAINER (widget)->border_width;
5425 if (GTK_WIDGET_REALIZED (widget))
5427 gdk_window_move_resize (widget->window,
5428 allocation->x + border_width,
5429 allocation->y + border_width,
5430 allocation->width - border_width * 2,
5431 allocation->height - border_width * 2);
5434 /* use internal allocation structure for all the math
5435 * because it's easier than always subtracting the container
5437 clist->internal_allocation.x = 0;
5438 clist->internal_allocation.y = 0;
5439 clist->internal_allocation.width = MAX (1, (gint)allocation->width -
5441 clist->internal_allocation.height = MAX (1, (gint)allocation->height -
5444 /* allocate clist window assuming no scrollbars */
5445 clist_allocation.x = (clist->internal_allocation.x +
5446 widget->style->xthickness);
5447 clist_allocation.y = (clist->internal_allocation.y +
5448 widget->style->ythickness +
5449 clist->column_title_area.height);
5450 clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width -
5451 (2 * (gint)widget->style->xthickness));
5452 clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
5453 (2 * (gint)widget->style->ythickness) -
5454 (gint)clist->column_title_area.height);
5456 clist->clist_window_width = clist_allocation.width;
5457 clist->clist_window_height = clist_allocation.height;
5459 if (GTK_WIDGET_REALIZED (widget))
5461 gdk_window_move_resize (clist->clist_window,
5464 clist_allocation.width,
5465 clist_allocation.height);
5468 /* position the window which holds the column title buttons */
5469 clist->column_title_area.x = widget->style->xthickness;
5470 clist->column_title_area.y = widget->style->ythickness;
5471 clist->column_title_area.width = clist_allocation.width;
5473 if (GTK_WIDGET_REALIZED (widget))
5475 gdk_window_move_resize (clist->title_window,
5476 clist->column_title_area.x,
5477 clist->column_title_area.y,
5478 clist->column_title_area.width,
5479 clist->column_title_area.height);
5482 /* column button allocation */
5483 size_allocate_columns (clist, FALSE);
5484 size_allocate_title_buttons (clist);
5486 adjust_adjustments (clist, TRUE);
5493 gtk_clist_forall (GtkContainer *container,
5494 gboolean include_internals,
5495 GtkCallback callback,
5496 gpointer callback_data)
5501 g_return_if_fail (GTK_IS_CLIST (container));
5502 g_return_if_fail (callback != NULL);
5504 if (!include_internals)
5507 clist = GTK_CLIST (container);
5509 /* callback for the column buttons */
5510 for (i = 0; i < clist->columns; i++)
5511 if (clist->column[i].button)
5512 (*callback) (clist->column[i].button, callback_data);
5515 /* PRIVATE DRAWING FUNCTIONS
5524 get_cell_style (GtkCList *clist,
5525 GtkCListRow *clist_row,
5534 if ((state == GTK_STATE_NORMAL) &&
5535 (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
5536 fg_state = GTK_STATE_INSENSITIVE;
5540 if (clist_row->cell[column].style)
5543 *style = clist_row->cell[column].style;
5545 *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
5547 if (state == GTK_STATE_SELECTED)
5548 *bg_gc = clist_row->cell[column].style->bg_gc[state];
5550 *bg_gc = clist_row->cell[column].style->base_gc[state];
5553 else if (clist_row->style)
5556 *style = clist_row->style;
5558 *fg_gc = clist_row->style->fg_gc[fg_state];
5560 if (state == GTK_STATE_SELECTED)
5561 *bg_gc = clist_row->style->bg_gc[state];
5563 *bg_gc = clist_row->style->base_gc[state];
5569 *style = GTK_WIDGET (clist)->style;
5571 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
5573 if (state == GTK_STATE_SELECTED)
5574 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
5576 *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
5579 if (state != GTK_STATE_SELECTED)
5581 if (fg_gc && clist_row->fg_set)
5582 *fg_gc = clist->fg_gc;
5583 if (bg_gc && clist_row->bg_set)
5584 *bg_gc = clist->bg_gc;
5590 draw_cell_pixmap (GdkWindow *window,
5591 GdkRectangle *clip_rectangle,
5605 gdk_gc_set_clip_mask (fg_gc, mask);
5606 gdk_gc_set_clip_origin (fg_gc, x, y);
5609 if (x < clip_rectangle->x)
5611 xsrc = clip_rectangle->x - x;
5613 x = clip_rectangle->x;
5615 if (x + width > clip_rectangle->x + clip_rectangle->width)
5616 width = clip_rectangle->x + clip_rectangle->width - x;
5618 if (y < clip_rectangle->y)
5620 ysrc = clip_rectangle->y - y;
5622 y = clip_rectangle->y;
5624 if (y + height > clip_rectangle->y + clip_rectangle->height)
5625 height = clip_rectangle->y + clip_rectangle->height - y;
5627 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
5628 gdk_gc_set_clip_origin (fg_gc, 0, 0);
5630 gdk_gc_set_clip_mask (fg_gc, NULL);
5632 return x + MAX (width, 0);
5636 draw_row (GtkCList *clist,
5639 GtkCListRow *clist_row)
5643 GdkRectangle row_rectangle;
5644 GdkRectangle cell_rectangle;
5645 GdkRectangle clip_rectangle;
5646 GdkRectangle intersect_rectangle;
5651 g_return_if_fail (clist != NULL);
5653 /* bail now if we arn't drawable yet */
5654 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
5657 widget = GTK_WIDGET (clist);
5659 /* if the function is passed the pointer to the row instead of null,
5660 * it avoids this expensive lookup */
5662 clist_row = ROW_ELEMENT (clist, row)->data;
5664 /* rectangle of the entire row */
5665 row_rectangle.x = 0;
5666 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
5667 row_rectangle.width = clist->clist_window_width;
5668 row_rectangle.height = clist->row_height;
5670 /* rectangle of the cell spacing above the row */
5671 cell_rectangle.x = 0;
5672 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
5673 cell_rectangle.width = row_rectangle.width;
5674 cell_rectangle.height = CELL_SPACING;
5676 /* rectangle used to clip drawing operations, its y and height
5677 * positions only need to be set once, so we set them once here.
5678 * the x and width are set withing the drawing loop below once per
5680 clip_rectangle.y = row_rectangle.y;
5681 clip_rectangle.height = row_rectangle.height;
5683 if (clist_row->state == GTK_STATE_NORMAL)
5685 if (clist_row->fg_set)
5686 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
5687 if (clist_row->bg_set)
5688 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
5691 state = clist_row->state;
5693 /* draw the cell borders and background */
5696 rect = &intersect_rectangle;
5697 if (gdk_rectangle_intersect (area, &cell_rectangle,
5698 &intersect_rectangle))
5699 gdk_draw_rectangle (clist->clist_window,
5700 widget->style->base_gc[GTK_STATE_NORMAL],
5702 intersect_rectangle.x,
5703 intersect_rectangle.y,
5704 intersect_rectangle.width,
5705 intersect_rectangle.height);
5707 /* the last row has to clear its bottom cell spacing too */
5708 if (clist_row == clist->row_list_end->data)
5710 cell_rectangle.y += clist->row_height + CELL_SPACING;
5712 if (gdk_rectangle_intersect (area, &cell_rectangle,
5713 &intersect_rectangle))
5714 gdk_draw_rectangle (clist->clist_window,
5715 widget->style->base_gc[GTK_STATE_NORMAL],
5717 intersect_rectangle.x,
5718 intersect_rectangle.y,
5719 intersect_rectangle.width,
5720 intersect_rectangle.height);
5723 if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
5729 rect = &clip_rectangle;
5730 gdk_draw_rectangle (clist->clist_window,
5731 widget->style->base_gc[GTK_STATE_NORMAL],
5735 cell_rectangle.width,
5736 cell_rectangle.height);
5738 /* the last row has to clear its bottom cell spacing too */
5739 if (clist_row == clist->row_list_end->data)
5741 cell_rectangle.y += clist->row_height + CELL_SPACING;
5743 gdk_draw_rectangle (clist->clist_window,
5744 widget->style->base_gc[GTK_STATE_NORMAL],
5748 cell_rectangle.width,
5749 cell_rectangle.height);
5753 for (last_column = clist->columns - 1;
5754 last_column >= 0 && !clist->column[last_column].visible; last_column--)
5757 /* iterate and draw all the columns (row cells) and draw their contents */
5758 for (i = 0; i < clist->columns; i++)
5763 PangoLayout *layout;
5764 PangoRectangle logical_rect;
5771 if (!clist->column[i].visible)
5774 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
5776 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
5777 clip_rectangle.width = clist->column[i].area.width;
5779 /* calculate clipping region clipping region */
5780 clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
5781 clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
5782 (i == last_column) * CELL_SPACING);
5784 if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
5785 &intersect_rectangle))
5788 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
5789 rect->x, rect->y, rect->width, rect->height);
5791 clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
5792 clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
5793 (i == last_column) * CELL_SPACING);
5796 /* calculate real width for column justification */
5798 layout = _gtk_clist_create_cell_layout (clist, clist_row, i);
5801 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
5802 width = logical_rect.width;
5809 switch (clist_row->cell[i].type)
5811 case GTK_CELL_PIXMAP:
5812 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5813 &pixmap_width, &height);
5814 width += pixmap_width;
5816 case GTK_CELL_PIXTEXT:
5817 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5818 &pixmap_width, &height);
5819 width += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
5825 switch (clist->column[i].justification)
5827 case GTK_JUSTIFY_LEFT:
5828 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
5830 case GTK_JUSTIFY_RIGHT:
5831 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5832 clip_rectangle.width - width);
5834 case GTK_JUSTIFY_CENTER:
5835 case GTK_JUSTIFY_FILL:
5836 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5837 (clip_rectangle.width / 2) - (width / 2));
5841 /* Draw Text and/or Pixmap */
5842 switch (clist_row->cell[i].type)
5844 case GTK_CELL_PIXMAP:
5845 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5846 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5847 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
5849 clip_rectangle.y + clist_row->cell[i].vertical +
5850 (clip_rectangle.height - height) / 2,
5851 pixmap_width, height);
5853 case GTK_CELL_PIXTEXT:
5855 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5856 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5857 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
5859 clip_rectangle.y + clist_row->cell[i].vertical+
5860 (clip_rectangle.height - height) / 2,
5861 pixmap_width, height);
5862 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
5868 gint row_center_offset = (clist->row_height - logical_rect.height - 1) / 2;
5870 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
5871 gdk_draw_layout (clist->clist_window, fg_gc,
5873 row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
5875 g_object_unref (G_OBJECT (layout));
5876 gdk_gc_set_clip_rectangle (fg_gc, NULL);
5884 /* draw focus rectangle */
5885 if (clist->focus_row == row &&
5886 GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
5889 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5890 row_rectangle.x, row_rectangle.y,
5891 row_rectangle.width - 1, row_rectangle.height - 1);
5892 else if (gdk_rectangle_intersect (area, &row_rectangle,
5893 &intersect_rectangle))
5895 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
5896 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5897 row_rectangle.x, row_rectangle.y,
5898 row_rectangle.width - 1,
5899 row_rectangle.height - 1);
5900 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
5906 draw_rows (GtkCList *clist,
5910 GtkCListRow *clist_row;
5915 g_return_if_fail (GTK_IS_CLIST (clist));
5917 if (clist->row_height == 0 ||
5918 !GTK_WIDGET_DRAWABLE (clist))
5923 first_row = ROW_FROM_YPIXEL (clist, area->y);
5924 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
5928 first_row = ROW_FROM_YPIXEL (clist, 0);
5929 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
5932 /* this is a small special case which exposes the bottom cell line
5933 * on the last row -- it might go away if I change the wall the cell
5934 * spacings are drawn
5936 if (clist->rows == first_row)
5939 list = ROW_ELEMENT (clist, first_row);
5943 clist_row = list->data;
5949 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, area, i, clist_row);
5954 gdk_window_clear_area (clist->clist_window, 0,
5955 ROW_TOP_YPIXEL (clist, i), 0, 0);
5959 draw_xor_line (GtkCList *clist)
5963 g_return_if_fail (clist != NULL);
5965 widget = GTK_WIDGET (clist);
5967 gdk_draw_line (widget->window, clist->xor_gc,
5969 widget->style->ythickness,
5971 clist->column_title_area.height +
5972 clist->clist_window_height + 1);
5976 clist_refresh (GtkCList *clist)
5978 g_return_if_fail (GTK_IS_CLIST (clist));
5980 if (CLIST_UNFROZEN (clist))
5982 adjust_adjustments (clist, FALSE);
5983 draw_rows (clist, NULL);
5987 /* get cell from coordinates
5988 * get_selection_info
5989 * gtk_clist_get_selection_info
5992 get_selection_info (GtkCList *clist,
6000 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
6002 /* bounds checking, return false if the user clicked
6003 * on a blank area */
6004 trow = ROW_FROM_YPIXEL (clist, y);
6005 if (trow >= clist->rows)
6011 tcol = COLUMN_FROM_XPIXEL (clist, x);
6012 if (tcol >= clist->columns)
6022 gtk_clist_get_selection_info (GtkCList *clist,
6028 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
6029 return get_selection_info (clist, x, y, row, column);
6032 /* PRIVATE ADJUSTMENT FUNCTIONS
6033 * adjust_adjustments
6034 * vadjustment_changed
6035 * hadjustment_changed
6036 * vadjustment_value_changed
6037 * hadjustment_value_changed
6041 adjust_adjustments (GtkCList *clist,
6042 gboolean block_resize)
6044 if (clist->vadjustment)
6046 clist->vadjustment->page_size = clist->clist_window_height;
6047 clist->vadjustment->step_increment = clist->row_height;
6048 clist->vadjustment->page_increment =
6049 MAX (clist->vadjustment->page_size - clist->vadjustment->step_increment,
6050 clist->vadjustment->page_size / 2);
6051 clist->vadjustment->lower = 0;
6052 clist->vadjustment->upper = LIST_HEIGHT (clist);
6054 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist) ||
6055 (clist->voffset + (gint)clist->vadjustment->value) != 0)
6057 clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
6058 clist->clist_window_height));
6059 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
6062 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
6065 if (clist->hadjustment)
6067 clist->hadjustment->page_size = clist->clist_window_width;
6068 clist->hadjustment->step_increment = 10;
6069 clist->vadjustment->page_increment =
6070 MAX (clist->vadjustment->page_size - clist->vadjustment->step_increment,
6071 clist->vadjustment->page_size / 2);
6072 clist->hadjustment->lower = 0;
6073 clist->hadjustment->upper = LIST_WIDTH (clist);
6075 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist) ||
6076 (clist->hoffset + (gint)clist->hadjustment->value) != 0)
6078 clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
6079 clist->clist_window_width));
6080 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
6083 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
6086 if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
6089 GtkRequisition requisition;
6091 widget = GTK_WIDGET (clist);
6092 gtk_widget_size_request (widget, &requisition);
6094 if ((!clist->hadjustment &&
6095 requisition.width != widget->allocation.width) ||
6096 (!clist->vadjustment &&
6097 requisition.height != widget->allocation.height))
6098 gtk_widget_queue_resize (widget);
6103 vadjustment_changed (GtkAdjustment *adjustment,
6108 g_return_if_fail (adjustment != NULL);
6109 g_return_if_fail (data != NULL);
6111 clist = GTK_CLIST (data);
6115 hadjustment_changed (GtkAdjustment *adjustment,
6120 g_return_if_fail (adjustment != NULL);
6121 g_return_if_fail (data != NULL);
6123 clist = GTK_CLIST (data);
6127 vadjustment_value_changed (GtkAdjustment *adjustment,
6133 g_return_if_fail (adjustment != NULL);
6134 g_return_if_fail (GTK_IS_CLIST (data));
6136 clist = GTK_CLIST (data);
6138 if (adjustment != clist->vadjustment)
6141 value = -adjustment->value;
6142 dy = value - clist->voffset;
6143 clist->voffset = value;
6145 if (GTK_WIDGET_DRAWABLE (clist))
6147 gdk_window_scroll (clist->clist_window, 0, dy);
6148 gdk_window_process_updates (clist->clist_window, FALSE);
6160 /* The window to which widget->window is relative */
6161 #define ALLOCATION_WINDOW(widget) \
6162 (GTK_WIDGET_NO_WINDOW (widget) ? \
6163 (widget)->window : \
6164 gdk_window_get_parent ((widget)->window))
6167 adjust_allocation_recurse (GtkWidget *widget,
6170 ScrollData *scroll_data = data;
6172 if (!GTK_WIDGET_REALIZED (widget))
6174 if (GTK_WIDGET_VISIBLE (widget))
6176 GdkRectangle tmp_rectangle = widget->allocation;
6177 tmp_rectangle.x += scroll_data->dx;
6179 gtk_widget_size_allocate (widget, &tmp_rectangle);
6184 if (ALLOCATION_WINDOW (widget) == scroll_data->window)
6186 widget->allocation.x += scroll_data->dx;
6188 if (GTK_IS_CONTAINER (widget))
6189 gtk_container_forall (GTK_CONTAINER (widget),
6190 adjust_allocation_recurse,
6197 adjust_allocation (GtkWidget *widget,
6200 ScrollData scroll_data;
6202 if (GTK_WIDGET_REALIZED (widget))
6203 scroll_data.window = ALLOCATION_WINDOW (widget);
6205 scroll_data.window = NULL;
6207 scroll_data.dx = dx;
6209 adjust_allocation_recurse (widget, &scroll_data);
6213 hadjustment_value_changed (GtkAdjustment *adjustment,
6217 GtkContainer *container;
6224 g_return_if_fail (adjustment != NULL);
6225 g_return_if_fail (GTK_IS_CLIST (data));
6227 clist = GTK_CLIST (data);
6228 container = GTK_CONTAINER (data);
6230 if (adjustment != clist->hadjustment)
6233 value = adjustment->value;
6235 dx = -value - clist->hoffset;
6237 if (GTK_WIDGET_REALIZED (clist))
6238 gdk_window_scroll (clist->title_window, dx, 0);
6240 /* adjust the column button's allocations */
6241 for (i = 0; i < clist->columns; i++)
6242 if (clist->column[i].button)
6243 adjust_allocation (clist->column[i].button, dx);
6245 clist->hoffset = -value;
6247 if (GTK_WIDGET_DRAWABLE (clist))
6249 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6250 !container->focus_child && GTK_CLIST_ADD_MODE(clist))
6252 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6254 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
6255 clist->clist_window_width - 1,
6256 clist->row_height - 1);
6259 gdk_window_scroll (clist->clist_window, dx, 0);
6260 gdk_window_process_updates (clist->clist_window, FALSE);
6262 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6263 !container->focus_child)
6265 if (GTK_CLIST_ADD_MODE(clist))
6269 focus_row = clist->focus_row;
6270 clist->focus_row = -1;
6271 draw_rows (clist, &area);
6272 clist->focus_row = focus_row;
6274 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
6275 FALSE, 0, y, clist->clist_window_width - 1,
6276 clist->row_height - 1);
6279 else if (ABS(dx) < clist->clist_window_width - 1)
6286 x0 = clist->clist_window_width - 1;
6292 x1 = clist->clist_window_width - 1 + dx;
6295 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6296 gdk_draw_line (clist->clist_window, clist->xor_gc,
6297 x0, y + 1, x0, y + clist->row_height - 2);
6298 gdk_draw_line (clist->clist_window, clist->xor_gc,
6299 x1, y + 1, x1, y + clist->row_height - 2);
6306 * Memory Allocation/Distruction Routines for GtkCList stuctures
6315 static GtkCListColumn *
6316 columns_new (GtkCList *clist)
6318 GtkCListColumn *column;
6321 column = g_new (GtkCListColumn, clist->columns);
6323 for (i = 0; i < clist->columns; i++)
6325 column[i].area.x = 0;
6326 column[i].area.y = 0;
6327 column[i].area.width = 0;
6328 column[i].area.height = 0;
6329 column[i].title = NULL;
6330 column[i].button = NULL;
6331 column[i].window = NULL;
6332 column[i].width = 0;
6333 column[i].min_width = -1;
6334 column[i].max_width = -1;
6335 column[i].visible = TRUE;
6336 column[i].width_set = FALSE;
6337 column[i].resizeable = TRUE;
6338 column[i].auto_resize = FALSE;
6339 column[i].button_passive = FALSE;
6340 column[i].justification = GTK_JUSTIFY_LEFT;
6347 column_title_new (GtkCList *clist,
6351 if (clist->column[column].title)
6352 g_free (clist->column[column].title);
6354 clist->column[column].title = g_strdup (title);
6358 columns_delete (GtkCList *clist)
6362 for (i = 0; i < clist->columns; i++)
6363 if (clist->column[i].title)
6364 g_free (clist->column[i].title);
6366 g_free (clist->column);
6369 static GtkCListRow *
6370 row_new (GtkCList *clist)
6373 GtkCListRow *clist_row;
6375 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
6376 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
6378 for (i = 0; i < clist->columns; i++)
6380 clist_row->cell[i].type = GTK_CELL_EMPTY;
6381 clist_row->cell[i].vertical = 0;
6382 clist_row->cell[i].horizontal = 0;
6383 clist_row->cell[i].style = NULL;
6386 clist_row->fg_set = FALSE;
6387 clist_row->bg_set = FALSE;
6388 clist_row->style = NULL;
6389 clist_row->selectable = TRUE;
6390 clist_row->state = GTK_STATE_NORMAL;
6391 clist_row->data = NULL;
6392 clist_row->destroy = NULL;
6398 row_delete (GtkCList *clist,
6399 GtkCListRow *clist_row)
6403 for (i = 0; i < clist->columns; i++)
6405 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
6406 (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
6407 if (clist_row->cell[i].style)
6409 if (GTK_WIDGET_REALIZED (clist))
6410 gtk_style_detach (clist_row->cell[i].style);
6411 g_object_unref (clist_row->cell[i].style);
6415 if (clist_row->style)
6417 if (GTK_WIDGET_REALIZED (clist))
6418 gtk_style_detach (clist_row->style);
6419 g_object_unref (clist_row->style);
6422 if (clist_row->destroy)
6423 clist_row->destroy (clist_row->data);
6425 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
6426 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
6430 * gtk_clist_focus_content_area
6432 * gtk_clist_draw_focus
6433 * gtk_clist_focus_in
6434 * gtk_clist_focus_out
6438 gtk_clist_focus_content_area (GtkCList *clist)
6440 if (clist->focus_row < 0)
6442 clist->focus_row = 0;
6444 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
6445 clist->selection_mode == GTK_SELECTION_MULTIPLE) &&
6447 gtk_signal_emit (GTK_OBJECT (clist),
6448 clist_signals[SELECT_ROW],
6449 clist->focus_row, -1, NULL);
6451 gtk_widget_grab_focus (GTK_WIDGET (clist));
6455 gtk_clist_focus (GtkWidget *widget,
6456 GtkDirectionType direction)
6458 GtkCList *clist = GTK_CLIST (widget);
6459 GtkWidget *focus_child;
6460 gboolean is_current_focus;
6462 if (!GTK_WIDGET_IS_SENSITIVE (widget))
6465 focus_child = GTK_CONTAINER (widget)->focus_child;
6467 is_current_focus = gtk_widget_is_focus (GTK_WIDGET (clist));
6470 gtk_widget_child_focus (focus_child, direction))
6479 if (title_focus_move (clist, direction))
6482 else if (!is_current_focus)
6484 gtk_clist_focus_content_area (clist);
6489 case GTK_DIR_TAB_FORWARD:
6490 if (!focus_child && !is_current_focus)
6492 if (title_focus_in (clist, direction))
6496 if (!is_current_focus && clist->rows)
6498 gtk_clist_focus_content_area (clist);
6503 case GTK_DIR_TAB_BACKWARD:
6504 if (!focus_child && is_current_focus)
6506 if (title_focus_in (clist, direction))
6510 if (!is_current_focus && !focus_child && clist->rows)
6512 gtk_clist_focus_content_area (clist);
6524 gtk_clist_set_focus_child (GtkContainer *container,
6527 GtkCList *clist = GTK_CLIST (container);
6530 for (i = 0; i < clist->columns; i++)
6531 if (clist->column[i].button == child)
6532 clist->focus_header_column = i;
6534 parent_class->set_focus_child (container, child);
6538 gtk_clist_draw_focus (GtkWidget *widget)
6542 g_return_if_fail (GTK_IS_CLIST (widget));
6544 if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
6547 clist = GTK_CLIST (widget);
6548 if (clist->focus_row >= 0)
6549 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
6550 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
6551 clist->clist_window_width - 1,
6552 clist->row_height - 1);
6556 gtk_clist_focus_in (GtkWidget *widget,
6557 GdkEventFocus *event)
6559 GtkCList *clist = GTK_CLIST (widget);
6561 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
6562 clist->selection == NULL && clist->focus_row > -1)
6566 list = g_list_nth (clist->row_list, clist->focus_row);
6567 if (list && GTK_CLIST_ROW (list)->selectable)
6568 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6569 clist->focus_row, -1, event);
6571 gtk_clist_draw_focus (widget);
6574 gtk_clist_draw_focus (widget);
6580 gtk_clist_focus_out (GtkWidget *widget,
6581 GdkEventFocus *event)
6583 GtkCList *clist = GTK_CLIST (widget);
6585 gtk_clist_draw_focus (widget);
6587 GTK_CLIST_GET_CLASS (widget)->resync_selection (clist, (GdkEvent *) event);
6593 focus_column (GtkCList *clist, gint column, gint dir)
6595 GtkWidget *child = clist->column[column].button;
6597 if (gtk_widget_child_focus (child, dir))
6601 else if (GTK_WIDGET_CAN_FOCUS (child))
6603 gtk_widget_grab_focus (child);
6610 /* Focus moved onto the headers. Focus first focusable and visible child.
6611 * (FIXME: focus the last focused child if visible)
6614 title_focus_in (GtkCList *clist, gint dir)
6619 if (!GTK_CLIST_SHOW_TITLES (clist))
6622 /* Check last focused column */
6623 if (clist->focus_header_column != -1)
6625 i = clist->focus_header_column;
6627 left = COLUMN_LEFT_XPIXEL (clist, i);
6628 right = left + clist->column[i].area.width;
6630 if (left >= 0 && right <= clist->clist_window_width)
6632 if (focus_column (clist, i, dir))
6637 /* Check fully visible columns */
6638 for (i = 0 ; i < clist->columns ; i++)
6640 left = COLUMN_LEFT_XPIXEL (clist, i);
6641 right = left + clist->column[i].area.width;
6643 if (left >= 0 && right <= clist->clist_window_width)
6645 if (focus_column (clist, i, dir))
6650 /* Check partially visible columns */
6651 for (i = 0 ; i < clist->columns ; i++)
6653 left = COLUMN_LEFT_XPIXEL (clist, i);
6654 right = left + clist->column[i].area.width;
6656 if ((left < 0 && right > 0) ||
6657 (left < clist->clist_window_width && right > clist->clist_window_width))
6659 if (focus_column (clist, i, dir))
6667 /* Move the focus right or left within the title buttons, scrolling
6668 * as necessary to keep the focused child visible.
6671 title_focus_move (GtkCList *clist,
6674 GtkWidget *focus_child;
6675 gboolean return_val = FALSE;
6680 if (!GTK_CLIST_SHOW_TITLES(clist))
6683 focus_child = GTK_CONTAINER (clist)->focus_child;
6684 g_assert (focus_child);
6686 /* Movement direction within headers
6698 for (i = 0; i < clist->columns; i++)
6699 if (clist->column[i].button == focus_child)
6702 g_assert (i != -1); /* Have a starting column */
6705 while (!return_val && j >= 0 && j < clist->columns)
6707 if (clist->column[j].button &&
6708 GTK_WIDGET_VISIBLE (clist->column[j].button))
6710 if (focus_column (clist, j, dir))
6719 /* If we didn't find it, wrap around and keep looking
6723 j = d > 0 ? 0 : clist->columns - 1;
6725 while (!return_val && j != i)
6727 if (clist->column[j].button &&
6728 GTK_WIDGET_VISIBLE (clist->column[j].button))
6730 if (focus_column (clist, j, dir))
6740 /* Scroll horizontally so focused column is visible
6744 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
6745 gtk_clist_moveto (clist, -1, j, 0, 0);
6746 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
6747 clist->clist_window_width)
6751 for (last_column = clist->columns - 1;
6752 last_column >= 0 && !clist->column[last_column].visible; last_column--);
6754 if (j == last_column)
6755 gtk_clist_moveto (clist, -1, j, 0, 0);
6757 gtk_clist_moveto (clist, -1, j, 0, 1);
6760 return TRUE; /* Even if we didn't find a new one, we can keep the
6761 * focus in the same place.
6765 /* PRIVATE SCROLLING FUNCTIONS
6771 * horizontal_timeout
6776 move_focus_row (GtkCList *clist,
6777 GtkScrollType scroll_type,
6782 g_return_if_fail (clist != 0);
6783 g_return_if_fail (GTK_IS_CLIST (clist));
6785 widget = GTK_WIDGET (clist);
6787 switch (scroll_type)
6789 case GTK_SCROLL_STEP_UP:
6790 case GTK_SCROLL_STEP_BACKWARD:
6791 if (clist->focus_row <= 0)
6793 gtk_clist_draw_focus (widget);
6795 gtk_clist_draw_focus (widget);
6798 case GTK_SCROLL_STEP_DOWN:
6799 case GTK_SCROLL_STEP_FORWARD:
6800 if (clist->focus_row >= clist->rows - 1)
6802 gtk_clist_draw_focus (widget);
6804 gtk_clist_draw_focus (widget);
6806 case GTK_SCROLL_PAGE_UP:
6807 case GTK_SCROLL_PAGE_BACKWARD:
6808 if (clist->focus_row <= 0)
6810 gtk_clist_draw_focus (widget);
6811 clist->focus_row = MAX (0, clist->focus_row -
6812 (2 * clist->clist_window_height -
6813 clist->row_height - CELL_SPACING) /
6814 (2 * (clist->row_height + CELL_SPACING)));
6815 gtk_clist_draw_focus (widget);
6817 case GTK_SCROLL_PAGE_DOWN:
6818 case GTK_SCROLL_PAGE_FORWARD:
6819 if (clist->focus_row >= clist->rows - 1)
6821 gtk_clist_draw_focus (widget);
6822 clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
6823 (2 * clist->clist_window_height -
6824 clist->row_height - CELL_SPACING) /
6825 (2 * (clist->row_height + CELL_SPACING)));
6826 gtk_clist_draw_focus (widget);
6828 case GTK_SCROLL_JUMP:
6829 if (position >= 0 && position <= 1)
6831 gtk_clist_draw_focus (widget);
6832 clist->focus_row = position * (clist->rows - 1);
6833 gtk_clist_draw_focus (widget);
6842 scroll_horizontal (GtkCList *clist,
6843 GtkScrollType scroll_type,
6849 g_return_if_fail (clist != 0);
6850 g_return_if_fail (GTK_IS_CLIST (clist));
6852 if (clist_has_grab (clist))
6855 for (last_column = clist->columns - 1;
6856 last_column >= 0 && !clist->column[last_column].visible; last_column--)
6859 switch (scroll_type)
6861 case GTK_SCROLL_STEP_BACKWARD:
6862 column = COLUMN_FROM_XPIXEL (clist, 0);
6863 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
6867 case GTK_SCROLL_STEP_FORWARD:
6868 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
6871 if (COLUMN_LEFT_XPIXEL (clist, column) +
6872 clist->column[column].area.width +
6873 CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
6874 column < last_column)
6877 case GTK_SCROLL_PAGE_BACKWARD:
6878 case GTK_SCROLL_PAGE_FORWARD:
6880 case GTK_SCROLL_JUMP:
6881 if (position >= 0 && position <= 1)
6883 gint vis_columns = 0;
6886 for (i = 0; i <= last_column; i++)
6887 if (clist->column[i].visible)
6890 column = position * vis_columns;
6892 for (i = 0; i <= last_column && column > 0; i++)
6893 if (clist->column[i].visible)
6905 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
6906 gtk_clist_moveto (clist, -1, column, 0, 0);
6907 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
6908 + clist->column[column].area.width > clist->clist_window_width)
6910 if (column == last_column)
6911 gtk_clist_moveto (clist, -1, column, 0, 0);
6913 gtk_clist_moveto (clist, -1, column, 0, 1);
6918 scroll_vertical (GtkCList *clist,
6919 GtkScrollType scroll_type,
6924 g_return_if_fail (GTK_IS_CLIST (clist));
6926 if (clist_has_grab (clist))
6929 switch (clist->selection_mode)
6931 case GTK_SELECTION_MULTIPLE:
6932 if (clist->anchor >= 0)
6934 case GTK_SELECTION_BROWSE:
6936 old_focus_row = clist->focus_row;
6937 move_focus_row (clist, scroll_type, position);
6939 if (old_focus_row != clist->focus_row)
6941 if (clist->selection_mode == GTK_SELECTION_BROWSE)
6942 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
6943 old_focus_row, -1, NULL);
6944 else if (!GTK_CLIST_ADD_MODE(clist))
6946 gtk_clist_unselect_all (clist);
6947 clist->undo_anchor = old_focus_row;
6951 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
6953 case GTK_VISIBILITY_NONE:
6954 if (old_focus_row != clist->focus_row &&
6955 !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
6956 GTK_CLIST_ADD_MODE(clist)))
6957 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6958 clist->focus_row, -1, NULL);
6959 switch (scroll_type)
6961 case GTK_SCROLL_PAGE_UP:
6962 case GTK_SCROLL_STEP_UP:
6963 case GTK_SCROLL_STEP_BACKWARD:
6964 case GTK_SCROLL_PAGE_BACKWARD:
6965 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6967 case GTK_SCROLL_PAGE_DOWN:
6968 case GTK_SCROLL_STEP_DOWN:
6969 case GTK_SCROLL_STEP_FORWARD:
6970 case GTK_SCROLL_PAGE_FORWARD:
6971 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6973 case GTK_SCROLL_JUMP:
6974 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
6980 case GTK_VISIBILITY_PARTIAL:
6981 switch (scroll_type)
6983 case GTK_SCROLL_STEP_BACKWARD:
6984 case GTK_SCROLL_PAGE_BACKWARD:
6985 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6987 case GTK_SCROLL_STEP_FORWARD:
6988 case GTK_SCROLL_PAGE_FORWARD:
6989 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6991 case GTK_SCROLL_JUMP:
6992 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
6998 if (old_focus_row != clist->focus_row &&
6999 !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
7000 GTK_CLIST_ADD_MODE(clist)))
7001 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
7002 clist->focus_row, -1, NULL);
7007 move_focus_row (clist, scroll_type, position);
7009 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
7010 clist->clist_window_height)
7011 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
7012 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
7013 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
7019 move_horizontal (GtkCList *clist,
7024 if (!clist->hadjustment)
7027 value = CLAMP (clist->hadjustment->value + diff, 0.0,
7028 clist->hadjustment->upper - clist->hadjustment->page_size);
7029 gtk_adjustment_set_value (clist->hadjustment, value);
7033 move_vertical (GtkCList *clist,
7039 if (!clist->vadjustment)
7042 value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
7043 align * (clist->clist_window_height - clist->row_height) +
7044 (2 * align - 1) * CELL_SPACING);
7046 if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
7047 value = clist->vadjustment->upper - clist->vadjustment->page_size;
7049 gtk_adjustment_set_value (clist->vadjustment, value);
7053 do_fake_motion (GtkWidget *widget)
7055 GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
7057 event->motion.send_event = TRUE;
7059 gtk_clist_motion (widget, (GdkEventMotion *)event);
7060 gdk_event_free (event);
7064 horizontal_timeout (GtkCList *clist)
7066 GDK_THREADS_ENTER ();
7069 do_fake_motion (GTK_WIDGET (clist));
7071 GDK_THREADS_LEAVE ();
7077 vertical_timeout (GtkCList *clist)
7079 GDK_THREADS_ENTER ();
7082 do_fake_motion (GTK_WIDGET (clist));
7084 GDK_THREADS_LEAVE ();
7090 remove_grab (GtkCList *clist)
7092 GtkWidget *widget = GTK_WIDGET (clist);
7094 if (GTK_WIDGET_HAS_GRAB (clist))
7096 GdkDisplay *display = gtk_widget_get_display (widget);
7098 gtk_grab_remove (widget);
7099 if (gdk_display_pointer_is_grabbed (display))
7100 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
7105 gtk_timeout_remove (clist->htimer);
7111 gtk_timeout_remove (clist->vtimer);
7116 /* PUBLIC SORTING FUNCTIONS
7118 * gtk_clist_set_compare_func
7119 * gtk_clist_set_auto_sort
7120 * gtk_clist_set_sort_type
7121 * gtk_clist_set_sort_column
7124 gtk_clist_sort (GtkCList *clist)
7126 g_return_if_fail (GTK_IS_CLIST (clist));
7128 GTK_CLIST_GET_CLASS (clist)->sort_list (clist);
7132 gtk_clist_set_compare_func (GtkCList *clist,
7133 GtkCListCompareFunc cmp_func)
7135 g_return_if_fail (GTK_IS_CLIST (clist));
7137 clist->compare = (cmp_func) ? cmp_func : default_compare;
7141 gtk_clist_set_auto_sort (GtkCList *clist,
7144 g_return_if_fail (GTK_IS_CLIST (clist));
7146 if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
7147 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
7148 else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
7150 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
7151 gtk_clist_sort (clist);
7156 gtk_clist_set_sort_type (GtkCList *clist,
7157 GtkSortType sort_type)
7159 g_return_if_fail (GTK_IS_CLIST (clist));
7161 clist->sort_type = sort_type;
7165 gtk_clist_set_sort_column (GtkCList *clist,
7168 g_return_if_fail (GTK_IS_CLIST (clist));
7170 if (column < 0 || column >= clist->columns)
7173 clist->sort_column = column;
7176 /* PRIVATE SORTING FUNCTIONS
7180 * gtk_clist_mergesort
7183 default_compare (GtkCList *clist,
7190 GtkCListRow *row1 = (GtkCListRow *) ptr1;
7191 GtkCListRow *row2 = (GtkCListRow *) ptr2;
7193 switch (row1->cell[clist->sort_column].type)
7196 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
7198 case GTK_CELL_PIXTEXT:
7199 text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
7205 switch (row2->cell[clist->sort_column].type)
7208 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
7210 case GTK_CELL_PIXTEXT:
7211 text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
7218 return (text1 != NULL);
7223 return strcmp (text1, text2);
7227 real_sort_list (GtkCList *clist)
7233 g_return_if_fail (GTK_IS_CLIST (clist));
7235 if (clist->rows <= 1)
7238 if (clist_has_grab (clist))
7241 gtk_clist_freeze (clist);
7243 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_MULTIPLE)
7245 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
7246 g_list_free (clist->undo_selection);
7247 g_list_free (clist->undo_unselection);
7248 clist->undo_selection = NULL;
7249 clist->undo_unselection = NULL;
7252 clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
7254 work = clist->selection;
7256 for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
7258 if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
7260 work->data = GINT_TO_POINTER (i);
7264 if (i == clist->rows - 1)
7265 clist->row_list_end = list;
7268 gtk_clist_thaw (clist);
7272 gtk_clist_merge (GtkCList *clist,
7273 GList *a, /* first list to merge */
7274 GList *b) /* second list to merge */
7276 GList z = { 0 }; /* auxiliary node */
7302 cmp = clist->compare (clist, GTK_CLIST_ROW (a), GTK_CLIST_ROW (b));
7303 if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
7304 (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
7322 z.next->prev = NULL;
7327 gtk_clist_mergesort (GtkCList *clist,
7328 GList *list, /* the list to sort */
7329 gint num) /* the list's length */
7340 /* move "half" to the middle */
7342 for (i = 0; i < num / 2; i++)
7345 /* cut the list in two */
7346 half->prev->next = NULL;
7349 /* recursively sort both lists */
7350 return gtk_clist_merge (clist,
7351 gtk_clist_mergesort (clist, list, num / 2),
7352 gtk_clist_mergesort (clist, half, num - num / 2));
7356 /************************/
7359 drag_source_info_destroy (gpointer data)
7361 GtkCListCellInfo *info = data;
7367 drag_dest_info_destroy (gpointer data)
7369 GtkCListDestInfo *info = data;
7375 drag_dest_cell (GtkCList *clist,
7378 GtkCListDestInfo *dest_info)
7382 widget = GTK_WIDGET (clist);
7384 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
7386 y -= (GTK_CONTAINER (clist)->border_width +
7387 widget->style->ythickness +
7388 clist->column_title_area.height);
7390 dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
7391 if (dest_info->cell.row >= clist->rows)
7393 dest_info->cell.row = clist->rows - 1;
7394 y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
7396 if (dest_info->cell.row < -1)
7397 dest_info->cell.row = -1;
7399 x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
7401 dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
7403 if (dest_info->cell.row >= 0)
7408 y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
7410 if (GTK_CLIST_DRAW_DRAG_RECT(clist))
7412 dest_info->insert_pos = GTK_CLIST_DRAG_INTO;
7413 h = clist->row_height / 4;
7415 else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7417 dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
7418 h = clist->row_height / 2;
7421 if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7424 dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
7425 else if (clist->row_height - y_delta < h)
7426 dest_info->insert_pos = GTK_CLIST_DRAG_AFTER;
7432 gtk_clist_drag_begin (GtkWidget *widget,
7433 GdkDragContext *context)
7436 GtkCListCellInfo *info;
7438 g_return_if_fail (GTK_IS_CLIST (widget));
7439 g_return_if_fail (context != NULL);
7441 clist = GTK_CLIST (widget);
7443 clist->drag_button = 0;
7444 remove_grab (clist);
7446 switch (clist->selection_mode)
7448 case GTK_SELECTION_MULTIPLE:
7449 update_extended_selection (clist, clist->focus_row);
7450 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
7452 case GTK_SELECTION_SINGLE:
7454 case GTK_SELECTION_BROWSE:
7457 g_assert_not_reached ();
7460 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7464 info = g_new (GtkCListCellInfo, 1);
7466 if (clist->click_cell.row < 0)
7467 clist->click_cell.row = 0;
7468 else if (clist->click_cell.row >= clist->rows)
7469 clist->click_cell.row = clist->rows - 1;
7470 info->row = clist->click_cell.row;
7471 info->column = clist->click_cell.column;
7473 g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
7474 drag_source_info_destroy);
7477 if (GTK_CLIST_USE_DRAG_ICONS (clist))
7478 gtk_drag_set_icon_default (context);
7482 gtk_clist_drag_end (GtkWidget *widget,
7483 GdkDragContext *context)
7487 g_return_if_fail (GTK_IS_CLIST (widget));
7488 g_return_if_fail (context != NULL);
7490 clist = GTK_CLIST (widget);
7492 clist->click_cell.row = -1;
7493 clist->click_cell.column = -1;
7497 gtk_clist_drag_leave (GtkWidget *widget,
7498 GdkDragContext *context,
7502 GtkCListDestInfo *dest_info;
7504 g_return_if_fail (GTK_IS_CLIST (widget));
7505 g_return_if_fail (context != NULL);
7507 clist = GTK_CLIST (widget);
7509 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7513 if (dest_info->cell.row >= 0 &&
7514 GTK_CLIST_REORDERABLE(clist) &&
7515 gtk_drag_get_source_widget (context) == widget)
7518 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7520 list = context->targets;
7523 if (atom == GDK_POINTER_TO_ATOM (list->data))
7525 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
7527 g_list_nth (clist->row_list, dest_info->cell.row)->data,
7528 dest_info->cell.row, dest_info->insert_pos);
7529 clist->drag_highlight_row = -1;
7535 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7540 gtk_clist_drag_motion (GtkWidget *widget,
7541 GdkDragContext *context,
7547 GtkCListDestInfo new_info;
7548 GtkCListDestInfo *dest_info;
7550 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7552 clist = GTK_CLIST (widget);
7554 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7558 dest_info = g_new (GtkCListDestInfo, 1);
7560 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
7561 dest_info->cell.row = -1;
7562 dest_info->cell.column = -1;
7564 g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
7565 drag_dest_info_destroy);
7568 drag_dest_cell (clist, x, y, &new_info);
7570 if (GTK_CLIST_REORDERABLE (clist))
7573 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7575 list = context->targets;
7578 if (atom == GDK_POINTER_TO_ATOM (list->data))
7585 if (gtk_drag_get_source_widget (context) != widget ||
7586 new_info.insert_pos == GTK_CLIST_DRAG_NONE ||
7587 new_info.cell.row == clist->click_cell.row ||
7588 (new_info.cell.row == clist->click_cell.row - 1 &&
7589 new_info.insert_pos == GTK_CLIST_DRAG_AFTER) ||
7590 (new_info.cell.row == clist->click_cell.row + 1 &&
7591 new_info.insert_pos == GTK_CLIST_DRAG_BEFORE))
7593 if (dest_info->cell.row < 0)
7595 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
7601 if (new_info.cell.row != dest_info->cell.row ||
7602 (new_info.cell.row == dest_info->cell.row &&
7603 dest_info->insert_pos != new_info.insert_pos))
7605 if (dest_info->cell.row >= 0)
7606 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
7607 (clist, g_list_nth (clist->row_list,
7608 dest_info->cell.row)->data,
7609 dest_info->cell.row, dest_info->insert_pos);
7611 dest_info->insert_pos = new_info.insert_pos;
7612 dest_info->cell.row = new_info.cell.row;
7613 dest_info->cell.column = new_info.cell.column;
7615 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
7616 (clist, g_list_nth (clist->row_list,
7617 dest_info->cell.row)->data,
7618 dest_info->cell.row, dest_info->insert_pos);
7620 clist->drag_highlight_row = dest_info->cell.row;
7621 clist->drag_highlight_pos = dest_info->insert_pos;
7623 gdk_drag_status (context, context->suggested_action, time);
7629 dest_info->insert_pos = new_info.insert_pos;
7630 dest_info->cell.row = new_info.cell.row;
7631 dest_info->cell.column = new_info.cell.column;
7636 gtk_clist_drag_drop (GtkWidget *widget,
7637 GdkDragContext *context,
7642 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7643 g_return_val_if_fail (context != NULL, FALSE);
7645 if (GTK_CLIST_REORDERABLE (widget) &&
7646 gtk_drag_get_source_widget (context) == widget)
7649 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7651 list = context->targets;
7654 if (atom == GDK_POINTER_TO_ATOM (list->data))
7663 gtk_clist_drag_data_received (GtkWidget *widget,
7664 GdkDragContext *context,
7667 GtkSelectionData *selection_data,
7673 g_return_if_fail (GTK_IS_CLIST (widget));
7674 g_return_if_fail (context != NULL);
7675 g_return_if_fail (selection_data != NULL);
7677 clist = GTK_CLIST (widget);
7679 if (GTK_CLIST_REORDERABLE (clist) &&
7680 gtk_drag_get_source_widget (context) == widget &&
7681 selection_data->target ==
7682 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
7683 selection_data->format == 8 &&
7684 selection_data->length == sizeof (GtkCListCellInfo))
7686 GtkCListCellInfo *source_info;
7688 source_info = (GtkCListCellInfo *)(selection_data->data);
7691 GtkCListDestInfo dest_info;
7693 drag_dest_cell (clist, x, y, &dest_info);
7695 if (dest_info.insert_pos == GTK_CLIST_DRAG_AFTER)
7696 dest_info.cell.row++;
7697 if (source_info->row < dest_info.cell.row)
7698 dest_info.cell.row--;
7699 if (dest_info.cell.row != source_info->row)
7700 gtk_clist_row_move (clist, source_info->row, dest_info.cell.row);
7702 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7708 gtk_clist_drag_data_get (GtkWidget *widget,
7709 GdkDragContext *context,
7710 GtkSelectionData *selection_data,
7714 g_return_if_fail (GTK_IS_CLIST (widget));
7715 g_return_if_fail (context != NULL);
7716 g_return_if_fail (selection_data != NULL);
7718 if (selection_data->target ==
7719 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
7721 GtkCListCellInfo *info;
7723 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7727 GtkCListCellInfo ret_info;
7729 ret_info.row = info->row;
7730 ret_info.column = info->column;
7732 gtk_selection_data_set (selection_data, selection_data->target,
7733 8, (guchar *) &ret_info,
7734 sizeof (GtkCListCellInfo));
7740 draw_drag_highlight (GtkCList *clist,
7741 GtkCListRow *dest_row,
7742 gint dest_row_number,
7743 GtkCListDragPos drag_pos)
7747 y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
7751 case GTK_CLIST_DRAG_NONE:
7753 case GTK_CLIST_DRAG_AFTER:
7754 y += clist->row_height + 1;
7755 case GTK_CLIST_DRAG_BEFORE:
7756 gdk_draw_line (clist->clist_window, clist->xor_gc,
7757 0, y, clist->clist_window_width, y);
7759 case GTK_CLIST_DRAG_INTO:
7760 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
7761 clist->clist_window_width - 1, clist->row_height);
7767 gtk_clist_set_reorderable (GtkCList *clist,
7768 gboolean reorderable)
7772 g_return_if_fail (GTK_IS_CLIST (clist));
7774 if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
7777 widget = GTK_WIDGET (clist);
7781 GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
7782 gtk_drag_dest_set (widget,
7783 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
7784 &clist_target_table, 1, GDK_ACTION_MOVE);
7788 GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
7789 gtk_drag_dest_unset (GTK_WIDGET (clist));
7794 gtk_clist_set_use_drag_icons (GtkCList *clist,
7797 g_return_if_fail (GTK_IS_CLIST (clist));
7800 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7802 GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7806 gtk_clist_set_button_actions (GtkCList *clist,
7808 guint8 button_actions)
7810 g_return_if_fail (GTK_IS_CLIST (clist));
7812 if (button < MAX_BUTTON)
7814 if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) ||
7815 GTK_WIDGET_HAS_GRAB (clist))
7817 remove_grab (clist);
7818 clist->drag_button = 0;
7821 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
7823 clist->button_actions[button] = button_actions;