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 Library 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 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library 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-1999. 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/.
33 #include "gtkbindings.h"
36 #include <gdk/gdkkeysyms.h>
38 /* length of button_actions array */
41 /* the number rows memchunk expands at a time */
42 #define CLIST_OPTIMUM_SIZE 512
44 /* the width of the column resize windows */
47 /* minimum allowed width of a column */
48 #define COLUMN_MIN_WIDTH 5
50 /* this defigns the base grid spacing */
51 #define CELL_SPACING 1
53 /* added the horizontal space at the beginning and end of a row*/
54 #define COLUMN_INSET 3
56 /* used for auto-scrolling */
57 #define SCROLL_TIME 100
59 /* gives the top pixel of the given row in context of
60 * the clist's voffset */
61 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
62 (((row) + 1) * CELL_SPACING) + \
65 /* returns the row index from a y pixel location in the
66 * context of the clist's voffset */
67 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
68 ((clist)->row_height + CELL_SPACING))
70 /* gives the left pixel of the given column in context of
71 * the clist's hoffset */
72 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
75 /* returns the column index from a x pixel location in the
76 * context of the clist's hoffset */
78 COLUMN_FROM_XPIXEL (GtkCList * clist,
83 for (i = 0; i < clist->columns; i++)
84 if (clist->column[i].visible)
86 cx = clist->column[i].area.x + clist->hoffset;
88 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
89 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
97 /* returns the top pixel of the given row in the context of
99 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
101 /* returns the left pixel of the given column in the context of
103 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
105 /* returns the total height of the list */
106 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
107 (CELL_SPACING * ((clist)->rows + 1)))
110 /* returns the total width of the list */
112 LIST_WIDTH (GtkCList * clist)
116 for (last_column = clist->columns - 1;
117 last_column >= 0 && !clist->column[last_column].visible; last_column--);
119 if (last_column >= 0)
120 return (clist->column[last_column].area.x +
121 clist->column[last_column].area.width +
122 COLUMN_INSET + CELL_SPACING);
126 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
128 /* redraw the list if it's not frozen */
129 #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
130 #define CLIST_REFRESH(clist) G_STMT_START { \
131 if (CLIST_UNFROZEN (clist)) \
132 GTK_CLIST_CLASS_FW (clist)->refresh ((GtkCList*) (clist)); \
175 /* GtkCList Methods */
176 static void gtk_clist_class_init (GtkCListClass *klass);
177 static void gtk_clist_init (GtkCList *clist);
179 /* GtkObject Methods */
180 static void gtk_clist_destroy (GtkObject *object);
181 static void gtk_clist_finalize (GtkObject *object);
182 static void gtk_clist_set_arg (GtkObject *object,
185 static void gtk_clist_get_arg (GtkObject *object,
189 /* GtkWidget Methods */
190 static void gtk_clist_set_scroll_adjustments (GtkCList *clist,
191 GtkAdjustment *hadjustment,
192 GtkAdjustment *vadjustment);
193 static void gtk_clist_realize (GtkWidget *widget);
194 static void gtk_clist_unrealize (GtkWidget *widget);
195 static void gtk_clist_map (GtkWidget *widget);
196 static void gtk_clist_unmap (GtkWidget *widget);
197 static void gtk_clist_draw (GtkWidget *widget,
199 static gint gtk_clist_expose (GtkWidget *widget,
200 GdkEventExpose *event);
201 static gint gtk_clist_key_press (GtkWidget *widget,
203 static gint gtk_clist_button_press (GtkWidget *widget,
204 GdkEventButton *event);
205 static gint gtk_clist_button_release (GtkWidget *widget,
206 GdkEventButton *event);
207 static gint gtk_clist_motion (GtkWidget *widget,
208 GdkEventMotion *event);
209 static void gtk_clist_size_request (GtkWidget *widget,
210 GtkRequisition *requisition);
211 static void gtk_clist_size_allocate (GtkWidget *widget,
212 GtkAllocation *allocation);
213 static void gtk_clist_draw_focus (GtkWidget *widget);
214 static gint gtk_clist_focus_in (GtkWidget *widget,
215 GdkEventFocus *event);
216 static gint gtk_clist_focus_out (GtkWidget *widget,
217 GdkEventFocus *event);
218 static gint gtk_clist_focus (GtkContainer *container,
219 GtkDirectionType direction);
220 static void gtk_clist_style_set (GtkWidget *widget,
221 GtkStyle *previous_style);
222 static void gtk_clist_drag_begin (GtkWidget *widget,
223 GdkDragContext *context);
224 static gint gtk_clist_drag_motion (GtkWidget *widget,
225 GdkDragContext *context,
229 static void gtk_clist_drag_leave (GtkWidget *widget,
230 GdkDragContext *context,
232 static void gtk_clist_drag_end (GtkWidget *widget,
233 GdkDragContext *context);
234 static gboolean gtk_clist_drag_drop (GtkWidget *widget,
235 GdkDragContext *context,
239 static void gtk_clist_drag_data_get (GtkWidget *widget,
240 GdkDragContext *context,
241 GtkSelectionData *selection_data,
244 static void gtk_clist_drag_data_received (GtkWidget *widget,
245 GdkDragContext *context,
248 GtkSelectionData *selection_data,
252 /* GtkContainer Methods */
253 static void gtk_clist_set_focus_child (GtkContainer *container,
255 static void gtk_clist_forall (GtkContainer *container,
256 gboolean include_internals,
257 GtkCallback callback,
258 gpointer callback_data);
261 static void toggle_row (GtkCList *clist,
265 static void real_select_row (GtkCList *clist,
269 static void real_unselect_row (GtkCList *clist,
273 static void update_extended_selection (GtkCList *clist,
275 static GList *selection_find (GtkCList *clist,
277 GList *row_list_element);
278 static void real_select_all (GtkCList *clist);
279 static void real_unselect_all (GtkCList *clist);
280 static void move_vertical (GtkCList *clist,
283 static void move_horizontal (GtkCList *clist,
285 static void real_undo_selection (GtkCList *clist);
286 static void fake_unselect_all (GtkCList *clist,
288 static void fake_toggle_row (GtkCList *clist,
290 static void resync_selection (GtkCList *clist,
292 static void sync_selection (GtkCList *clist,
295 static void set_anchor (GtkCList *clist,
299 static void start_selection (GtkCList *clist);
300 static void end_selection (GtkCList *clist);
301 static void toggle_add_mode (GtkCList *clist);
302 static void toggle_focus_row (GtkCList *clist);
303 static void extend_selection (GtkCList *clist,
304 GtkScrollType scroll_type,
306 gboolean auto_start_selection);
307 static gint get_selection_info (GtkCList *clist,
314 static void move_focus_row (GtkCList *clist,
315 GtkScrollType scroll_type,
317 static void scroll_horizontal (GtkCList *clist,
318 GtkScrollType scroll_type,
320 static void scroll_vertical (GtkCList *clist,
321 GtkScrollType scroll_type,
323 static void move_horizontal (GtkCList *clist,
325 static void move_vertical (GtkCList *clist,
328 static gint horizontal_timeout (GtkCList *clist);
329 static gint vertical_timeout (GtkCList *clist);
330 static void remove_grab (GtkCList *clist);
334 static void draw_xor_line (GtkCList *clist);
335 static gint new_column_width (GtkCList *clist,
338 static void column_auto_resize (GtkCList *clist,
339 GtkCListRow *clist_row,
342 static void real_resize_column (GtkCList *clist,
345 static void abort_column_resize (GtkCList *clist);
346 static void cell_size_request (GtkCList *clist,
347 GtkCListRow *clist_row,
349 GtkRequisition *requisition);
352 static void column_button_create (GtkCList *clist,
354 static void column_button_clicked (GtkWidget *widget,
358 static void adjust_adjustments (GtkCList *clist,
359 gboolean block_resize);
360 static void check_exposures (GtkCList *clist);
361 static void vadjustment_changed (GtkAdjustment *adjustment,
363 static void vadjustment_value_changed (GtkAdjustment *adjustment,
365 static void hadjustment_changed (GtkAdjustment *adjustment,
367 static void hadjustment_value_changed (GtkAdjustment *adjustment,
371 static void get_cell_style (GtkCList *clist,
372 GtkCListRow *clist_row,
378 static gint draw_cell_pixmap (GdkWindow *window,
379 GdkRectangle *clip_rectangle,
387 static void draw_row (GtkCList *clist,
390 GtkCListRow *clist_row);
391 static void draw_rows (GtkCList *clist,
393 static void clist_refresh (GtkCList *clist);
394 static void draw_drag_highlight (GtkCList *clist,
395 GtkCListRow *dest_row,
396 gint dest_row_number,
397 GtkCListDragPos drag_pos);
399 /* Size Allocation / Requisition */
400 static void size_allocate_title_buttons (GtkCList *clist);
401 static void size_allocate_columns (GtkCList *clist,
402 gboolean block_resize);
403 static gint list_requisition_width (GtkCList *clist);
405 /* Memory Allocation/Distruction Routines */
406 static GtkCListColumn *columns_new (GtkCList *clist);
407 static void column_title_new (GtkCList *clist,
410 static void columns_delete (GtkCList *clist);
411 static GtkCListRow *row_new (GtkCList *clist);
412 static void row_delete (GtkCList *clist,
413 GtkCListRow *clist_row);
414 static void set_cell_contents (GtkCList *clist,
415 GtkCListRow *clist_row,
422 static gint real_insert_row (GtkCList *clist,
425 static void real_remove_row (GtkCList *clist,
427 static void real_clear (GtkCList *clist);
430 static gint default_compare (GtkCList *clist,
433 static void real_sort_list (GtkCList *clist);
434 static GList *gtk_clist_merge (GtkCList *clist,
437 static GList *gtk_clist_mergesort (GtkCList *clist,
441 static gboolean title_focus (GtkCList *clist,
443 static void real_row_move (GtkCList *clist,
449 static GtkContainerClass *parent_class = NULL;
450 static guint clist_signals[LAST_SIGNAL] = {0};
452 static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
455 gtk_clist_get_type (void)
457 static GtkType clist_type = 0;
461 static const GtkTypeInfo clist_info =
465 sizeof (GtkCListClass),
466 (GtkClassInitFunc) gtk_clist_class_init,
467 (GtkObjectInitFunc) gtk_clist_init,
468 /* reserved_1 */ NULL,
469 /* reserved_2 */ NULL,
470 (GtkClassInitFunc) NULL,
473 clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
480 gtk_clist_class_init (GtkCListClass *klass)
482 GtkObjectClass *object_class;
483 GtkWidgetClass *widget_class;
484 GtkContainerClass *container_class;
485 GtkBindingSet *binding_set;
487 object_class = (GtkObjectClass *) klass;
488 widget_class = (GtkWidgetClass *) klass;
489 container_class = (GtkContainerClass *) klass;
491 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
493 gtk_object_add_arg_type ("GtkCList::n_columns",
495 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
497 gtk_object_add_arg_type ("GtkCList::shadow_type",
498 GTK_TYPE_SHADOW_TYPE,
501 gtk_object_add_arg_type ("GtkCList::selection_mode",
502 GTK_TYPE_SELECTION_MODE,
505 gtk_object_add_arg_type ("GtkCList::row_height",
509 gtk_object_add_arg_type ("GtkCList::reorderable",
513 gtk_object_add_arg_type ("GtkCList::titles_active",
517 gtk_object_add_arg_type ("GtkCList::use_drag_icons",
522 object_class->set_arg = gtk_clist_set_arg;
523 object_class->get_arg = gtk_clist_get_arg;
524 object_class->destroy = gtk_clist_destroy;
525 object_class->finalize = gtk_clist_finalize;
528 widget_class->set_scroll_adjustments_signal =
529 gtk_signal_new ("set_scroll_adjustments",
532 GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
533 gtk_marshal_NONE__POINTER_POINTER,
534 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
536 clist_signals[SELECT_ROW] =
537 gtk_signal_new ("select_row",
540 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
541 gtk_marshal_NONE__INT_INT_POINTER,
546 clist_signals[UNSELECT_ROW] =
547 gtk_signal_new ("unselect_row",
550 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
551 gtk_marshal_NONE__INT_INT_POINTER,
552 GTK_TYPE_NONE, 3, GTK_TYPE_INT,
553 GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
554 clist_signals[ROW_MOVE] =
555 gtk_signal_new ("row_move",
558 GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
559 gtk_marshal_NONE__INT_INT,
560 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
561 clist_signals[CLICK_COLUMN] =
562 gtk_signal_new ("click_column",
565 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
566 gtk_marshal_NONE__INT,
567 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
568 clist_signals[RESIZE_COLUMN] =
569 gtk_signal_new ("resize_column",
572 GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
573 gtk_marshal_NONE__INT_INT,
574 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
576 clist_signals[TOGGLE_FOCUS_ROW] =
577 gtk_signal_new ("toggle_focus_row",
578 GTK_RUN_LAST | GTK_RUN_ACTION,
580 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
581 gtk_marshal_NONE__NONE,
583 clist_signals[SELECT_ALL] =
584 gtk_signal_new ("select_all",
585 GTK_RUN_LAST | GTK_RUN_ACTION,
587 GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
588 gtk_marshal_NONE__NONE,
590 clist_signals[UNSELECT_ALL] =
591 gtk_signal_new ("unselect_all",
592 GTK_RUN_LAST | GTK_RUN_ACTION,
594 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
595 gtk_marshal_NONE__NONE,
597 clist_signals[UNDO_SELECTION] =
598 gtk_signal_new ("undo_selection",
599 GTK_RUN_LAST | GTK_RUN_ACTION,
601 GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
602 gtk_marshal_NONE__NONE,
604 clist_signals[START_SELECTION] =
605 gtk_signal_new ("start_selection",
606 GTK_RUN_LAST | GTK_RUN_ACTION,
608 GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
609 gtk_marshal_NONE__NONE,
611 clist_signals[END_SELECTION] =
612 gtk_signal_new ("end_selection",
613 GTK_RUN_LAST | GTK_RUN_ACTION,
615 GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
616 gtk_marshal_NONE__NONE,
618 clist_signals[TOGGLE_ADD_MODE] =
619 gtk_signal_new ("toggle_add_mode",
620 GTK_RUN_LAST | GTK_RUN_ACTION,
622 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
623 gtk_marshal_NONE__NONE,
625 clist_signals[EXTEND_SELECTION] =
626 gtk_signal_new ("extend_selection",
627 GTK_RUN_LAST | GTK_RUN_ACTION,
629 GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
630 gtk_marshal_NONE__ENUM_FLOAT_BOOL,
632 GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
633 clist_signals[SCROLL_VERTICAL] =
634 gtk_signal_new ("scroll_vertical",
635 GTK_RUN_LAST | GTK_RUN_ACTION,
637 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
638 gtk_marshal_NONE__ENUM_FLOAT,
639 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
640 clist_signals[SCROLL_HORIZONTAL] =
641 gtk_signal_new ("scroll_horizontal",
642 GTK_RUN_LAST | GTK_RUN_ACTION,
644 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
645 gtk_marshal_NONE__ENUM_FLOAT,
646 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
647 clist_signals[ABORT_COLUMN_RESIZE] =
648 gtk_signal_new ("abort_column_resize",
649 GTK_RUN_LAST | GTK_RUN_ACTION,
651 GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
652 gtk_marshal_NONE__NONE,
654 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
656 widget_class->realize = gtk_clist_realize;
657 widget_class->unrealize = gtk_clist_unrealize;
658 widget_class->map = gtk_clist_map;
659 widget_class->unmap = gtk_clist_unmap;
660 widget_class->draw = gtk_clist_draw;
661 widget_class->button_press_event = gtk_clist_button_press;
662 widget_class->button_release_event = gtk_clist_button_release;
663 widget_class->motion_notify_event = gtk_clist_motion;
664 widget_class->expose_event = gtk_clist_expose;
665 widget_class->size_request = gtk_clist_size_request;
666 widget_class->size_allocate = gtk_clist_size_allocate;
667 widget_class->key_press_event = gtk_clist_key_press;
668 widget_class->focus_in_event = gtk_clist_focus_in;
669 widget_class->focus_out_event = gtk_clist_focus_out;
670 widget_class->draw_focus = gtk_clist_draw_focus;
671 widget_class->style_set = gtk_clist_style_set;
672 widget_class->drag_begin = gtk_clist_drag_begin;
673 widget_class->drag_end = gtk_clist_drag_end;
674 widget_class->drag_motion = gtk_clist_drag_motion;
675 widget_class->drag_leave = gtk_clist_drag_leave;
676 widget_class->drag_drop = gtk_clist_drag_drop;
677 widget_class->drag_data_get = gtk_clist_drag_data_get;
678 widget_class->drag_data_received = gtk_clist_drag_data_received;
680 /* container_class->add = NULL; use the default GtkContainerClass warning */
681 /* container_class->remove=NULL; use the default GtkContainerClass warning */
683 container_class->forall = gtk_clist_forall;
684 container_class->focus = gtk_clist_focus;
685 container_class->set_focus_child = gtk_clist_set_focus_child;
687 klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
688 klass->refresh = clist_refresh;
689 klass->select_row = real_select_row;
690 klass->unselect_row = real_unselect_row;
691 klass->row_move = real_row_move;
692 klass->undo_selection = real_undo_selection;
693 klass->resync_selection = resync_selection;
694 klass->selection_find = selection_find;
695 klass->click_column = NULL;
696 klass->resize_column = real_resize_column;
697 klass->draw_row = draw_row;
698 klass->draw_drag_highlight = draw_drag_highlight;
699 klass->insert_row = real_insert_row;
700 klass->remove_row = real_remove_row;
701 klass->clear = real_clear;
702 klass->sort_list = real_sort_list;
703 klass->select_all = real_select_all;
704 klass->unselect_all = real_unselect_all;
705 klass->fake_unselect_all = fake_unselect_all;
706 klass->scroll_horizontal = scroll_horizontal;
707 klass->scroll_vertical = scroll_vertical;
708 klass->extend_selection = extend_selection;
709 klass->toggle_focus_row = toggle_focus_row;
710 klass->toggle_add_mode = toggle_add_mode;
711 klass->start_selection = start_selection;
712 klass->end_selection = end_selection;
713 klass->abort_column_resize = abort_column_resize;
714 klass->set_cell_contents = set_cell_contents;
715 klass->cell_size_request = cell_size_request;
717 binding_set = gtk_binding_set_by_class (klass);
718 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
719 "scroll_vertical", 2,
720 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
721 GTK_TYPE_FLOAT, 0.0);
722 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
723 "scroll_vertical", 2,
724 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
725 GTK_TYPE_FLOAT, 0.0);
726 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
727 "scroll_vertical", 2,
728 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
729 GTK_TYPE_FLOAT, 0.0);
730 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
731 "scroll_vertical", 2,
732 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
733 GTK_TYPE_FLOAT, 0.0);
734 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
735 "scroll_vertical", 2,
736 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
737 GTK_TYPE_FLOAT, 0.0);
738 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
739 "scroll_vertical", 2,
740 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
741 GTK_TYPE_FLOAT, 1.0);
743 gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
744 "extend_selection", 3,
745 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
746 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
747 gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
748 "extend_selection", 3,
749 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
750 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
751 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
752 "extend_selection", 3,
753 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
754 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
755 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
756 "extend_selection", 3,
757 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
758 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
759 gtk_binding_entry_add_signal (binding_set, GDK_Home,
760 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
761 "extend_selection", 3,
762 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
763 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
764 gtk_binding_entry_add_signal (binding_set, GDK_End,
765 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
766 "extend_selection", 3,
767 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
768 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
770 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
771 "scroll_horizontal", 2,
772 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
773 GTK_TYPE_FLOAT, 0.0);
774 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
775 "scroll_horizontal", 2,
776 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
777 GTK_TYPE_FLOAT, 0.0);
778 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
779 "scroll_horizontal", 2,
780 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
781 GTK_TYPE_FLOAT, 0.0);
782 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
783 "scroll_horizontal", 2,
784 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
785 GTK_TYPE_FLOAT, 1.0);
787 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
788 "undo_selection", 0);
789 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
790 "abort_column_resize", 0);
791 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
792 "toggle_focus_row", 0);
793 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
794 "toggle_add_mode", 0);
795 gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
797 gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
799 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
800 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
802 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
803 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
805 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
806 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
809 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
810 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
816 gtk_clist_set_arg (GtkObject *object,
822 clist = GTK_CLIST (object);
826 case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
827 gtk_clist_construct (clist, MAX (1, GTK_VALUE_UINT (*arg)), NULL);
829 case ARG_SHADOW_TYPE:
830 gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
832 case ARG_SELECTION_MODE:
833 gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
836 gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
838 case ARG_REORDERABLE:
839 gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
841 case ARG_TITLES_ACTIVE:
842 if (GTK_VALUE_BOOL (*arg))
843 gtk_clist_column_titles_active (clist);
845 gtk_clist_column_titles_passive (clist);
847 case ARG_USE_DRAG_ICONS:
848 gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
856 gtk_clist_get_arg (GtkObject *object,
862 clist = GTK_CLIST (object);
869 GTK_VALUE_UINT (*arg) = clist->columns;
871 case ARG_SHADOW_TYPE:
872 GTK_VALUE_ENUM (*arg) = clist->shadow_type;
874 case ARG_SELECTION_MODE:
875 GTK_VALUE_ENUM (*arg) = clist->selection_mode;
878 GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
880 case ARG_REORDERABLE:
881 GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
883 case ARG_TITLES_ACTIVE:
884 GTK_VALUE_BOOL (*arg) = TRUE;
885 for (i = 0; i < clist->columns; i++)
886 if (clist->column[i].button &&
887 !GTK_WIDGET_SENSITIVE (clist->column[i].button))
889 GTK_VALUE_BOOL (*arg) = FALSE;
893 case ARG_USE_DRAG_ICONS:
894 GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
897 arg->type = GTK_TYPE_INVALID;
903 gtk_clist_init (GtkCList *clist)
907 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
908 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
909 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
910 GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
911 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
913 clist->row_mem_chunk = NULL;
914 clist->cell_mem_chunk = NULL;
916 clist->freeze_count = 0;
919 clist->row_center_offset = 0;
920 clist->row_height = 0;
921 clist->row_list = NULL;
922 clist->row_list_end = NULL;
926 clist->title_window = NULL;
927 clist->column_title_area.x = 0;
928 clist->column_title_area.y = 0;
929 clist->column_title_area.width = 1;
930 clist->column_title_area.height = 1;
932 clist->clist_window = NULL;
933 clist->clist_window_width = 1;
934 clist->clist_window_height = 1;
939 clist->shadow_type = GTK_SHADOW_IN;
940 clist->vadjustment = NULL;
941 clist->hadjustment = NULL;
943 clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
944 clist->button_actions[1] = GTK_BUTTON_IGNORED;
945 clist->button_actions[2] = GTK_BUTTON_IGNORED;
946 clist->button_actions[3] = GTK_BUTTON_IGNORED;
947 clist->button_actions[4] = GTK_BUTTON_IGNORED;
949 clist->cursor_drag = NULL;
950 clist->xor_gc = NULL;
955 clist->selection_mode = GTK_SELECTION_SINGLE;
956 clist->selection = NULL;
957 clist->selection_end = NULL;
958 clist->undo_selection = NULL;
959 clist->undo_unselection = NULL;
961 clist->focus_row = -1;
962 clist->undo_anchor = -1;
965 clist->anchor_state = GTK_STATE_SELECTED;
966 clist->drag_pos = -1;
970 clist->click_cell.row = -1;
971 clist->click_cell.column = -1;
973 clist->compare = default_compare;
974 clist->sort_type = GTK_SORT_ASCENDING;
975 clist->sort_column = 0;
980 gtk_clist_construct (GtkCList *clist,
984 g_return_if_fail (clist != NULL);
985 g_return_if_fail (GTK_IS_CLIST (clist));
986 g_return_if_fail (columns > 0);
987 g_return_if_fail (GTK_OBJECT_CONSTRUCTED (clist) == FALSE);
989 /* mark the object as constructed */
990 gtk_object_constructed (GTK_OBJECT (clist));
992 /* initalize memory chunks, if this has not been done by any
993 * possibly derived widget
995 if (!clist->row_mem_chunk)
996 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
997 sizeof (GtkCListRow),
998 sizeof (GtkCListRow) *
1002 if (!clist->cell_mem_chunk)
1003 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
1004 sizeof (GtkCell) * columns,
1005 sizeof (GtkCell) * columns *
1009 /* set number of columns, allocate memory */
1010 clist->columns = columns;
1011 clist->column = columns_new (clist);
1013 /* there needs to be at least one column button
1014 * because there is alot of code that will break if it
1016 column_button_create (clist, 0);
1022 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1023 for (i = 0; i < columns; i++)
1024 gtk_clist_set_column_title (clist, i, titles[i]);
1028 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1032 /* GTKCLIST PUBLIC INTERFACE
1034 * gtk_clist_new_with_titles
1035 * gtk_clist_set_hadjustment
1036 * gtk_clist_set_vadjustment
1037 * gtk_clist_get_hadjustment
1038 * gtk_clist_get_vadjustment
1039 * gtk_clist_set_shadow_type
1040 * gtk_clist_set_selection_mode
1045 gtk_clist_new (gint columns)
1047 return gtk_clist_new_with_titles (columns, NULL);
1051 gtk_clist_new_with_titles (gint columns,
1056 widget = gtk_type_new (GTK_TYPE_CLIST);
1057 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
1063 gtk_clist_set_hadjustment (GtkCList *clist,
1064 GtkAdjustment *adjustment)
1066 GtkAdjustment *old_adjustment;
1068 g_return_if_fail (clist != NULL);
1069 g_return_if_fail (GTK_IS_CLIST (clist));
1071 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1073 if (clist->hadjustment == adjustment)
1076 old_adjustment = clist->hadjustment;
1078 if (clist->hadjustment)
1080 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
1081 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
1084 clist->hadjustment = adjustment;
1086 if (clist->hadjustment)
1088 gtk_object_ref (GTK_OBJECT (clist->hadjustment));
1089 gtk_object_sink (GTK_OBJECT (clist->hadjustment));
1091 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
1092 (GtkSignalFunc) hadjustment_changed,
1094 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
1095 (GtkSignalFunc) hadjustment_value_changed,
1099 if (!clist->hadjustment || !old_adjustment)
1100 gtk_widget_queue_resize (GTK_WIDGET (clist));
1104 gtk_clist_get_hadjustment (GtkCList *clist)
1106 g_return_val_if_fail (clist != NULL, NULL);
1107 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1109 return clist->hadjustment;
1113 gtk_clist_set_vadjustment (GtkCList *clist,
1114 GtkAdjustment *adjustment)
1116 GtkAdjustment *old_adjustment;
1118 g_return_if_fail (clist != NULL);
1119 g_return_if_fail (GTK_IS_CLIST (clist));
1121 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1123 if (clist->vadjustment == adjustment)
1126 old_adjustment = clist->vadjustment;
1128 if (clist->vadjustment)
1130 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
1131 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
1134 clist->vadjustment = adjustment;
1136 if (clist->vadjustment)
1138 gtk_object_ref (GTK_OBJECT (clist->vadjustment));
1139 gtk_object_sink (GTK_OBJECT (clist->vadjustment));
1141 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
1142 (GtkSignalFunc) vadjustment_changed,
1144 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
1145 (GtkSignalFunc) vadjustment_value_changed,
1149 if (!clist->vadjustment || !old_adjustment)
1150 gtk_widget_queue_resize (GTK_WIDGET (clist));
1154 gtk_clist_get_vadjustment (GtkCList *clist)
1156 g_return_val_if_fail (clist != NULL, NULL);
1157 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1159 return clist->vadjustment;
1163 gtk_clist_set_scroll_adjustments (GtkCList *clist,
1164 GtkAdjustment *hadjustment,
1165 GtkAdjustment *vadjustment)
1167 if (clist->hadjustment != hadjustment)
1168 gtk_clist_set_hadjustment (clist, hadjustment);
1169 if (clist->vadjustment != vadjustment)
1170 gtk_clist_set_vadjustment (clist, vadjustment);
1174 gtk_clist_set_shadow_type (GtkCList *clist,
1177 g_return_if_fail (clist != NULL);
1178 g_return_if_fail (GTK_IS_CLIST (clist));
1180 clist->shadow_type = type;
1182 if (GTK_WIDGET_VISIBLE (clist))
1183 gtk_widget_queue_resize (GTK_WIDGET (clist));
1187 gtk_clist_set_selection_mode (GtkCList *clist,
1188 GtkSelectionMode mode)
1190 g_return_if_fail (clist != NULL);
1191 g_return_if_fail (GTK_IS_CLIST (clist));
1193 if (mode == clist->selection_mode)
1196 clist->selection_mode = mode;
1198 clist->anchor_state = GTK_STATE_SELECTED;
1199 clist->drag_pos = -1;
1200 clist->undo_anchor = clist->focus_row;
1202 g_list_free (clist->undo_selection);
1203 g_list_free (clist->undo_unselection);
1204 clist->undo_selection = NULL;
1205 clist->undo_unselection = NULL;
1209 case GTK_SELECTION_MULTIPLE:
1210 case GTK_SELECTION_EXTENDED:
1212 case GTK_SELECTION_BROWSE:
1213 case GTK_SELECTION_SINGLE:
1214 gtk_clist_unselect_all (clist);
1220 gtk_clist_freeze (GtkCList *clist)
1222 g_return_if_fail (clist != NULL);
1223 g_return_if_fail (GTK_IS_CLIST (clist));
1225 clist->freeze_count++;
1229 gtk_clist_thaw (GtkCList *clist)
1231 g_return_if_fail (clist != NULL);
1232 g_return_if_fail (GTK_IS_CLIST (clist));
1234 if (clist->freeze_count)
1236 clist->freeze_count--;
1237 CLIST_REFRESH (clist);
1241 /* PUBLIC COLUMN FUNCTIONS
1242 * gtk_clist_column_titles_show
1243 * gtk_clist_column_titles_hide
1244 * gtk_clist_column_title_active
1245 * gtk_clist_column_title_passive
1246 * gtk_clist_column_titles_active
1247 * gtk_clist_column_titles_passive
1248 * gtk_clist_set_column_title
1249 * gtk_clist_get_column_title
1250 * gtk_clist_set_column_widget
1251 * gtk_clist_set_column_justification
1252 * gtk_clist_set_column_visibility
1253 * gtk_clist_set_column_resizeable
1254 * gtk_clist_set_column_auto_resize
1255 * gtk_clist_optimal_column_width
1256 * gtk_clist_set_column_width
1257 * gtk_clist_set_column_min_width
1258 * gtk_clist_set_column_max_width
1261 gtk_clist_column_titles_show (GtkCList *clist)
1263 g_return_if_fail (clist != NULL);
1264 g_return_if_fail (GTK_IS_CLIST (clist));
1266 if (!GTK_CLIST_SHOW_TITLES(clist))
1268 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1269 if (clist->title_window)
1270 gdk_window_show (clist->title_window);
1271 gtk_widget_queue_resize (GTK_WIDGET (clist));
1276 gtk_clist_column_titles_hide (GtkCList *clist)
1278 g_return_if_fail (clist != NULL);
1279 g_return_if_fail (GTK_IS_CLIST (clist));
1281 if (GTK_CLIST_SHOW_TITLES(clist))
1283 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1284 if (clist->title_window)
1285 gdk_window_hide (clist->title_window);
1286 gtk_widget_queue_resize (GTK_WIDGET (clist));
1291 gtk_clist_column_title_active (GtkCList *clist,
1294 g_return_if_fail (clist != NULL);
1295 g_return_if_fail (GTK_IS_CLIST (clist));
1297 if (column < 0 || column >= clist->columns)
1299 if (!clist->column[column].button)
1302 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1303 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1305 GTK_WIDGET_SET_FLAGS (clist->column[column].button,
1306 GTK_SENSITIVE | GTK_CAN_FOCUS);
1307 if (GTK_WIDGET_VISIBLE (clist))
1308 gtk_widget_queue_draw (clist->column[column].button);
1313 gtk_clist_column_title_passive (GtkCList *clist,
1316 g_return_if_fail (clist != NULL);
1317 g_return_if_fail (GTK_IS_CLIST (clist));
1319 if (column < 0 || column >= clist->columns)
1321 if (!clist->column[column].button)
1324 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
1325 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
1327 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button,
1328 GTK_SENSITIVE | GTK_CAN_FOCUS);
1329 if (GTK_WIDGET_VISIBLE (clist))
1330 gtk_widget_queue_draw (clist->column[column].button);
1335 gtk_clist_column_titles_active (GtkCList *clist)
1339 g_return_if_fail (clist != NULL);
1340 g_return_if_fail (GTK_IS_CLIST (clist));
1342 if (!GTK_CLIST_SHOW_TITLES(clist))
1345 for (i = 0; i < clist->columns; i++)
1346 gtk_clist_column_title_active (clist, i);
1350 gtk_clist_column_titles_passive (GtkCList *clist)
1354 g_return_if_fail (clist != NULL);
1355 g_return_if_fail (GTK_IS_CLIST (clist));
1357 if (!GTK_CLIST_SHOW_TITLES(clist))
1360 for (i = 0; i < clist->columns; i++)
1361 gtk_clist_column_title_passive (clist, i);
1365 gtk_clist_set_column_title (GtkCList *clist,
1369 gint new_button = 0;
1370 GtkWidget *old_widget;
1371 GtkWidget *alignment = NULL;
1374 g_return_if_fail (clist != NULL);
1375 g_return_if_fail (GTK_IS_CLIST (clist));
1377 if (column < 0 || column >= clist->columns)
1380 /* if the column button doesn't currently exist,
1381 * it has to be created first */
1382 if (!clist->column[column].button)
1384 column_button_create (clist, column);
1388 column_title_new (clist, column, title);
1390 /* remove and destroy the old widget */
1391 old_widget = GTK_BIN (clist->column[column].button)->child;
1393 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1395 /* create new alignment based no column justification */
1396 switch (clist->column[column].justification)
1398 case GTK_JUSTIFY_LEFT:
1399 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1402 case GTK_JUSTIFY_RIGHT:
1403 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1406 case GTK_JUSTIFY_CENTER:
1407 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1410 case GTK_JUSTIFY_FILL:
1411 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1415 gtk_widget_push_composite_child ();
1416 label = gtk_label_new (clist->column[column].title);
1417 gtk_widget_pop_composite_child ();
1418 gtk_container_add (GTK_CONTAINER (alignment), label);
1419 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1420 gtk_widget_show (label);
1421 gtk_widget_show (alignment);
1423 /* if this button didn't previously exist, then the
1424 * column button positions have to be re-computed */
1425 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1426 size_allocate_title_buttons (clist);
1430 gtk_clist_get_column_title (GtkCList *clist,
1433 g_return_val_if_fail (clist != NULL, NULL);
1434 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1436 if (column < 0 || column >= clist->columns)
1439 return clist->column[column].title;
1443 gtk_clist_set_column_widget (GtkCList *clist,
1447 gint new_button = 0;
1448 GtkWidget *old_widget;
1450 g_return_if_fail (clist != NULL);
1451 g_return_if_fail (GTK_IS_CLIST (clist));
1453 if (column < 0 || column >= clist->columns)
1456 /* if the column button doesn't currently exist,
1457 * it has to be created first */
1458 if (!clist->column[column].button)
1460 column_button_create (clist, column);
1464 column_title_new (clist, column, NULL);
1466 /* remove and destroy the old widget */
1467 old_widget = GTK_BIN (clist->column[column].button)->child;
1469 gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
1472 /* add and show the widget */
1475 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1476 gtk_widget_show (widget);
1479 /* if this button didn't previously exist, then the
1480 * column button positions have to be re-computed */
1481 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1482 size_allocate_title_buttons (clist);
1486 gtk_clist_get_column_widget (GtkCList *clist,
1489 g_return_val_if_fail (clist != NULL, NULL);
1490 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1492 if (column < 0 || column >= clist->columns)
1495 if (clist->column[column].button)
1496 return GTK_BUTTON (clist->column[column].button)->child;
1502 gtk_clist_set_column_justification (GtkCList *clist,
1504 GtkJustification justification)
1506 GtkWidget *alignment;
1508 g_return_if_fail (clist != NULL);
1509 g_return_if_fail (GTK_IS_CLIST (clist));
1511 if (column < 0 || column >= clist->columns)
1514 clist->column[column].justification = justification;
1516 /* change the alinment of the button title if it's not a
1518 if (clist->column[column].title)
1520 alignment = GTK_BIN (clist->column[column].button)->child;
1522 switch (clist->column[column].justification)
1524 case GTK_JUSTIFY_LEFT:
1525 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1528 case GTK_JUSTIFY_RIGHT:
1529 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1532 case GTK_JUSTIFY_CENTER:
1533 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1536 case GTK_JUSTIFY_FILL:
1537 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1545 if (CLIST_UNFROZEN (clist))
1546 draw_rows (clist, NULL);
1550 gtk_clist_set_column_visibility (GtkCList *clist,
1554 g_return_if_fail (clist != NULL);
1555 g_return_if_fail (GTK_IS_CLIST (clist));
1557 if (column < 0 || column >= clist->columns)
1559 if (clist->column[column].visible == visible)
1562 /* don't hide last visible column */
1566 gint vis_columns = 0;
1568 for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
1569 if (clist->column[i].visible)
1572 if (vis_columns < 2)
1576 clist->column[column].visible = visible;
1578 if (clist->column[column].button)
1581 gtk_widget_show (clist->column[column].button);
1583 gtk_widget_hide (clist->column[column].button);
1586 gtk_widget_queue_resize (GTK_WIDGET(clist));
1590 gtk_clist_set_column_resizeable (GtkCList *clist,
1594 g_return_if_fail (clist != NULL);
1595 g_return_if_fail (GTK_IS_CLIST (clist));
1597 if (column < 0 || column >= clist->columns)
1599 if (clist->column[column].resizeable == resizeable)
1602 clist->column[column].resizeable = resizeable;
1604 clist->column[column].auto_resize = FALSE;
1606 if (GTK_WIDGET_VISIBLE (clist))
1607 size_allocate_title_buttons (clist);
1611 gtk_clist_set_column_auto_resize (GtkCList *clist,
1613 gboolean auto_resize)
1615 g_return_if_fail (clist != NULL);
1616 g_return_if_fail (GTK_IS_CLIST (clist));
1618 if (column < 0 || column >= clist->columns)
1620 if (clist->column[column].auto_resize == auto_resize)
1623 clist->column[column].auto_resize = auto_resize;
1626 clist->column[column].resizeable = FALSE;
1627 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
1631 width = gtk_clist_optimal_column_width (clist, column);
1632 gtk_clist_set_column_width (clist, column, width);
1636 if (GTK_WIDGET_VISIBLE (clist))
1637 size_allocate_title_buttons (clist);
1641 gtk_clist_columns_autosize (GtkCList *clist)
1646 g_return_val_if_fail (clist != NULL, 0);
1647 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1649 gtk_clist_freeze (clist);
1651 for (i = 0; i < clist->columns; i++)
1653 gtk_clist_set_column_width (clist, i,
1654 gtk_clist_optimal_column_width (clist, i));
1656 width += clist->column[i].width;
1659 gtk_clist_thaw (clist);
1664 gtk_clist_optimal_column_width (GtkCList *clist,
1667 GtkRequisition requisition;
1671 g_return_val_if_fail (clist != NULL, 0);
1672 g_return_val_if_fail (GTK_CLIST (clist), 0);
1674 if (column < 0 || column > clist->columns)
1677 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1678 width = (clist->column[column].button->requisition.width)
1680 (CELL_SPACING + (2 * COLUMN_INSET)))
1686 for (list = clist->row_list; list; list = list->next)
1688 GTK_CLIST_CLASS_FW (clist)->cell_size_request
1689 (clist, GTK_CLIST_ROW (list), column, &requisition);
1690 width = MAX (width, requisition.width);
1697 gtk_clist_set_column_width (GtkCList *clist,
1701 g_return_if_fail (clist != NULL);
1702 g_return_if_fail (GTK_IS_CLIST (clist));
1704 if (column < 0 || column >= clist->columns)
1707 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
1712 gtk_clist_set_column_min_width (GtkCList *clist,
1716 g_return_if_fail (clist != NULL);
1717 g_return_if_fail (GTK_IS_CLIST (clist));
1719 if (column < 0 || column >= clist->columns)
1721 if (clist->column[column].min_width == min_width)
1724 if (clist->column[column].max_width >= 0 &&
1725 clist->column[column].max_width < min_width)
1726 clist->column[column].min_width = clist->column[column].max_width;
1728 clist->column[column].min_width = min_width;
1730 if (clist->column[column].area.width < clist->column[column].min_width)
1731 gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
1735 gtk_clist_set_column_max_width (GtkCList *clist,
1739 g_return_if_fail (clist != NULL);
1740 g_return_if_fail (GTK_IS_CLIST (clist));
1742 if (column < 0 || column >= clist->columns)
1744 if (clist->column[column].max_width == max_width)
1747 if (clist->column[column].min_width >= 0 && max_width >= 0 &&
1748 clist->column[column].min_width > max_width)
1749 clist->column[column].max_width = clist->column[column].min_width;
1751 clist->column[column].max_width = max_width;
1753 if (clist->column[column].area.width > clist->column[column].max_width)
1754 gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
1757 /* PRIVATE COLUMN FUNCTIONS
1758 * column_auto_resize
1759 * real_resize_column
1760 * abort_column_resize
1761 * size_allocate_title_buttons
1762 * size_allocate_columns
1763 * list_requisition_width
1765 * column_button_create
1766 * column_button_clicked
1769 column_auto_resize (GtkCList *clist,
1770 GtkCListRow *clist_row,
1774 /* resize column if needed for auto_resize */
1775 GtkRequisition requisition;
1777 if (!clist->column[column].auto_resize ||
1778 GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
1782 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
1783 column, &requisition);
1785 requisition.width = 0;
1787 if (requisition.width > clist->column[column].width)
1788 gtk_clist_set_column_width (clist, column, requisition.width);
1789 else if (requisition.width < old_width &&
1790 old_width == clist->column[column].width)
1795 /* run a "gtk_clist_optimal_column_width" but break, if
1796 * the column doesn't shrink */
1797 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1798 new_width = (clist->column[column].button->requisition.width -
1799 (CELL_SPACING + (2 * COLUMN_INSET)));
1803 for (list = clist->row_list; list; list = list->next)
1805 GTK_CLIST_CLASS_FW (clist)->cell_size_request
1806 (clist, GTK_CLIST_ROW (list), column, &requisition);
1807 new_width = MAX (new_width, requisition.width);
1808 if (new_width == clist->column[column].width)
1811 if (new_width < clist->column[column].width)
1812 gtk_clist_set_column_width
1813 (clist, column, MAX (new_width, clist->column[column].min_width));
1818 real_resize_column (GtkCList *clist,
1822 g_return_if_fail (clist != NULL);
1823 g_return_if_fail (GTK_IS_CLIST (clist));
1825 if (column < 0 || column >= clist->columns)
1828 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
1829 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
1830 if (clist->column[column].max_width >= 0 &&
1831 width > clist->column[column].max_width)
1832 width = clist->column[column].max_width;
1834 clist->column[column].width = width;
1835 clist->column[column].width_set = TRUE;
1837 /* FIXME: this is quite expensive to do if the widget hasn't
1838 * been size_allocated yet, and pointless. Should
1841 size_allocate_columns (clist, TRUE);
1842 size_allocate_title_buttons (clist);
1844 CLIST_REFRESH (clist);
1848 abort_column_resize (GtkCList *clist)
1850 g_return_if_fail (clist != NULL);
1851 g_return_if_fail (GTK_IS_CLIST (clist));
1853 if (!GTK_CLIST_IN_DRAG(clist))
1856 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
1857 gtk_grab_remove (GTK_WIDGET (clist));
1858 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1859 clist->drag_pos = -1;
1861 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
1862 draw_xor_line (clist);
1864 if (GTK_CLIST_ADD_MODE(clist))
1866 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
1867 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
1872 size_allocate_title_buttons (GtkCList *clist)
1874 GtkAllocation button_allocation;
1876 gint last_button = 0;
1879 if (!GTK_WIDGET_REALIZED (clist))
1882 button_allocation.x = clist->hoffset;
1883 button_allocation.y = 0;
1884 button_allocation.width = 0;
1885 button_allocation.height = clist->column_title_area.height;
1887 /* find last visible column */
1888 for (last_column = clist->columns - 1; last_column >= 0; last_column--)
1889 if (clist->column[last_column].visible)
1892 for (i = 0; i < last_column; i++)
1894 if (!clist->column[i].visible)
1896 last_button = i + 1;
1897 gdk_window_hide (clist->column[i].window);
1901 button_allocation.width += (clist->column[i].area.width +
1902 CELL_SPACING + 2 * COLUMN_INSET);
1904 if (!clist->column[i + 1].button)
1906 gdk_window_hide (clist->column[i].window);
1910 gtk_widget_size_allocate (clist->column[last_button].button,
1911 &button_allocation);
1912 button_allocation.x += button_allocation.width;
1913 button_allocation.width = 0;
1915 if (clist->column[last_button].resizeable)
1917 gdk_window_show (clist->column[last_button].window);
1918 gdk_window_move_resize (clist->column[last_button].window,
1919 button_allocation.x - (DRAG_WIDTH / 2),
1921 clist->column_title_area.height);
1924 gdk_window_hide (clist->column[last_button].window);
1926 last_button = i + 1;
1929 button_allocation.width += (clist->column[last_column].area.width +
1930 2 * (CELL_SPACING + COLUMN_INSET));
1931 gtk_widget_size_allocate (clist->column[last_button].button,
1932 &button_allocation);
1934 if (clist->column[last_button].resizeable)
1936 button_allocation.x += button_allocation.width;
1938 gdk_window_show (clist->column[last_button].window);
1939 gdk_window_move_resize (clist->column[last_button].window,
1940 button_allocation.x - (DRAG_WIDTH / 2),
1941 0, DRAG_WIDTH, clist->column_title_area.height);
1944 gdk_window_hide (clist->column[last_button].window);
1948 size_allocate_columns (GtkCList *clist,
1949 gboolean block_resize)
1951 gint xoffset = CELL_SPACING + COLUMN_INSET;
1955 /* find last visible column and calculate correct column width */
1956 for (last_column = clist->columns - 1;
1957 last_column >= 0 && !clist->column[last_column].visible; last_column--);
1959 if (last_column < 0)
1962 for (i = 0; i <= last_column; i++)
1964 if (!clist->column[i].visible)
1966 clist->column[i].area.x = xoffset;
1967 if (clist->column[i].width_set)
1969 if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
1970 clist->column[i].auto_resize && clist->column[i].button)
1974 width = (clist->column[i].button->requisition.width -
1975 (CELL_SPACING + (2 * COLUMN_INSET)));
1977 if (width > clist->column[i].width)
1978 gtk_clist_set_column_width (clist, i, width);
1981 clist->column[i].area.width = clist->column[i].width;
1982 xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
1984 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
1986 clist->column[i].area.width =
1987 clist->column[i].button->requisition.width -
1988 (CELL_SPACING + (2 * COLUMN_INSET));
1989 xoffset += clist->column[i].button->requisition.width;
1993 clist->column[last_column].area.width = clist->column[last_column].area.width
1994 + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
1998 list_requisition_width (GtkCList *clist)
2000 gint width = CELL_SPACING;
2003 for (i = clist->columns - 1; i >= 0; i--)
2005 if (!clist->column[i].visible)
2008 if (clist->column[i].width_set)
2009 width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
2010 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2011 width += clist->column[i].button->requisition.width;
2017 /* this function returns the new width of the column being resized given
2018 * the column and x position of the cursor; the x cursor position is passed
2019 * in as a pointer and automagicly corrected if it's beyond min/max limits */
2021 new_column_width (GtkCList *clist,
2025 gint xthickness = GTK_WIDGET (clist)->style->klass->xthickness;
2031 /* first translate the x position from widget->window
2032 * to clist->clist_window */
2033 cx = *x - xthickness;
2035 for (last_column = clist->columns - 1;
2036 last_column >= 0 && !clist->column[last_column].visible; last_column--);
2038 /* calculate new column width making sure it doesn't end up
2039 * less than the minimum width */
2040 dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
2041 (column < last_column) * CELL_SPACING);
2044 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
2046 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
2048 *x = cx + xthickness;
2050 else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
2051 width > clist->column[column].max_width)
2053 width = clist->column[column].max_width;
2054 cx = dx + clist->column[column].max_width;
2055 *x = cx + xthickness;
2058 if (cx < 0 || cx > clist->clist_window_width)
2065 column_button_create (GtkCList *clist,
2070 gtk_widget_push_composite_child ();
2071 button = clist->column[column].button = gtk_button_new ();
2072 gtk_widget_pop_composite_child ();
2074 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
2075 gtk_widget_set_parent_window (clist->column[column].button,
2076 clist->title_window);
2077 gtk_widget_set_parent (button, GTK_WIDGET (clist));
2079 gtk_signal_connect (GTK_OBJECT (button), "clicked",
2080 (GtkSignalFunc) column_button_clicked,
2083 gtk_widget_show (button);
2087 column_button_clicked (GtkWidget *widget,
2093 g_return_if_fail (widget != NULL);
2094 g_return_if_fail (GTK_IS_CLIST (data));
2096 clist = GTK_CLIST (data);
2098 /* find the column who's button was pressed */
2099 for (i = 0; i < clist->columns; i++)
2100 if (clist->column[i].button == widget)
2103 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
2107 gtk_clist_set_row_height (GtkCList *clist,
2112 g_return_if_fail (clist != NULL);
2113 g_return_if_fail (GTK_IS_CLIST (clist));
2115 widget = GTK_WIDGET (clist);
2119 clist->row_height = height;
2120 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
2124 GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
2125 clist->row_height = 0;
2128 if (GTK_WIDGET_REALIZED (clist))
2130 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
2132 clist->row_height = (widget->style->font->ascent +
2133 widget->style->font->descent + 1);
2134 clist->row_center_offset = widget->style->font->ascent + 1.5;
2137 clist->row_center_offset = 1.5 + (clist->row_height +
2138 widget->style->font->ascent -
2139 widget->style->font->descent - 1) / 2;
2142 CLIST_REFRESH (clist);
2146 gtk_clist_moveto (GtkCList *clist,
2152 g_return_if_fail (clist != NULL);
2153 g_return_if_fail (GTK_IS_CLIST (clist));
2155 if (row < -1 || row >= clist->rows)
2157 if (column < -1 || column >= clist->columns)
2160 row_align = CLAMP (row_align, 0, 1);
2161 col_align = CLAMP (col_align, 0, 1);
2163 /* adjust horizontal scrollbar */
2164 if (clist->hadjustment && column >= 0)
2168 x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
2169 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
2170 CELL_SPACING - clist->column[column].area.width)));
2172 gtk_adjustment_set_value (clist->hadjustment, 0.0);
2173 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
2174 gtk_adjustment_set_value
2175 (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
2177 gtk_adjustment_set_value (clist->hadjustment, x);
2180 /* adjust vertical scrollbar */
2181 if (clist->vadjustment && row >= 0)
2182 move_vertical (clist, row, row_align);
2185 /* PUBLIC CELL FUNCTIONS
2186 * gtk_clist_get_cell_type
2187 * gtk_clist_set_text
2188 * gtk_clist_get_text
2189 * gtk_clist_set_pixmap
2190 * gtk_clist_get_pixmap
2191 * gtk_clist_set_pixtext
2192 * gtk_clist_get_pixtext
2193 * gtk_clist_set_shift
2196 gtk_clist_get_cell_type (GtkCList *clist,
2200 GtkCListRow *clist_row;
2202 g_return_val_if_fail (clist != NULL, -1);
2203 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2205 if (row < 0 || row >= clist->rows)
2207 if (column < 0 || column >= clist->columns)
2210 clist_row = (g_list_nth (clist->row_list, row))->data;
2212 return clist_row->cell[column].type;
2216 gtk_clist_set_text (GtkCList *clist,
2221 GtkCListRow *clist_row;
2223 g_return_if_fail (clist != NULL);
2224 g_return_if_fail (GTK_IS_CLIST (clist));
2226 if (row < 0 || row >= clist->rows)
2228 if (column < 0 || column >= clist->columns)
2231 clist_row = (g_list_nth (clist->row_list, row))->data;
2233 /* if text is null, then the cell is empty */
2234 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2235 (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
2237 /* redraw the list if it's not frozen */
2238 if (CLIST_UNFROZEN (clist))
2240 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2241 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2246 gtk_clist_get_text (GtkCList *clist,
2251 GtkCListRow *clist_row;
2253 g_return_val_if_fail (clist != NULL, 0);
2254 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2256 if (row < 0 || row >= clist->rows)
2258 if (column < 0 || column >= clist->columns)
2261 clist_row = (g_list_nth (clist->row_list, row))->data;
2263 if (clist_row->cell[column].type != GTK_CELL_TEXT)
2267 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
2273 gtk_clist_set_pixmap (GtkCList *clist,
2279 GtkCListRow *clist_row;
2281 g_return_if_fail (clist != NULL);
2282 g_return_if_fail (GTK_IS_CLIST (clist));
2284 if (row < 0 || row >= clist->rows)
2286 if (column < 0 || column >= clist->columns)
2289 clist_row = (g_list_nth (clist->row_list, row))->data;
2291 gdk_pixmap_ref (pixmap);
2293 if (mask) gdk_pixmap_ref (mask);
2295 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2296 (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
2298 /* redraw the list if it's not frozen */
2299 if (CLIST_UNFROZEN (clist))
2301 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2302 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2307 gtk_clist_get_pixmap (GtkCList *clist,
2313 GtkCListRow *clist_row;
2315 g_return_val_if_fail (clist != NULL, 0);
2316 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2318 if (row < 0 || row >= clist->rows)
2320 if (column < 0 || column >= clist->columns)
2323 clist_row = (g_list_nth (clist->row_list, row))->data;
2325 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
2330 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
2331 /* mask can be NULL */
2332 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
2339 gtk_clist_set_pixtext (GtkCList *clist,
2347 GtkCListRow *clist_row;
2349 g_return_if_fail (clist != NULL);
2350 g_return_if_fail (GTK_IS_CLIST (clist));
2352 if (row < 0 || row >= clist->rows)
2354 if (column < 0 || column >= clist->columns)
2357 clist_row = (g_list_nth (clist->row_list, row))->data;
2359 gdk_pixmap_ref (pixmap);
2360 if (mask) gdk_pixmap_ref (mask);
2361 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2362 (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
2364 /* redraw the list if it's not frozen */
2365 if (CLIST_UNFROZEN (clist))
2367 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2368 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2373 gtk_clist_get_pixtext (GtkCList *clist,
2381 GtkCListRow *clist_row;
2383 g_return_val_if_fail (clist != NULL, 0);
2384 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2386 if (row < 0 || row >= clist->rows)
2388 if (column < 0 || column >= clist->columns)
2391 clist_row = (g_list_nth (clist->row_list, row))->data;
2393 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
2397 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
2399 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2401 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
2403 /* mask can be NULL */
2404 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
2410 gtk_clist_set_shift (GtkCList *clist,
2416 GtkRequisition requisition;
2417 GtkCListRow *clist_row;
2419 g_return_if_fail (clist != NULL);
2420 g_return_if_fail (GTK_IS_CLIST (clist));
2422 if (row < 0 || row >= clist->rows)
2424 if (column < 0 || column >= clist->columns)
2427 clist_row = (g_list_nth (clist->row_list, row))->data;
2429 if (clist->column[column].auto_resize &&
2430 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2431 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2432 column, &requisition);
2434 clist_row->cell[column].vertical = vertical;
2435 clist_row->cell[column].horizontal = horizontal;
2437 column_auto_resize (clist, clist_row, column, requisition.width);
2439 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2440 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2443 /* PRIVATE CELL FUNCTIONS
2448 set_cell_contents (GtkCList *clist,
2449 GtkCListRow *clist_row,
2457 GtkRequisition requisition;
2459 g_return_if_fail (clist != NULL);
2460 g_return_if_fail (GTK_IS_CLIST (clist));
2461 g_return_if_fail (clist_row != NULL);
2463 if (clist->column[column].auto_resize &&
2464 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2465 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2466 column, &requisition);
2468 switch (clist_row->cell[column].type)
2470 case GTK_CELL_EMPTY:
2473 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2475 case GTK_CELL_PIXMAP:
2476 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2477 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
2478 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2480 case GTK_CELL_PIXTEXT:
2481 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2482 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2483 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
2484 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2486 case GTK_CELL_WIDGET:
2493 clist_row->cell[column].type = GTK_CELL_EMPTY;
2500 clist_row->cell[column].type = GTK_CELL_TEXT;
2501 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2504 case GTK_CELL_PIXMAP:
2507 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2508 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2509 /* We set the mask even if it is NULL */
2510 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2513 case GTK_CELL_PIXTEXT:
2516 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2517 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2518 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2519 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2520 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2527 if (clist->column[column].auto_resize &&
2528 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2529 column_auto_resize (clist, clist_row, column, requisition.width);
2533 cell_size_request (GtkCList *clist,
2534 GtkCListRow *clist_row,
2536 GtkRequisition *requisition)
2542 g_return_if_fail (clist != NULL);
2543 g_return_if_fail (GTK_IS_CLIST (clist));
2544 g_return_if_fail (requisition != NULL);
2546 get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
2549 switch (clist_row->cell[column].type)
2552 requisition->width =
2553 gdk_string_width (style->font,
2554 GTK_CELL_TEXT (clist_row->cell[column])->text);
2555 requisition->height = style->font->ascent + style->font->descent;
2557 case GTK_CELL_PIXTEXT:
2558 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
2560 requisition->width = width +
2561 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing +
2562 gdk_string_width (style->font,
2563 GTK_CELL_TEXT (clist_row->cell[column])->text);
2565 requisition->height = MAX (style->font->ascent + style->font->descent,
2568 case GTK_CELL_PIXMAP:
2569 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
2571 requisition->width = width;
2572 requisition->height = height;
2575 requisition->width = 0;
2576 requisition->height = 0;
2580 requisition->width += clist_row->cell[column].horizontal;
2581 requisition->height += clist_row->cell[column].vertical;
2584 /* PUBLIC INSERT/REMOVE ROW FUNCTIONS
2592 gtk_clist_prepend (GtkCList *clist,
2595 g_return_val_if_fail (clist != NULL, -1);
2596 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2597 g_return_val_if_fail (text != NULL, -1);
2599 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, 0, text);
2603 gtk_clist_append (GtkCList *clist,
2606 g_return_val_if_fail (clist != NULL, -1);
2607 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2608 g_return_val_if_fail (text != NULL, -1);
2610 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
2614 gtk_clist_insert (GtkCList *clist,
2618 g_return_val_if_fail (clist != NULL, -1);
2619 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2620 g_return_val_if_fail (text != NULL, -1);
2622 if (row < 0 || row > clist->rows)
2625 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
2629 gtk_clist_remove (GtkCList *clist,
2632 GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
2636 gtk_clist_clear (GtkCList *clist)
2638 g_return_if_fail (clist != NULL);
2639 g_return_if_fail (GTK_IS_CLIST (clist));
2641 GTK_CLIST_CLASS_FW (clist)->clear (clist);
2644 /* PRIVATE INSERT/REMOVE ROW FUNCTIONS
2651 real_insert_row (GtkCList *clist,
2656 GtkCListRow *clist_row;
2658 g_return_val_if_fail (clist != NULL, -1);
2659 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2660 g_return_val_if_fail (text != NULL, -1);
2662 /* return if out of bounds */
2663 if (row < 0 || row > clist->rows)
2666 /* create the row */
2667 clist_row = row_new (clist);
2669 /* set the text in the row's columns */
2670 for (i = 0; i < clist->columns; i++)
2672 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2673 (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
2677 clist->row_list = g_list_append (clist->row_list, clist_row);
2678 clist->row_list_end = clist->row_list;
2682 if (GTK_CLIST_AUTO_SORT(clist)) /* override insertion pos */
2687 work = clist->row_list;
2689 if (clist->sort_type == GTK_SORT_ASCENDING)
2691 while (row < clist->rows &&
2692 clist->compare (clist, clist_row,
2693 GTK_CLIST_ROW (work)) > 0)
2701 while (row < clist->rows &&
2702 clist->compare (clist, clist_row,
2703 GTK_CLIST_ROW (work)) < 0)
2711 /* reset the row end pointer if we're inserting at the end of the list */
2712 if (row == clist->rows)
2713 clist->row_list_end = (g_list_append (clist->row_list_end,
2716 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
2721 if (row < ROW_FROM_YPIXEL (clist, 0))
2722 clist->voffset -= (clist->row_height + CELL_SPACING);
2724 /* syncronize the selection list */
2725 sync_selection (clist, row, SYNC_INSERT);
2727 if (clist->rows == 1)
2729 clist->focus_row = 0;
2730 if (clist->selection_mode == GTK_SELECTION_BROWSE)
2731 gtk_clist_select_row (clist, 0, -1);
2734 /* redraw the list if it isn't frozen */
2735 if (CLIST_UNFROZEN (clist))
2737 adjust_adjustments (clist, FALSE);
2739 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2740 draw_rows (clist, NULL);
2747 real_remove_row (GtkCList *clist,
2750 gint was_visible, was_selected;
2752 GtkCListRow *clist_row;
2754 g_return_if_fail (clist != NULL);
2755 g_return_if_fail (GTK_IS_CLIST (clist));
2757 /* return if out of bounds */
2758 if (row < 0 || row > (clist->rows - 1))
2761 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
2764 /* get the row we're going to delete */
2765 list = g_list_nth (clist->row_list, row);
2766 g_assert (list != NULL);
2767 clist_row = list->data;
2769 /* if we're removing a selected row, we have to make sure
2770 * it's properly unselected, and then sync up the clist->selected
2771 * list to reflect the deincrimented indexies of rows after the
2773 if (clist_row->state == GTK_STATE_SELECTED)
2774 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2777 /* reset the row end pointer if we're removing at the
2778 * end of the list */
2780 if (clist->row_list == list)
2781 clist->row_list = g_list_next (list);
2782 if (clist->row_list_end == list)
2783 clist->row_list_end = g_list_previous (list);
2784 g_list_remove (list, clist_row);
2786 /*if (clist->focus_row >=0 &&
2787 (row <= clist->focus_row || clist->focus_row >= clist->rows))
2788 clist->focus_row--;*/
2790 if (row < ROW_FROM_YPIXEL (clist, 0))
2791 clist->voffset += clist->row_height + CELL_SPACING;
2793 sync_selection (clist, row, SYNC_REMOVE);
2795 if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
2796 clist->focus_row >= 0)
2797 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2798 clist->focus_row, -1, NULL);
2801 row_delete (clist, clist_row);
2803 /* redraw the row if it isn't frozen */
2804 if (CLIST_UNFROZEN (clist))
2806 adjust_adjustments (clist, FALSE);
2809 draw_rows (clist, NULL);
2814 real_clear (GtkCList *clist)
2820 g_return_if_fail (clist != NULL);
2821 g_return_if_fail (GTK_IS_CLIST (clist));
2823 /* free up the selection list */
2824 g_list_free (clist->selection);
2825 g_list_free (clist->undo_selection);
2826 g_list_free (clist->undo_unselection);
2828 clist->selection = NULL;
2829 clist->selection_end = NULL;
2830 clist->undo_selection = NULL;
2831 clist->undo_unselection = NULL;
2833 clist->focus_row = -1;
2835 clist->undo_anchor = -1;
2836 clist->anchor_state = GTK_STATE_SELECTED;
2837 clist->drag_pos = -1;
2839 /* remove all the rows */
2840 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2841 free_list = clist->row_list;
2842 clist->row_list = NULL;
2843 clist->row_list_end = NULL;
2845 for (list = free_list; list; list = list->next)
2846 row_delete (clist, GTK_CLIST_ROW (list));
2847 g_list_free (free_list);
2848 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2849 for (i = 0; i < clist->columns; i++)
2850 if (clist->column[i].auto_resize)
2852 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2853 gtk_clist_set_column_width
2854 (clist, i, (clist->column[i].button->requisition.width -
2855 (CELL_SPACING + (2 * COLUMN_INSET))));
2857 gtk_clist_set_column_width (clist, i, 0);
2859 /* zero-out the scrollbars */
2860 if (clist->vadjustment)
2862 gtk_adjustment_set_value (clist->vadjustment, 0.0);
2863 CLIST_REFRESH (clist);
2866 gtk_widget_queue_resize (GTK_WIDGET (clist));
2870 real_row_move (GtkCList *clist,
2874 GtkCListRow *clist_row;
2879 g_return_if_fail (clist != NULL);
2880 g_return_if_fail (GTK_IS_CLIST (clist));
2882 if (GTK_CLIST_AUTO_SORT(clist))
2885 if (source_row < 0 || source_row >= clist->rows ||
2886 dest_row < 0 || dest_row >= clist->rows ||
2887 source_row == dest_row)
2890 gtk_clist_freeze (clist);
2892 /* unlink source row */
2893 clist_row = g_list_nth_data (clist->row_list, source_row);
2894 if (source_row == clist->rows - 1)
2895 clist->row_list_end = clist->row_list_end->prev;
2896 clist->row_list = g_list_remove (clist->row_list, clist_row);
2899 /* relink source row */
2900 clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
2901 if (dest_row == clist->rows)
2902 clist->row_list_end = clist->row_list_end->next;
2905 /* sync selection */
2906 if (source_row > dest_row)
2919 for (list = clist->selection; list; list = list->next)
2921 if (list->data == GINT_TO_POINTER (source_row))
2922 list->data = GINT_TO_POINTER (dest_row);
2923 else if (first <= GPOINTER_TO_INT (list->data) &&
2924 last >= GPOINTER_TO_INT (list->data))
2925 list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
2928 if (clist->focus_row == source_row)
2929 clist->focus_row = dest_row;
2930 else if (clist->focus_row > first)
2931 clist->focus_row += d;
2933 gtk_clist_thaw (clist);
2936 /* PUBLIC ROW FUNCTIONS
2937 * gtk_clist_set_row_data
2938 * gtk_clist_set_row_data_full
2939 * gtk_clist_get_row_data
2940 * gtk_clist_find_row_from_data
2941 * gtk_clist_swap_rows
2942 * gtk_clist_row_move
2943 * gtk_clist_row_is_visible
2944 * gtk_clist_set_foreground
2945 * gtk_clist_set_background
2948 gtk_clist_set_row_data (GtkCList *clist,
2952 gtk_clist_set_row_data_full (clist, row, data, NULL);
2956 gtk_clist_set_row_data_full (GtkCList *clist,
2959 GtkDestroyNotify destroy)
2961 GtkCListRow *clist_row;
2963 g_return_if_fail (clist != NULL);
2964 g_return_if_fail (GTK_IS_CLIST (clist));
2966 if (row < 0 || row > (clist->rows - 1))
2969 clist_row = (g_list_nth (clist->row_list, row))->data;
2970 clist_row->data = data;
2971 clist_row->destroy = destroy;
2975 gtk_clist_get_row_data (GtkCList *clist,
2978 GtkCListRow *clist_row;
2980 g_return_val_if_fail (clist != NULL, NULL);
2981 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
2983 if (row < 0 || row > (clist->rows - 1))
2986 clist_row = (g_list_nth (clist->row_list, row))->data;
2987 return clist_row->data;
2991 gtk_clist_find_row_from_data (GtkCList *clist,
2997 g_return_val_if_fail (clist != NULL, -1);
2998 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
3000 for (n = 0, list = clist->row_list; list; n++, list = list->next)
3001 if (GTK_CLIST_ROW (list)->data == data)
3008 gtk_clist_swap_rows (GtkCList *clist,
3014 g_return_if_fail (clist != NULL);
3015 g_return_if_fail (GTK_IS_CLIST (clist));
3016 g_return_if_fail (row1 != row2);
3018 if (GTK_CLIST_AUTO_SORT(clist))
3021 gtk_clist_freeze (clist);
3023 first = MIN (row1, row2);
3024 last = MAX (row1, row2);
3026 gtk_clist_row_move (clist, last, first);
3027 gtk_clist_row_move (clist, first + 1, last);
3029 gtk_clist_thaw (clist);
3033 gtk_clist_row_move (GtkCList *clist,
3037 g_return_if_fail (clist != NULL);
3038 g_return_if_fail (GTK_IS_CLIST (clist));
3040 if (GTK_CLIST_AUTO_SORT(clist))
3043 if (source_row < 0 || source_row >= clist->rows ||
3044 dest_row < 0 || dest_row >= clist->rows ||
3045 source_row == dest_row)
3048 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE],
3049 source_row, dest_row);
3053 gtk_clist_row_is_visible (GtkCList *clist,
3058 g_return_val_if_fail (clist != NULL, 0);
3059 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3061 if (row < 0 || row >= clist->rows)
3062 return GTK_VISIBILITY_NONE;
3064 if (clist->row_height == 0)
3065 return GTK_VISIBILITY_NONE;
3067 if (row < ROW_FROM_YPIXEL (clist, 0))
3068 return GTK_VISIBILITY_NONE;
3070 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
3071 return GTK_VISIBILITY_NONE;
3073 top = ROW_TOP_YPIXEL (clist, row);
3076 || ((top + clist->row_height) >= clist->clist_window_height))
3077 return GTK_VISIBILITY_PARTIAL;
3079 return GTK_VISIBILITY_FULL;
3083 gtk_clist_set_foreground (GtkCList *clist,
3087 GtkCListRow *clist_row;
3089 g_return_if_fail (clist != NULL);
3090 g_return_if_fail (GTK_IS_CLIST (clist));
3092 if (row < 0 || row >= clist->rows)
3095 clist_row = (g_list_nth (clist->row_list, row))->data;
3099 clist_row->foreground = *color;
3100 clist_row->fg_set = TRUE;
3101 if (GTK_WIDGET_REALIZED (clist))
3102 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3103 &clist_row->foreground);
3106 clist_row->fg_set = FALSE;
3108 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3109 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3113 gtk_clist_set_background (GtkCList *clist,
3117 GtkCListRow *clist_row;
3119 g_return_if_fail (clist != NULL);
3120 g_return_if_fail (GTK_IS_CLIST (clist));
3122 if (row < 0 || row >= clist->rows)
3125 clist_row = (g_list_nth (clist->row_list, row))->data;
3129 clist_row->background = *color;
3130 clist_row->bg_set = TRUE;
3131 if (GTK_WIDGET_REALIZED (clist))
3132 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3133 &clist_row->background);
3136 clist_row->bg_set = FALSE;
3138 if (CLIST_UNFROZEN (clist)
3139 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3140 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3143 /* PUBLIC ROW/CELL STYLE FUNCTIONS
3144 * gtk_clist_set_cell_style
3145 * gtk_clist_get_cell_style
3146 * gtk_clist_set_row_style
3147 * gtk_clist_get_row_style
3150 gtk_clist_set_cell_style (GtkCList *clist,
3155 GtkRequisition requisition;
3156 GtkCListRow *clist_row;
3158 g_return_if_fail (clist != NULL);
3159 g_return_if_fail (GTK_IS_CLIST (clist));
3161 if (row < 0 || row >= clist->rows)
3163 if (column < 0 || column >= clist->columns)
3166 clist_row = (g_list_nth (clist->row_list, row))->data;
3168 if (clist_row->cell[column].style == style)
3171 if (clist->column[column].auto_resize &&
3172 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3173 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3174 column, &requisition);
3176 if (clist_row->cell[column].style)
3178 if (GTK_WIDGET_REALIZED (clist))
3179 gtk_style_detach (clist_row->cell[column].style);
3180 gtk_style_unref (clist_row->cell[column].style);
3183 clist_row->cell[column].style = style;
3185 if (clist_row->cell[column].style)
3187 gtk_style_ref (clist_row->cell[column].style);
3189 if (GTK_WIDGET_REALIZED (clist))
3190 clist_row->cell[column].style =
3191 gtk_style_attach (clist_row->cell[column].style,
3192 clist->clist_window);
3195 column_auto_resize (clist, clist_row, column, requisition.width);
3197 /* redraw the list if it's not frozen */
3198 if (CLIST_UNFROZEN (clist))
3200 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3201 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3206 gtk_clist_get_cell_style (GtkCList *clist,
3210 GtkCListRow *clist_row;
3212 g_return_val_if_fail (clist != NULL, NULL);
3213 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3215 if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
3218 clist_row = (g_list_nth (clist->row_list, row))->data;
3220 return clist_row->cell[column].style;
3224 gtk_clist_set_row_style (GtkCList *clist,
3228 GtkRequisition requisition;
3229 GtkCListRow *clist_row;
3233 g_return_if_fail (clist != NULL);
3234 g_return_if_fail (GTK_IS_CLIST (clist));
3236 if (row < 0 || row >= clist->rows)
3239 clist_row = (g_list_nth (clist->row_list, row))->data;
3241 if (clist_row->style == style)
3244 old_width = g_new (gint, clist->columns);
3246 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3248 for (i = 0; i < clist->columns; i++)
3249 if (clist->column[i].auto_resize)
3251 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3253 old_width[i] = requisition.width;
3257 if (clist_row->style)
3259 if (GTK_WIDGET_REALIZED (clist))
3260 gtk_style_detach (clist_row->style);
3261 gtk_style_unref (clist_row->style);
3264 clist_row->style = style;
3266 if (clist_row->style)
3268 gtk_style_ref (clist_row->style);
3270 if (GTK_WIDGET_REALIZED (clist))
3271 clist_row->style = gtk_style_attach (clist_row->style,
3272 clist->clist_window);
3275 if (GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3276 for (i = 0; i < clist->columns; i++)
3277 column_auto_resize (clist, clist_row, i, old_width[i]);
3281 /* redraw the list if it's not frozen */
3282 if (CLIST_UNFROZEN (clist))
3284 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3285 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3290 gtk_clist_get_row_style (GtkCList *clist,
3293 GtkCListRow *clist_row;
3295 g_return_val_if_fail (clist != NULL, NULL);
3296 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3298 if (row < 0 || row >= clist->rows)
3301 clist_row = (g_list_nth (clist->row_list, row))->data;
3303 return clist_row->style;
3306 /* PUBLIC SELECTION FUNCTIONS
3307 * gtk_clist_set_selectable
3308 * gtk_clist_get_selectable
3309 * gtk_clist_select_row
3310 * gtk_clist_unselect_row
3311 * gtk_clist_select_all
3312 * gtk_clist_unselect_all
3313 * gtk_clist_undo_selection
3316 gtk_clist_set_selectable (GtkCList *clist,
3318 gboolean selectable)
3320 GtkCListRow *clist_row;
3322 g_return_if_fail (clist != NULL);
3323 g_return_if_fail (GTK_IS_CLIST (clist));
3325 if (row < 0 || row >= clist->rows)
3328 clist_row = (g_list_nth (clist->row_list, row))->data;
3330 if (selectable == clist_row->selectable)
3333 clist_row->selectable = selectable;
3335 if (!selectable && clist_row->state == GTK_STATE_SELECTED)
3337 if (clist->anchor >= 0 &&
3338 clist->selection_mode == GTK_SELECTION_EXTENDED)
3340 clist->drag_button = 0;
3341 remove_grab (clist);
3342 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3344 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3350 gtk_clist_get_selectable (GtkCList *clist,
3353 g_return_val_if_fail (clist != NULL, FALSE);
3354 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
3356 if (row < 0 || row >= clist->rows)
3359 return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
3363 gtk_clist_select_row (GtkCList *clist,
3367 g_return_if_fail (clist != NULL);
3368 g_return_if_fail (GTK_IS_CLIST (clist));
3370 if (row < 0 || row >= clist->rows)
3372 if (column < -1 || column >= clist->columns)
3375 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3380 gtk_clist_unselect_row (GtkCList *clist,
3384 g_return_if_fail (clist != NULL);
3385 g_return_if_fail (GTK_IS_CLIST (clist));
3387 if (row < 0 || row >= clist->rows)
3389 if (column < -1 || column >= clist->columns)
3392 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3397 gtk_clist_select_all (GtkCList *clist)
3399 g_return_if_fail (clist != NULL);
3400 g_return_if_fail (GTK_IS_CLIST (clist));
3402 GTK_CLIST_CLASS_FW (clist)->select_all (clist);
3406 gtk_clist_unselect_all (GtkCList *clist)
3408 g_return_if_fail (clist != NULL);
3409 g_return_if_fail (GTK_IS_CLIST (clist));
3411 GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
3415 gtk_clist_undo_selection (GtkCList *clist)
3417 g_return_if_fail (clist != NULL);
3418 g_return_if_fail (GTK_IS_CLIST (clist));
3420 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
3421 (clist->undo_selection || clist->undo_unselection))
3422 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
3425 /* PRIVATE SELECTION FUNCTIONS
3436 * real_undo_selection
3439 * update_extended_selection
3446 selection_find (GtkCList *clist,
3448 GList *row_list_element)
3450 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
3454 toggle_row (GtkCList *clist,
3459 GtkCListRow *clist_row;
3461 switch (clist->selection_mode)
3463 case GTK_SELECTION_EXTENDED:
3464 case GTK_SELECTION_MULTIPLE:
3465 case GTK_SELECTION_SINGLE:
3466 clist_row = g_list_nth (clist->row_list, row)->data;
3471 if (clist_row->state == GTK_STATE_SELECTED)
3473 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3474 row, column, event);
3477 case GTK_SELECTION_BROWSE:
3478 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3479 row, column, event);
3485 fake_toggle_row (GtkCList *clist,
3490 work = g_list_nth (clist->row_list, row);
3492 if (!work || !GTK_CLIST_ROW (work)->selectable)
3495 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
3496 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3498 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3500 if (CLIST_UNFROZEN (clist) &&
3501 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3502 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
3503 GTK_CLIST_ROW (work));
3507 toggle_focus_row (GtkCList *clist)
3509 g_return_if_fail (clist != 0);
3510 g_return_if_fail (GTK_IS_CLIST (clist));
3512 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3513 clist->focus_row < 0 || clist->focus_row >= clist->rows)
3516 switch (clist->selection_mode)
3518 case GTK_SELECTION_SINGLE:
3519 case GTK_SELECTION_MULTIPLE:
3520 toggle_row (clist, clist->focus_row, 0, NULL);
3522 case GTK_SELECTION_EXTENDED:
3523 g_list_free (clist->undo_selection);
3524 g_list_free (clist->undo_unselection);
3525 clist->undo_selection = NULL;
3526 clist->undo_unselection = NULL;
3528 clist->anchor = clist->focus_row;
3529 clist->drag_pos = clist->focus_row;
3530 clist->undo_anchor = clist->focus_row;
3532 if (GTK_CLIST_ADD_MODE(clist))
3533 fake_toggle_row (clist, clist->focus_row);
3535 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
3537 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3545 toggle_add_mode (GtkCList *clist)
3547 g_return_if_fail (clist != 0);
3548 g_return_if_fail (GTK_IS_CLIST (clist));
3550 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3551 clist->selection_mode != GTK_SELECTION_EXTENDED)
3554 gtk_clist_draw_focus (GTK_WIDGET (clist));
3555 if (!GTK_CLIST_ADD_MODE(clist))
3557 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
3558 gdk_gc_set_line_attributes (clist->xor_gc, 1,
3559 GDK_LINE_ON_OFF_DASH, 0, 0);
3560 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
3564 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
3565 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
3566 clist->anchor_state = GTK_STATE_SELECTED;
3568 gtk_clist_draw_focus (GTK_WIDGET (clist));
3572 real_select_row (GtkCList *clist,
3577 GtkCListRow *clist_row;
3580 gboolean row_selected;
3582 g_return_if_fail (clist != NULL);
3583 g_return_if_fail (GTK_IS_CLIST (clist));
3585 if (row < 0 || row > (clist->rows - 1))
3588 switch (clist->selection_mode)
3590 case GTK_SELECTION_SINGLE:
3591 case GTK_SELECTION_BROWSE:
3593 row_selected = FALSE;
3594 list = clist->selection;
3598 sel_row = GPOINTER_TO_INT (list->data);
3602 row_selected = TRUE;
3604 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3605 sel_row, column, event);
3615 clist_row = (g_list_nth (clist->row_list, row))->data;
3617 if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
3620 clist_row->state = GTK_STATE_SELECTED;
3621 if (!clist->selection)
3623 clist->selection = g_list_append (clist->selection,
3624 GINT_TO_POINTER (row));
3625 clist->selection_end = clist->selection;
3628 clist->selection_end =
3629 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
3631 if (CLIST_UNFROZEN (clist)
3632 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3633 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3637 real_unselect_row (GtkCList *clist,
3642 GtkCListRow *clist_row;
3644 g_return_if_fail (clist != NULL);
3645 g_return_if_fail (GTK_IS_CLIST (clist));
3647 if (row < 0 || row > (clist->rows - 1))
3650 clist_row = (g_list_nth (clist->row_list, row))->data;
3652 if (clist_row->state == GTK_STATE_SELECTED)
3654 clist_row->state = GTK_STATE_NORMAL;
3656 if (clist->selection_end &&
3657 clist->selection_end->data == GINT_TO_POINTER (row))
3658 clist->selection_end = clist->selection_end->prev;
3660 clist->selection = g_list_remove (clist->selection,
3661 GINT_TO_POINTER (row));
3663 if (CLIST_UNFROZEN (clist)
3664 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3665 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3670 real_select_all (GtkCList *clist)
3675 g_return_if_fail (clist != NULL);
3676 g_return_if_fail (GTK_IS_CLIST (clist));
3678 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
3681 switch (clist->selection_mode)
3683 case GTK_SELECTION_SINGLE:
3684 case GTK_SELECTION_BROWSE:
3687 case GTK_SELECTION_EXTENDED:
3688 g_list_free (clist->undo_selection);
3689 g_list_free (clist->undo_unselection);
3690 clist->undo_selection = NULL;
3691 clist->undo_unselection = NULL;
3694 ((GtkCListRow *) (clist->row_list->data))->state !=
3696 fake_toggle_row (clist, 0);
3698 clist->anchor_state = GTK_STATE_SELECTED;
3700 clist->drag_pos = 0;
3701 clist->undo_anchor = clist->focus_row;
3702 update_extended_selection (clist, clist->rows);
3703 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3706 case GTK_SELECTION_MULTIPLE:
3707 for (i = 0, list = clist->row_list; list; i++, list = list->next)
3709 if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
3710 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3718 real_unselect_all (GtkCList *clist)
3723 g_return_if_fail (clist != NULL);
3724 g_return_if_fail (GTK_IS_CLIST (clist));
3726 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
3729 switch (clist->selection_mode)
3731 case GTK_SELECTION_BROWSE:
3732 if (clist->focus_row >= 0)
3734 gtk_signal_emit (GTK_OBJECT (clist),
3735 clist_signals[SELECT_ROW],
3736 clist->focus_row, -1, NULL);
3740 case GTK_SELECTION_EXTENDED:
3741 g_list_free (clist->undo_selection);
3742 g_list_free (clist->undo_unselection);
3743 clist->undo_selection = NULL;
3744 clist->undo_unselection = NULL;
3747 clist->drag_pos = -1;
3748 clist->undo_anchor = clist->focus_row;
3754 list = clist->selection;
3757 i = GPOINTER_TO_INT (list->data);
3759 gtk_signal_emit (GTK_OBJECT (clist),
3760 clist_signals[UNSELECT_ROW], i, -1, NULL);
3765 fake_unselect_all (GtkCList *clist,
3772 if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
3774 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
3775 GTK_CLIST_ROW (work)->selectable)
3777 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3779 if (CLIST_UNFROZEN (clist) &&
3780 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3781 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
3782 GTK_CLIST_ROW (work));
3786 clist->undo_selection = clist->selection;
3787 clist->selection = NULL;
3788 clist->selection_end = NULL;
3790 for (list = clist->undo_selection; list; list = list->next)
3792 if ((i = GPOINTER_TO_INT (list->data)) == row ||
3793 !(work = g_list_nth (clist->row_list, i)))
3796 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3797 if (CLIST_UNFROZEN (clist) &&
3798 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
3799 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
3800 GTK_CLIST_ROW (work));
3805 real_undo_selection (GtkCList *clist)
3809 g_return_if_fail (clist != NULL);
3810 g_return_if_fail (GTK_IS_CLIST (clist));
3812 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3813 clist->selection_mode != GTK_SELECTION_EXTENDED)
3816 if (clist->anchor >= 0)
3817 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3819 if (!(clist->undo_selection || clist->undo_unselection))
3821 gtk_clist_unselect_all (clist);
3825 for (work = clist->undo_selection; work; work = work->next)
3826 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3827 GPOINTER_TO_INT (work->data), -1, NULL);
3829 for (work = clist->undo_unselection; work; work = work->next)
3830 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3831 GPOINTER_TO_INT (work->data), -1, NULL);
3833 if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
3835 gtk_clist_draw_focus (GTK_WIDGET (clist));
3836 clist->focus_row = clist->undo_anchor;
3837 gtk_clist_draw_focus (GTK_WIDGET (clist));
3840 clist->focus_row = clist->undo_anchor;
3842 clist->undo_anchor = -1;
3844 g_list_free (clist->undo_selection);
3845 g_list_free (clist->undo_unselection);
3846 clist->undo_selection = NULL;
3847 clist->undo_unselection = NULL;
3849 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
3850 clist->clist_window_height)
3851 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3852 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
3853 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3857 set_anchor (GtkCList *clist,
3862 g_return_if_fail (clist != NULL);
3863 g_return_if_fail (GTK_IS_CLIST (clist));
3865 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
3868 g_list_free (clist->undo_selection);
3869 g_list_free (clist->undo_unselection);
3870 clist->undo_selection = NULL;
3871 clist->undo_unselection = NULL;
3874 fake_toggle_row (clist, anchor);
3877 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
3878 clist->anchor_state = GTK_STATE_SELECTED;
3881 clist->anchor = anchor;
3882 clist->drag_pos = anchor;
3883 clist->undo_anchor = undo_anchor;
3887 resync_selection (GtkCList *clist,
3894 GtkCListRow *clist_row;
3896 if (clist->anchor < 0)
3899 gtk_clist_freeze (clist);
3901 i = MIN (clist->anchor, clist->drag_pos);
3902 e = MAX (clist->anchor, clist->drag_pos);
3904 if (clist->undo_selection)
3906 list = clist->selection;
3907 clist->selection = clist->undo_selection;
3908 clist->selection_end = g_list_last (clist->selection);
3909 clist->undo_selection = list;
3910 list = clist->selection;
3913 row = GPOINTER_TO_INT (list->data);
3915 if (row < i || row > e)
3917 clist_row = g_list_nth (clist->row_list, row)->data;
3918 if (clist_row->selectable)
3920 clist_row->state = GTK_STATE_SELECTED;
3921 gtk_signal_emit (GTK_OBJECT (clist),
3922 clist_signals[UNSELECT_ROW],
3924 clist->undo_selection = g_list_prepend
3925 (clist->undo_selection, GINT_TO_POINTER (row));
3931 if (clist->anchor < clist->drag_pos)
3933 for (list = g_list_nth (clist->row_list, i); i <= e;
3934 i++, list = list->next)
3935 if (GTK_CLIST_ROW (list)->selectable)
3937 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
3939 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
3941 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
3942 gtk_signal_emit (GTK_OBJECT (clist),
3943 clist_signals[UNSELECT_ROW],
3945 clist->undo_selection =
3946 g_list_prepend (clist->undo_selection,
3947 GINT_TO_POINTER (i));
3950 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
3952 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
3953 clist->undo_unselection =
3954 g_list_prepend (clist->undo_unselection,
3955 GINT_TO_POINTER (i));
3961 for (list = g_list_nth (clist->row_list, e); i <= e;
3962 e--, list = list->prev)
3963 if (GTK_CLIST_ROW (list)->selectable)
3965 if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
3967 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
3969 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
3970 gtk_signal_emit (GTK_OBJECT (clist),
3971 clist_signals[UNSELECT_ROW],
3973 clist->undo_selection =
3974 g_list_prepend (clist->undo_selection,
3975 GINT_TO_POINTER (e));
3978 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
3980 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
3981 clist->undo_unselection =
3982 g_list_prepend (clist->undo_unselection,
3983 GINT_TO_POINTER (e));
3988 for (list = g_list_reverse (clist->undo_unselection); list;
3990 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3991 GPOINTER_TO_INT (list->data), -1, event);
3994 clist->drag_pos = -1;
3996 gtk_clist_thaw (clist);
4000 update_extended_selection (GtkCList *clist,
4010 gint y1 = clist->clist_window_height;
4011 gint y2 = clist->clist_window_height;
4016 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
4021 if (row >= clist->rows)
4022 row = clist->rows - 1;
4024 /* extending downwards */
4025 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
4027 s2 = clist->drag_pos + 1;
4030 /* extending upwards */
4031 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
4034 e2 = clist->drag_pos - 1;
4036 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
4038 e1 = clist->drag_pos;
4039 /* row and drag_pos on different sides of anchor :
4040 take back the selection between anchor and drag_pos,
4041 select between anchor and row */
4042 if (row < clist->anchor)
4044 s1 = clist->anchor + 1;
4046 e2 = clist->anchor - 1;
4048 /* take back the selection between anchor and drag_pos */
4052 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
4054 s1 = clist->drag_pos;
4055 /* row and drag_pos on different sides of anchor :
4056 take back the selection between anchor and drag_pos,
4057 select between anchor and row */
4058 if (row > clist->anchor)
4060 e1 = clist->anchor - 1;
4061 s2 = clist->anchor + 1;
4064 /* take back the selection between anchor and drag_pos */
4069 clist->drag_pos = row;
4072 area.width = clist->clist_window_width;
4074 /* restore the elements between s1 and e1 */
4077 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
4078 i++, list = list->next)
4079 if (GTK_CLIST_ROW (list)->selectable)
4081 if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
4082 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4084 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4087 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4089 if (top + clist->row_height <= 0)
4092 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
4093 draw_rows (clist, &area);
4094 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4096 else if (top >= clist->clist_window_height)
4098 area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
4099 area.height = clist->clist_window_height - area.y;
4100 draw_rows (clist, &area);
4101 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4104 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4105 else if (top + clist->row_height > clist->clist_window_height)
4106 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4108 y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
4109 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
4112 /* extend the selection between s2 and e2 */
4115 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
4116 i++, list = list->next)
4117 if (GTK_CLIST_ROW (list)->selectable &&
4118 GTK_CLIST_ROW (list)->state != clist->anchor_state)
4119 GTK_CLIST_ROW (list)->state = clist->anchor_state;
4121 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4123 if (top + clist->row_height <= 0)
4126 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
4127 draw_rows (clist, &area);
4128 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4130 else if (top >= clist->clist_window_height)
4132 area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
4133 area.height = clist->clist_window_height - area.y;
4134 draw_rows (clist, &area);
4135 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4138 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4139 else if (top + clist->row_height > clist->clist_window_height)
4140 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4142 y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
4143 h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
4146 area.y = MAX (0, MIN (y1, y2));
4147 if (area.y > clist->clist_window_height)
4149 area.height = MIN (clist->clist_window_height, h1 + h2);
4150 if (s1 >= 0 && s2 >= 0)
4151 area.height += (clist->row_height + CELL_SPACING);
4152 draw_rows (clist, &area);
4156 start_selection (GtkCList *clist)
4158 g_return_if_fail (clist != NULL);
4159 g_return_if_fail (GTK_IS_CLIST (clist));
4161 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4164 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4169 end_selection (GtkCList *clist)
4171 g_return_if_fail (clist != NULL);
4172 g_return_if_fail (GTK_IS_CLIST (clist));
4174 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist)) ||
4175 clist->anchor == -1)
4178 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4182 extend_selection (GtkCList *clist,
4183 GtkScrollType scroll_type,
4185 gboolean auto_start_selection)
4187 g_return_if_fail (clist != NULL);
4188 g_return_if_fail (GTK_IS_CLIST (clist));
4190 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
4191 clist->selection_mode != GTK_SELECTION_EXTENDED)
4194 if (auto_start_selection)
4195 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4197 else if (clist->anchor == -1)
4200 move_focus_row (clist, scroll_type, position);
4202 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
4203 clist->clist_window_height)
4204 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4205 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
4206 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4208 update_extended_selection (clist, clist->focus_row);
4212 sync_selection (GtkCList *clist,
4219 if (mode == SYNC_INSERT)
4224 if (clist->focus_row >= row)
4226 if (d > 0 || clist->focus_row > row)
4227 clist->focus_row += d;
4228 if (clist->focus_row == -1 && clist->rows >= 1)
4229 clist->focus_row = 0;
4230 else if (clist->focus_row >= clist->rows)
4231 clist->focus_row = clist->rows - 1;
4234 if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
4235 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4237 g_list_free (clist->undo_selection);
4238 g_list_free (clist->undo_unselection);
4239 clist->undo_selection = NULL;
4240 clist->undo_unselection = NULL;
4243 clist->drag_pos = -1;
4244 clist->undo_anchor = clist->focus_row;
4246 list = clist->selection;
4250 if (GPOINTER_TO_INT (list->data) >= row)
4251 list->data = ((gchar*) list->data) + d;
4258 * gtk_clist_finalize
4261 gtk_clist_destroy (GtkObject *object)
4266 g_return_if_fail (object != NULL);
4267 g_return_if_fail (GTK_IS_CLIST (object));
4269 clist = GTK_CLIST (object);
4271 /* freeze the list */
4272 clist->freeze_count++;
4274 /* get rid of all the rows */
4275 gtk_clist_clear (clist);
4277 /* Since we don't have a _remove method, unparent the children
4278 * instead of destroying them so the focus will be unset properly.
4279 * (For other containers, the _remove method takes care of the
4280 * unparent) The destroy will happen when the refcount drops
4284 /* unref adjustments */
4285 if (clist->hadjustment)
4287 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
4288 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
4289 clist->hadjustment = NULL;
4291 if (clist->vadjustment)
4293 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
4294 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
4295 clist->vadjustment = NULL;
4298 remove_grab (clist);
4300 /* destroy the column buttons */
4301 for (i = 0; i < clist->columns; i++)
4302 if (clist->column[i].button)
4304 gtk_widget_unparent (clist->column[i].button);
4305 clist->column[i].button = NULL;
4308 if (GTK_OBJECT_CLASS (parent_class)->destroy)
4309 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
4313 gtk_clist_finalize (GtkObject *object)
4317 g_return_if_fail (object != NULL);
4318 g_return_if_fail (GTK_IS_CLIST (object));
4320 clist = GTK_CLIST (object);
4322 columns_delete (clist);
4324 g_mem_chunk_destroy (clist->cell_mem_chunk);
4325 g_mem_chunk_destroy (clist->row_mem_chunk);
4327 if (GTK_OBJECT_CLASS (parent_class)->finalize)
4328 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
4333 * gtk_clist_unrealize
4338 * gtk_clist_style_set
4339 * gtk_clist_key_press
4340 * gtk_clist_button_press
4341 * gtk_clist_button_release
4343 * gtk_clist_size_request
4344 * gtk_clist_size_allocate
4347 gtk_clist_realize (GtkWidget *widget)
4350 GdkWindowAttr attributes;
4352 GtkCListRow *clist_row;
4354 gint attributes_mask;
4359 g_return_if_fail (widget != NULL);
4360 g_return_if_fail (GTK_IS_CLIST (widget));
4362 clist = GTK_CLIST (widget);
4364 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4366 border_width = GTK_CONTAINER (widget)->border_width;
4368 attributes.window_type = GDK_WINDOW_CHILD;
4369 attributes.x = widget->allocation.x + border_width;
4370 attributes.y = widget->allocation.y + border_width;
4371 attributes.width = widget->allocation.width - border_width * 2;
4372 attributes.height = widget->allocation.height - border_width * 2;
4373 attributes.wclass = GDK_INPUT_OUTPUT;
4374 attributes.visual = gtk_widget_get_visual (widget);
4375 attributes.colormap = gtk_widget_get_colormap (widget);
4376 attributes.event_mask = gtk_widget_get_events (widget);
4377 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4378 GDK_BUTTON_PRESS_MASK |
4379 GDK_BUTTON_RELEASE_MASK |
4380 GDK_KEY_PRESS_MASK |
4381 GDK_KEY_RELEASE_MASK);
4382 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
4385 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
4386 &attributes, attributes_mask);
4387 gdk_window_set_user_data (widget->window, clist);
4389 widget->style = gtk_style_attach (widget->style, widget->window);
4391 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4393 /* column-title window */
4395 attributes.x = clist->column_title_area.x;
4396 attributes.y = clist->column_title_area.y;
4397 attributes.width = clist->column_title_area.width;
4398 attributes.height = clist->column_title_area.height;
4400 clist->title_window = gdk_window_new (widget->window, &attributes,
4402 gdk_window_set_user_data (clist->title_window, clist);
4404 gtk_style_set_background (widget->style, clist->title_window,
4406 gdk_window_show (clist->title_window);
4408 /* set things up so column buttons are drawn in title window */
4409 for (i = 0; i < clist->columns; i++)
4410 if (clist->column[i].button)
4411 gtk_widget_set_parent_window (clist->column[i].button,
4412 clist->title_window);
4415 attributes.x = (clist->internal_allocation.x +
4416 widget->style->klass->xthickness);
4417 attributes.y = (clist->internal_allocation.y +
4418 widget->style->klass->ythickness +
4419 clist->column_title_area.height);
4420 attributes.width = clist->clist_window_width;
4421 attributes.height = clist->clist_window_height;
4423 clist->clist_window = gdk_window_new (widget->window, &attributes,
4425 gdk_window_set_user_data (clist->clist_window, clist);
4427 gdk_window_set_background (clist->clist_window,
4428 &widget->style->base[GTK_STATE_NORMAL]);
4429 gdk_window_show (clist->clist_window);
4430 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
4431 &clist->clist_window_height);
4433 /* create resize windows */
4434 attributes.wclass = GDK_INPUT_ONLY;
4435 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
4436 GDK_BUTTON_RELEASE_MASK |
4437 GDK_POINTER_MOTION_MASK |
4438 GDK_POINTER_MOTION_HINT_MASK |
4439 GDK_KEY_PRESS_MASK);
4440 attributes_mask = GDK_WA_CURSOR;
4441 attributes.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
4442 clist->cursor_drag = attributes.cursor;
4444 attributes.x = LIST_WIDTH (clist) + 1;
4446 attributes.width = 0;
4447 attributes.height = 0;
4449 for (i = 0; i < clist->columns; i++)
4451 clist->column[i].window = gdk_window_new (clist->title_window,
4452 &attributes, attributes_mask);
4453 gdk_window_set_user_data (clist->column[i].window, clist);
4456 /* This is slightly less efficient than creating them with the
4457 * right size to begin with, but easier
4459 size_allocate_title_buttons (clist);
4462 clist->fg_gc = gdk_gc_new (widget->window);
4463 clist->bg_gc = gdk_gc_new (widget->window);
4465 /* We'll use this gc to do scrolling as well */
4466 gdk_gc_set_exposures (clist->fg_gc, TRUE);
4468 values.foreground = widget->style->white;
4469 values.function = GDK_XOR;
4470 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
4471 clist->xor_gc = gdk_gc_new_with_values (widget->window,
4477 /* attach optional row/cell styles, allocate foreground/background colors */
4478 list = clist->row_list;
4479 for (i = 0; i < clist->rows; i++)
4481 clist_row = list->data;
4484 if (clist_row->style)
4485 clist_row->style = gtk_style_attach (clist_row->style,
4486 clist->clist_window);
4488 if (clist_row->fg_set || clist_row->bg_set)
4490 GdkColormap *colormap;
4492 colormap = gtk_widget_get_colormap (widget);
4493 if (clist_row->fg_set)
4494 gdk_color_alloc (colormap, &clist_row->foreground);
4495 if (clist_row->bg_set)
4496 gdk_color_alloc (colormap, &clist_row->background);
4499 for (j = 0; j < clist->columns; j++)
4500 if (clist_row->cell[j].style)
4501 clist_row->cell[j].style =
4502 gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
4507 gtk_clist_unrealize (GtkWidget *widget)
4512 g_return_if_fail (widget != NULL);
4513 g_return_if_fail (GTK_IS_CLIST (widget));
4515 clist = GTK_CLIST (widget);
4517 /* freeze the list */
4518 clist->freeze_count++;
4520 /* detach optional row/cell styles */
4522 if (GTK_WIDGET_REALIZED (widget))
4524 GtkCListRow *clist_row;
4528 list = clist->row_list;
4529 for (i = 0; i < clist->rows; i++)
4531 clist_row = list->data;
4534 if (clist_row->style)
4535 gtk_style_detach (clist_row->style);
4536 for (j = 0; j < clist->columns; j++)
4537 if (clist_row->cell[j].style)
4538 gtk_style_detach (clist_row->cell[j].style);
4542 gdk_cursor_destroy (clist->cursor_drag);
4543 gdk_gc_destroy (clist->xor_gc);
4544 gdk_gc_destroy (clist->fg_gc);
4545 gdk_gc_destroy (clist->bg_gc);
4547 for (i = 0; i < clist->columns; i++)
4548 if (clist->column[i].window)
4550 gdk_window_set_user_data (clist->column[i].window, NULL);
4551 gdk_window_destroy (clist->column[i].window);
4552 clist->column[i].window = NULL;
4555 gdk_window_set_user_data (clist->clist_window, NULL);
4556 gdk_window_destroy (clist->clist_window);
4557 clist->clist_window = NULL;
4559 gdk_window_set_user_data (clist->title_window, NULL);
4560 gdk_window_destroy (clist->title_window);
4561 clist->title_window = NULL;
4563 clist->cursor_drag = NULL;
4564 clist->xor_gc = NULL;
4565 clist->fg_gc = NULL;
4566 clist->bg_gc = NULL;
4568 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
4569 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4573 gtk_clist_map (GtkWidget *widget)
4578 g_return_if_fail (widget != NULL);
4579 g_return_if_fail (GTK_IS_CLIST (widget));
4581 clist = GTK_CLIST (widget);
4583 if (!GTK_WIDGET_MAPPED (widget))
4585 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4587 /* map column buttons */
4588 for (i = 0; i < clist->columns; i++)
4589 if (clist->column[i].button &&
4590 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
4591 !GTK_WIDGET_MAPPED (clist->column[i].button))
4592 gtk_widget_map (clist->column[i].button);
4594 for (i = 0; i < clist->columns; i++)
4595 if (clist->column[i].window && clist->column[i].button)
4597 gdk_window_raise (clist->column[i].window);
4598 gdk_window_show (clist->column[i].window);
4601 gdk_window_show (clist->title_window);
4602 gdk_window_show (clist->clist_window);
4603 gdk_window_show (widget->window);
4605 /* unfreeze the list */
4606 clist->freeze_count = 0;
4611 gtk_clist_unmap (GtkWidget *widget)
4616 g_return_if_fail (widget != NULL);
4617 g_return_if_fail (GTK_IS_CLIST (widget));
4619 clist = GTK_CLIST (widget);
4621 if (GTK_WIDGET_MAPPED (widget))
4623 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4625 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4627 remove_grab (clist);
4629 if (clist->anchor != -1 &&
4630 clist->selection_mode == GTK_SELECTION_EXTENDED)
4631 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
4633 clist->click_cell.row = -1;
4634 clist->click_cell.column = -1;
4635 clist->drag_button = 0;
4637 if (GTK_CLIST_IN_DRAG(clist))
4641 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
4642 drag_data = gtk_object_get_data (GTK_OBJECT (clist),
4645 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
4650 for (i = 0; i < clist->columns; i++)
4651 if (clist->column[i].window)
4652 gdk_window_hide (clist->column[i].window);
4654 gdk_window_hide (clist->clist_window);
4655 gdk_window_hide (clist->title_window);
4656 gdk_window_hide (widget->window);
4658 /* unmap column buttons */
4659 for (i = 0; i < clist->columns; i++)
4660 if (clist->column[i].button &&
4661 GTK_WIDGET_MAPPED (clist->column[i].button))
4662 gtk_widget_unmap (clist->column[i].button);
4664 /* freeze the list */
4665 clist->freeze_count++;
4670 gtk_clist_draw (GtkWidget *widget,
4675 GdkRectangle child_area;
4678 g_return_if_fail (widget != NULL);
4679 g_return_if_fail (GTK_IS_CLIST (widget));
4680 g_return_if_fail (area != NULL);
4682 if (GTK_WIDGET_DRAWABLE (widget))
4684 clist = GTK_CLIST (widget);
4685 border_width = GTK_CONTAINER (widget)->border_width;
4687 gdk_window_clear_area (widget->window,
4688 area->x - border_width,
4689 area->y - border_width,
4690 area->width, area->height);
4692 /* draw list shadow/border */
4693 gtk_draw_shadow (widget->style, widget->window,
4694 GTK_STATE_NORMAL, clist->shadow_type,
4696 clist->clist_window_width +
4697 (2 * widget->style->klass->xthickness),
4698 clist->clist_window_height +
4699 (2 * widget->style->klass->ythickness) +
4700 clist->column_title_area.height);
4702 gdk_window_clear_area (clist->clist_window, 0, 0, -1, -1);
4703 draw_rows (clist, NULL);
4705 for (i = 0; i < clist->columns; i++)
4707 if (!clist->column[i].visible)
4709 if (clist->column[i].button &&
4710 gtk_widget_intersect(clist->column[i].button, area, &child_area))
4711 gtk_widget_draw (clist->column[i].button, &child_area);
4717 gtk_clist_expose (GtkWidget *widget,
4718 GdkEventExpose *event)
4722 g_return_val_if_fail (widget != NULL, FALSE);
4723 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4724 g_return_val_if_fail (event != NULL, FALSE);
4726 if (GTK_WIDGET_DRAWABLE (widget))
4728 clist = GTK_CLIST (widget);
4731 if (event->window == widget->window)
4732 gtk_draw_shadow (widget->style, widget->window,
4733 GTK_STATE_NORMAL, clist->shadow_type,
4735 clist->clist_window_width +
4736 (2 * widget->style->klass->xthickness),
4737 clist->clist_window_height +
4738 (2 * widget->style->klass->ythickness) +
4739 clist->column_title_area.height);
4741 /* exposure events on the list */
4742 if (event->window == clist->clist_window)
4743 draw_rows (clist, &event->area);
4750 gtk_clist_style_set (GtkWidget *widget,
4751 GtkStyle *previous_style)
4755 g_return_if_fail (widget != NULL);
4756 g_return_if_fail (GTK_IS_CLIST (widget));
4758 if (GTK_WIDGET_CLASS (parent_class)->style_set)
4759 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
4761 clist = GTK_CLIST (widget);
4763 if (GTK_WIDGET_REALIZED (widget))
4765 gtk_style_set_background (widget->style, widget->window, widget->state);
4766 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
4767 gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
4770 /* Fill in data after widget has correct style */
4772 /* text properties */
4773 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
4775 clist->row_height = (widget->style->font->ascent +
4776 widget->style->font->descent + 1);
4777 clist->row_center_offset = widget->style->font->ascent + 1.5;
4780 clist->row_center_offset = 1.5 + (clist->row_height +
4781 widget->style->font->ascent -
4782 widget->style->font->descent - 1) / 2;
4785 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
4790 for (i = 0; i < clist->columns; i++)
4791 if (clist->column[i].auto_resize)
4793 width = gtk_clist_optimal_column_width (clist, i);
4794 if (width != clist->column[i].width)
4795 gtk_clist_set_column_width (clist, i, width);
4801 gtk_clist_key_press (GtkWidget *widget,
4804 g_return_val_if_fail (widget != NULL, FALSE);
4805 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4806 g_return_val_if_fail (event != NULL, FALSE);
4808 if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
4809 GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
4812 switch (event->keyval)
4815 case GDK_ISO_Left_Tab:
4816 if (event->state & GDK_SHIFT_MASK)
4817 return gtk_container_focus (GTK_CONTAINER (widget),
4818 GTK_DIR_TAB_BACKWARD);
4820 return gtk_container_focus (GTK_CONTAINER (widget),
4821 GTK_DIR_TAB_FORWARD);
4829 gtk_clist_button_press (GtkWidget *widget,
4830 GdkEventButton *event)
4838 gint button_actions;
4840 g_return_val_if_fail (widget != NULL, FALSE);
4841 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4842 g_return_val_if_fail (event != NULL, FALSE);
4844 clist = GTK_CLIST (widget);
4846 button_actions = clist->button_actions[event->button - 1];
4848 if (button_actions == GTK_BUTTON_IGNORED)
4851 /* selections on the list */
4852 if (event->window == clist->clist_window)
4857 if (get_selection_info (clist, x, y, &row, &column))
4859 gint old_row = clist->focus_row;
4861 if (clist->focus_row == -1)
4864 if (event->type == GDK_BUTTON_PRESS)
4866 GdkEventMask mask = ((1 << (4 + event->button)) |
4867 GDK_POINTER_MOTION_HINT_MASK |
4868 GDK_BUTTON_RELEASE_MASK);
4870 if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
4871 NULL, NULL, event->time))
4873 gtk_grab_add (widget);
4875 clist->click_cell.row = row;
4876 clist->click_cell.column = column;
4877 clist->drag_button = event->button;
4881 clist->click_cell.row = -1;
4882 clist->click_cell.column = -1;
4884 clist->drag_button = 0;
4885 remove_grab (clist);
4888 if (button_actions & GTK_BUTTON_SELECTS)
4890 if (GTK_CLIST_ADD_MODE(clist))
4892 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
4893 if (GTK_WIDGET_HAS_FOCUS(widget))
4895 gtk_clist_draw_focus (widget);
4896 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4897 GDK_LINE_SOLID, 0, 0);
4898 clist->focus_row = row;
4899 gtk_clist_draw_focus (widget);
4903 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4904 GDK_LINE_SOLID, 0, 0);
4905 clist->focus_row = row;
4908 else if (row != clist->focus_row)
4910 if (GTK_WIDGET_HAS_FOCUS(widget))
4912 gtk_clist_draw_focus (widget);
4913 clist->focus_row = row;
4914 gtk_clist_draw_focus (widget);
4917 clist->focus_row = row;
4921 if (!GTK_WIDGET_HAS_FOCUS(widget))
4922 gtk_widget_grab_focus (widget);
4924 if (button_actions & GTK_BUTTON_SELECTS)
4926 switch (clist->selection_mode)
4928 case GTK_SELECTION_SINGLE:
4929 case GTK_SELECTION_MULTIPLE:
4930 if (event->type != GDK_BUTTON_PRESS)
4931 gtk_signal_emit (GTK_OBJECT (clist),
4932 clist_signals[SELECT_ROW],
4933 row, column, event);
4935 clist->anchor = row;
4937 case GTK_SELECTION_BROWSE:
4938 gtk_signal_emit (GTK_OBJECT (clist),
4939 clist_signals[SELECT_ROW],
4940 row, column, event);
4942 case GTK_SELECTION_EXTENDED:
4943 if (event->type != GDK_BUTTON_PRESS)
4945 if (clist->anchor != -1)
4947 update_extended_selection (clist, clist->focus_row);
4948 GTK_CLIST_CLASS_FW (clist)->resync_selection
4949 (clist, (GdkEvent *) event);
4951 gtk_signal_emit (GTK_OBJECT (clist),
4952 clist_signals[SELECT_ROW],
4953 row, column, event);
4957 if (event->state & GDK_CONTROL_MASK)
4959 if (event->state & GDK_SHIFT_MASK)
4961 if (clist->anchor < 0)
4963 g_list_free (clist->undo_selection);
4964 g_list_free (clist->undo_unselection);
4965 clist->undo_selection = NULL;
4966 clist->undo_unselection = NULL;
4967 clist->anchor = old_row;
4968 clist->drag_pos = old_row;
4969 clist->undo_anchor = old_row;
4971 update_extended_selection (clist, clist->focus_row);
4975 if (clist->anchor == -1)
4976 set_anchor (clist, TRUE, row, old_row);
4978 update_extended_selection (clist,
4984 if (event->state & GDK_SHIFT_MASK)
4986 set_anchor (clist, FALSE, old_row, old_row);
4987 update_extended_selection (clist, clist->focus_row);
4991 if (clist->anchor == -1)
4992 set_anchor (clist, FALSE, row, old_row);
4994 update_extended_selection (clist, clist->focus_row);
5004 /* press on resize windows */
5005 for (i = 0; i < clist->columns; i++)
5006 if (clist->column[i].resizeable && clist->column[i].window &&
5007 event->window == clist->column[i].window)
5011 if (gdk_pointer_grab (clist->column[i].window, FALSE,
5012 GDK_POINTER_MOTION_HINT_MASK |
5013 GDK_BUTTON1_MOTION_MASK |
5014 GDK_BUTTON_RELEASE_MASK,
5015 NULL, NULL, event->time))
5018 gtk_grab_add (widget);
5019 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
5021 /* block attached dnd signal handler */
5022 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5024 gtk_signal_handler_block_by_data (GTK_OBJECT (clist), drag_data);
5026 if (!GTK_WIDGET_HAS_FOCUS(widget))
5027 gtk_widget_grab_focus (widget);
5029 clist->drag_pos = i;
5030 clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
5031 clist->column[i].area.width + CELL_SPACING);
5033 if (GTK_CLIST_ADD_MODE(clist))
5034 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
5035 draw_xor_line (clist);
5041 gtk_clist_button_release (GtkWidget *widget,
5042 GdkEventButton *event)
5045 gint button_actions;
5047 g_return_val_if_fail (widget != NULL, FALSE);
5048 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5049 g_return_val_if_fail (event != NULL, FALSE);
5051 clist = GTK_CLIST (widget);
5053 button_actions = clist->button_actions[event->button - 1];
5054 if (button_actions == GTK_BUTTON_IGNORED)
5057 /* release on resize windows */
5058 if (GTK_CLIST_IN_DRAG(clist))
5065 i = clist->drag_pos;
5066 clist->drag_pos = -1;
5068 /* unblock attached dnd signal handler */
5069 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5071 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
5073 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5074 gtk_widget_get_pointer (widget, &x, NULL);
5075 gtk_grab_remove (widget);
5076 gdk_pointer_ungrab (event->time);
5078 if (clist->x_drag >= 0)
5079 draw_xor_line (clist);
5081 if (GTK_CLIST_ADD_MODE(clist))
5083 gdk_gc_set_line_attributes (clist->xor_gc, 1,
5084 GDK_LINE_ON_OFF_DASH, 0, 0);
5085 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5088 width = new_column_width (clist, i, &x);
5089 gtk_clist_set_column_width (clist, i, width);
5093 if (clist->drag_button == event->button)
5098 clist->drag_button = 0;
5099 clist->click_cell.row = -1;
5100 clist->click_cell.column = -1;
5102 remove_grab (clist);
5104 if (button_actions & GTK_BUTTON_SELECTS)
5106 switch (clist->selection_mode)
5108 case GTK_SELECTION_EXTENDED:
5109 if (!(event->state & GDK_SHIFT_MASK) ||
5110 event->x < 0 || event->x >= clist->clist_window_width ||
5111 event->y < 0 || event->y >= clist->clist_window_height)
5112 GTK_CLIST_CLASS_FW (clist)->resync_selection
5113 (clist, (GdkEvent *) event);
5115 case GTK_SELECTION_SINGLE:
5116 case GTK_SELECTION_MULTIPLE:
5117 if (get_selection_info (clist, event->x, event->y,
5120 if (row >= 0 && row < clist->rows && clist->anchor == row)
5121 toggle_row (clist, row, column, (GdkEvent *) event);
5134 gtk_clist_motion (GtkWidget *widget,
5135 GdkEventMotion *event)
5142 gint button_actions = 0;
5144 g_return_val_if_fail (widget != NULL, FALSE);
5145 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5147 clist = GTK_CLIST (widget);
5148 if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
5151 if (clist->drag_button > 0)
5152 button_actions = clist->button_actions[clist->drag_button - 1];
5154 if (GTK_CLIST_IN_DRAG(clist))
5156 if (event->is_hint || event->window != widget->window)
5157 gtk_widget_get_pointer (widget, &x, NULL);
5161 new_width = new_column_width (clist, clist->drag_pos, &x);
5162 if (x != clist->x_drag)
5164 /* x_drag < 0 indicates that the xor line is already invisible */
5165 if (clist->x_drag >= 0)
5166 draw_xor_line (clist);
5170 if (clist->x_drag >= 0)
5171 draw_xor_line (clist);
5174 if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
5175 clist->column[clist->drag_pos].min_width + 1))
5177 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
5178 gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
5181 if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
5182 new_width >= clist->column[clist->drag_pos].max_width)
5184 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
5185 clist->clist_window_width && x < 0)
5186 move_horizontal (clist,
5187 COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
5188 new_width - clist->clist_window_width +
5189 COLUMN_INSET + CELL_SPACING);
5194 if (event->is_hint || event->window != clist->clist_window)
5195 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
5197 if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
5199 /* delayed drag start */
5200 if (event->window == clist->clist_window &&
5201 clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
5202 (y < 0 || y >= clist->clist_window_height ||
5203 x < 0 || x >= clist->clist_window_width ||
5204 y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
5205 y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
5206 clist->row_height) ||
5207 x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
5208 x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) +
5209 clist->column[clist->click_cell.column].area.width)))
5211 GtkTargetList *target_list;
5213 target_list = gtk_target_list_new (&clist_target_table, 1);
5214 gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
5215 clist->drag_button, (GdkEvent *)event);
5221 /* horizontal autoscrolling */
5222 if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
5223 (x < 0 || x >= clist->clist_window_width))
5228 clist->htimer = gtk_timeout_add
5229 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
5231 if (!((x < 0 && clist->hadjustment->value == 0) ||
5232 (x >= clist->clist_window_width &&
5233 clist->hadjustment->value ==
5234 LIST_WIDTH (clist) - clist->clist_window_width)))
5237 move_horizontal (clist, -1 + (x/2));
5239 move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
5243 if (GTK_CLIST_IN_DRAG(clist))
5246 /* vertical autoscrolling */
5247 row = ROW_FROM_YPIXEL (clist, y);
5249 /* don't scroll on last pixel row if it's a cell spacing */
5250 if (y == clist->clist_window_height - 1 &&
5251 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
5254 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
5255 (y < 0 || y >= clist->clist_window_height))
5260 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
5261 (GtkFunction) vertical_timeout, clist);
5263 if (clist->drag_button &&
5264 ((y < 0 && clist->focus_row == 0) ||
5265 (y >= clist->clist_window_height &&
5266 clist->focus_row == clist->rows - 1)))
5270 row = CLAMP (row, 0, clist->rows - 1);
5272 if (button_actions & GTK_BUTTON_SELECTS &
5273 !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
5275 if (row == clist->focus_row)
5278 gtk_clist_draw_focus (widget);
5279 clist->focus_row = row;
5280 gtk_clist_draw_focus (widget);
5282 switch (clist->selection_mode)
5284 case GTK_SELECTION_BROWSE:
5285 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5286 clist->focus_row, -1, event);
5288 case GTK_SELECTION_EXTENDED:
5289 update_extended_selection (clist, clist->focus_row);
5296 if (ROW_TOP_YPIXEL(clist, row) < 0)
5297 move_vertical (clist, row, 0);
5298 else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
5299 clist->clist_window_height)
5300 move_vertical (clist, row, 1);
5306 gtk_clist_size_request (GtkWidget *widget,
5307 GtkRequisition *requisition)
5312 g_return_if_fail (widget != NULL);
5313 g_return_if_fail (GTK_IS_CLIST (widget));
5314 g_return_if_fail (requisition != NULL);
5316 clist = GTK_CLIST (widget);
5318 requisition->width = 0;
5319 requisition->height = 0;
5321 /* compute the size of the column title (title) area */
5322 clist->column_title_area.height = 0;
5323 if (GTK_CLIST_SHOW_TITLES(clist))
5324 for (i = 0; i < clist->columns; i++)
5325 if (clist->column[i].button)
5327 GtkRequisition child_requisition;
5329 gtk_widget_size_request (clist->column[i].button,
5330 &child_requisition);
5331 clist->column_title_area.height =
5332 MAX (clist->column_title_area.height,
5333 child_requisition.height);
5336 requisition->width += (widget->style->klass->xthickness +
5337 GTK_CONTAINER (widget)->border_width) * 2;
5338 requisition->height += (clist->column_title_area.height +
5339 (widget->style->klass->ythickness +
5340 GTK_CONTAINER (widget)->border_width) * 2);
5342 /* if (!clist->hadjustment) */
5343 requisition->width += list_requisition_width (clist);
5344 /* if (!clist->vadjustment) */
5345 requisition->height += LIST_HEIGHT (clist);
5349 gtk_clist_size_allocate (GtkWidget *widget,
5350 GtkAllocation *allocation)
5353 GtkAllocation clist_allocation;
5356 g_return_if_fail (widget != NULL);
5357 g_return_if_fail (GTK_IS_CLIST (widget));
5358 g_return_if_fail (allocation != NULL);
5360 clist = GTK_CLIST (widget);
5361 widget->allocation = *allocation;
5362 border_width = GTK_CONTAINER (widget)->border_width;
5364 if (GTK_WIDGET_REALIZED (widget))
5366 gdk_window_move_resize (widget->window,
5367 allocation->x + border_width,
5368 allocation->y + border_width,
5369 allocation->width - border_width * 2,
5370 allocation->height - border_width * 2);
5373 /* use internal allocation structure for all the math
5374 * because it's easier than always subtracting the container
5376 clist->internal_allocation.x = 0;
5377 clist->internal_allocation.y = 0;
5378 clist->internal_allocation.width = MAX (1, (gint)allocation->width -
5380 clist->internal_allocation.height = MAX (1, (gint)allocation->height -
5383 /* allocate clist window assuming no scrollbars */
5384 clist_allocation.x = (clist->internal_allocation.x +
5385 widget->style->klass->xthickness);
5386 clist_allocation.y = (clist->internal_allocation.y +
5387 widget->style->klass->ythickness +
5388 clist->column_title_area.height);
5389 clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width -
5390 (2 * (gint)widget->style->klass->xthickness));
5391 clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
5392 (2 * (gint)widget->style->klass->ythickness) -
5393 (gint)clist->column_title_area.height);
5395 clist->clist_window_width = clist_allocation.width;
5396 clist->clist_window_height = clist_allocation.height;
5398 if (GTK_WIDGET_REALIZED (widget))
5400 gdk_window_move_resize (clist->clist_window,
5403 clist_allocation.width,
5404 clist_allocation.height);
5407 /* position the window which holds the column title buttons */
5408 clist->column_title_area.x = widget->style->klass->xthickness;
5409 clist->column_title_area.y = widget->style->klass->ythickness;
5410 clist->column_title_area.width = clist_allocation.width;
5412 if (GTK_WIDGET_REALIZED (widget))
5414 gdk_window_move_resize (clist->title_window,
5415 clist->column_title_area.x,
5416 clist->column_title_area.y,
5417 clist->column_title_area.width,
5418 clist->column_title_area.height);
5421 /* column button allocation */
5422 size_allocate_columns (clist, FALSE);
5423 size_allocate_title_buttons (clist);
5425 adjust_adjustments (clist, TRUE);
5432 gtk_clist_forall (GtkContainer *container,
5433 gboolean include_internals,
5434 GtkCallback callback,
5435 gpointer callback_data)
5440 g_return_if_fail (container != NULL);
5441 g_return_if_fail (GTK_IS_CLIST (container));
5442 g_return_if_fail (callback != NULL);
5444 if (!include_internals)
5447 clist = GTK_CLIST (container);
5449 /* callback for the column buttons */
5450 for (i = 0; i < clist->columns; i++)
5451 if (clist->column[i].button)
5452 (*callback) (clist->column[i].button, callback_data);
5455 /* PRIVATE DRAWING FUNCTIONS
5464 get_cell_style (GtkCList *clist,
5465 GtkCListRow *clist_row,
5474 if ((state == GTK_STATE_NORMAL) &&
5475 (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
5476 fg_state = GTK_STATE_INSENSITIVE;
5480 if (clist_row->cell[column].style)
5483 *style = clist_row->cell[column].style;
5485 *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
5487 if (state == GTK_STATE_SELECTED)
5488 *bg_gc = clist_row->cell[column].style->bg_gc[state];
5490 *bg_gc = clist_row->cell[column].style->base_gc[state];
5493 else if (clist_row->style)
5496 *style = clist_row->style;
5498 *fg_gc = clist_row->style->fg_gc[fg_state];
5500 if (state == GTK_STATE_SELECTED)
5501 *bg_gc = clist_row->style->bg_gc[state];
5503 *bg_gc = clist_row->style->base_gc[state];
5509 *style = GTK_WIDGET (clist)->style;
5511 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
5513 if (state == GTK_STATE_SELECTED)
5514 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
5516 *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
5519 if (state != GTK_STATE_SELECTED)
5521 if (fg_gc && clist_row->fg_set)
5522 *fg_gc = clist->fg_gc;
5523 if (bg_gc && clist_row->bg_set)
5524 *bg_gc = clist->bg_gc;
5530 draw_cell_pixmap (GdkWindow *window,
5531 GdkRectangle *clip_rectangle,
5545 gdk_gc_set_clip_mask (fg_gc, mask);
5546 gdk_gc_set_clip_origin (fg_gc, x, y);
5549 if (x < clip_rectangle->x)
5551 xsrc = clip_rectangle->x - x;
5553 x = clip_rectangle->x;
5555 if (x + width > clip_rectangle->x + clip_rectangle->width)
5556 width = clip_rectangle->x + clip_rectangle->width - x;
5558 if (y < clip_rectangle->y)
5560 ysrc = clip_rectangle->y - y;
5562 y = clip_rectangle->y;
5564 if (y + height > clip_rectangle->y + clip_rectangle->height)
5565 height = clip_rectangle->y + clip_rectangle->height - y;
5567 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
5568 gdk_gc_set_clip_origin (fg_gc, 0, 0);
5570 gdk_gc_set_clip_mask (fg_gc, NULL);
5572 return x + MAX (width, 0);
5576 draw_row (GtkCList *clist,
5579 GtkCListRow *clist_row)
5583 GdkRectangle row_rectangle;
5584 GdkRectangle cell_rectangle;
5585 GdkRectangle clip_rectangle;
5586 GdkRectangle intersect_rectangle;
5591 g_return_if_fail (clist != NULL);
5593 /* bail now if we arn't drawable yet */
5594 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
5597 widget = GTK_WIDGET (clist);
5599 /* if the function is passed the pointer to the row instead of null,
5600 * it avoids this expensive lookup */
5602 clist_row = (g_list_nth (clist->row_list, row))->data;
5604 /* rectangle of the entire row */
5605 row_rectangle.x = 0;
5606 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
5607 row_rectangle.width = clist->clist_window_width;
5608 row_rectangle.height = clist->row_height;
5610 /* rectangle of the cell spacing above the row */
5611 cell_rectangle.x = 0;
5612 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
5613 cell_rectangle.width = row_rectangle.width;
5614 cell_rectangle.height = CELL_SPACING;
5616 /* rectangle used to clip drawing operations, it's y and height
5617 * positions only need to be set once, so we set them once here.
5618 * the x and width are set withing the drawing loop below once per
5620 clip_rectangle.y = row_rectangle.y;
5621 clip_rectangle.height = row_rectangle.height;
5623 if (clist_row->state == GTK_STATE_NORMAL)
5625 if (clist_row->fg_set)
5626 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
5627 if (clist_row->bg_set)
5628 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
5631 state = clist_row->state;
5633 /* draw the cell borders and background */
5636 rect = &intersect_rectangle;
5637 if (gdk_rectangle_intersect (area, &cell_rectangle,
5638 &intersect_rectangle))
5639 gdk_draw_rectangle (clist->clist_window,
5640 widget->style->base_gc[GTK_STATE_ACTIVE],
5642 intersect_rectangle.x,
5643 intersect_rectangle.y,
5644 intersect_rectangle.width,
5645 intersect_rectangle.height);
5647 /* the last row has to clear it's bottom cell spacing too */
5648 if (clist_row == clist->row_list_end->data)
5650 cell_rectangle.y += clist->row_height + CELL_SPACING;
5652 if (gdk_rectangle_intersect (area, &cell_rectangle,
5653 &intersect_rectangle))
5654 gdk_draw_rectangle (clist->clist_window,
5655 widget->style->base_gc[GTK_STATE_ACTIVE],
5657 intersect_rectangle.x,
5658 intersect_rectangle.y,
5659 intersect_rectangle.width,
5660 intersect_rectangle.height);
5663 if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
5669 rect = &clip_rectangle;
5670 gdk_draw_rectangle (clist->clist_window,
5671 widget->style->base_gc[GTK_STATE_ACTIVE],
5675 cell_rectangle.width,
5676 cell_rectangle.height);
5678 /* the last row has to clear it's bottom cell spacing too */
5679 if (clist_row == clist->row_list_end->data)
5681 cell_rectangle.y += clist->row_height + CELL_SPACING;
5683 gdk_draw_rectangle (clist->clist_window,
5684 widget->style->base_gc[GTK_STATE_ACTIVE],
5688 cell_rectangle.width,
5689 cell_rectangle.height);
5693 for (last_column = clist->columns - 1;
5694 last_column >= 0 && !clist->column[last_column].visible; last_column--)
5697 /* iterate and draw all the columns (row cells) and draw their contents */
5698 for (i = 0; i < clist->columns; i++)
5708 gint row_center_offset;
5710 if (!clist->column[i].visible)
5713 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
5715 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
5716 clip_rectangle.width = clist->column[i].area.width;
5718 /* calculate clipping region clipping region */
5719 clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
5720 clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
5721 (i == last_column) * CELL_SPACING);
5723 if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
5724 &intersect_rectangle))
5727 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
5728 rect->x, rect->y, rect->width, rect->height);
5730 clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
5731 clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
5732 (i == last_column) * CELL_SPACING);
5734 /* calculate real width for column justification */
5737 switch (clist_row->cell[i].type)
5740 width = gdk_string_width (style->font,
5741 GTK_CELL_TEXT (clist_row->cell[i])->text);
5743 case GTK_CELL_PIXMAP:
5744 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5745 &pixmap_width, &height);
5746 width = pixmap_width;
5748 case GTK_CELL_PIXTEXT:
5749 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5750 &pixmap_width, &height);
5751 width = (pixmap_width +
5752 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
5753 gdk_string_width (style->font,
5755 (clist_row->cell[i])->text));
5762 switch (clist->column[i].justification)
5764 case GTK_JUSTIFY_LEFT:
5765 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
5767 case GTK_JUSTIFY_RIGHT:
5768 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5769 clip_rectangle.width - width);
5771 case GTK_JUSTIFY_CENTER:
5772 case GTK_JUSTIFY_FILL:
5773 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5774 (clip_rectangle.width / 2) - (width / 2));
5778 /* Draw Text and/or Pixmap */
5779 switch (clist_row->cell[i].type)
5781 case GTK_CELL_PIXMAP:
5782 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5783 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5784 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
5786 clip_rectangle.y + clist_row->cell[i].vertical +
5787 (clip_rectangle.height - height) / 2,
5788 pixmap_width, height);
5790 case GTK_CELL_PIXTEXT:
5792 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5793 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5794 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
5796 clip_rectangle.y + clist_row->cell[i].vertical+
5797 (clip_rectangle.height - height) / 2,
5798 pixmap_width, height);
5799 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
5801 if (style != GTK_WIDGET (clist)->style)
5802 row_center_offset = (((clist->row_height - style->font->ascent -
5803 style->font->descent - 1) / 2) + 1.5 +
5804 style->font->ascent);
5806 row_center_offset = clist->row_center_offset;
5808 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
5809 gdk_draw_string (clist->clist_window, style->font, fg_gc,
5811 row_rectangle.y + row_center_offset +
5812 clist_row->cell[i].vertical,
5813 (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
5814 GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
5815 GTK_CELL_TEXT (clist_row->cell[i])->text);
5816 gdk_gc_set_clip_rectangle (fg_gc, NULL);
5823 /* draw focus rectangle */
5824 if (clist->focus_row == row &&
5825 GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
5828 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5829 row_rectangle.x, row_rectangle.y,
5830 row_rectangle.width - 1, row_rectangle.height - 1);
5831 else if (gdk_rectangle_intersect (area, &row_rectangle,
5832 &intersect_rectangle))
5834 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
5835 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5836 row_rectangle.x, row_rectangle.y,
5837 row_rectangle.width - 1,
5838 row_rectangle.height - 1);
5839 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
5845 draw_rows (GtkCList *clist,
5849 GtkCListRow *clist_row;
5854 g_return_if_fail (clist != NULL);
5855 g_return_if_fail (GTK_IS_CLIST (clist));
5857 if (clist->row_height == 0 ||
5858 !GTK_WIDGET_DRAWABLE (clist))
5863 first_row = ROW_FROM_YPIXEL (clist, area->y);
5864 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
5868 first_row = ROW_FROM_YPIXEL (clist, 0);
5869 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
5872 /* this is a small special case which exposes the bottom cell line
5873 * on the last row -- it might go away if I change the wall the cell
5874 * spacings are drawn
5876 if (clist->rows == first_row)
5879 list = g_list_nth (clist->row_list, first_row);
5883 clist_row = list->data;
5889 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
5894 gdk_window_clear_area (clist->clist_window,
5895 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
5899 draw_xor_line (GtkCList *clist)
5903 g_return_if_fail (clist != NULL);
5905 widget = GTK_WIDGET (clist);
5907 gdk_draw_line (widget->window, clist->xor_gc,
5909 widget->style->klass->ythickness,
5911 clist->column_title_area.height +
5912 clist->clist_window_height + 1);
5916 clist_refresh (GtkCList *clist)
5918 g_return_if_fail (clist != NULL);
5919 g_return_if_fail (GTK_IS_CLIST (clist));
5921 if (CLIST_UNFROZEN (clist))
5923 adjust_adjustments (clist, FALSE);
5924 draw_rows (clist, NULL);
5928 /* get cell from coordinates
5929 * get_selection_info
5930 * gtk_clist_get_selection_info
5933 get_selection_info (GtkCList *clist,
5941 g_return_val_if_fail (clist != NULL, 0);
5942 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
5944 /* bounds checking, return false if the user clicked
5945 * on a blank area */
5946 trow = ROW_FROM_YPIXEL (clist, y);
5947 if (trow >= clist->rows)
5953 tcol = COLUMN_FROM_XPIXEL (clist, x);
5954 if (tcol >= clist->columns)
5964 gtk_clist_get_selection_info (GtkCList *clist,
5970 g_return_val_if_fail (clist != NULL, 0);
5971 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
5972 return get_selection_info (clist, x, y, row, column);
5975 /* PRIVATE ADJUSTMENT FUNCTIONS
5976 * adjust_adjustments
5977 * vadjustment_changed
5978 * hadjustment_changed
5979 * vadjustment_value_changed
5980 * hadjustment_value_changed
5984 adjust_adjustments (GtkCList *clist,
5985 gboolean block_resize)
5987 if (clist->vadjustment)
5989 clist->vadjustment->page_size = clist->clist_window_height;
5990 clist->vadjustment->page_increment = clist->clist_window_height / 2;
5991 clist->vadjustment->step_increment = clist->row_height;
5992 clist->vadjustment->lower = 0;
5993 clist->vadjustment->upper = LIST_HEIGHT (clist);
5995 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
5997 clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
5998 clist->clist_window_height));
5999 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
6002 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
6005 if (clist->hadjustment)
6007 clist->hadjustment->page_size = clist->clist_window_width;
6008 clist->hadjustment->page_increment = clist->clist_window_width / 2;
6009 clist->hadjustment->step_increment = 10;
6010 clist->hadjustment->lower = 0;
6011 clist->hadjustment->upper = LIST_WIDTH (clist);
6013 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
6015 clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
6016 clist->clist_window_width));
6017 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
6020 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
6023 if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
6026 GtkRequisition requisition;
6028 widget = GTK_WIDGET (clist);
6029 gtk_widget_size_request (widget, &requisition);
6031 if ((!clist->hadjustment &&
6032 requisition.width != widget->allocation.width) ||
6033 (!clist->vadjustment &&
6034 requisition.height != widget->allocation.height))
6035 gtk_widget_queue_resize (widget);
6040 vadjustment_changed (GtkAdjustment *adjustment,
6045 g_return_if_fail (adjustment != NULL);
6046 g_return_if_fail (data != NULL);
6048 clist = GTK_CLIST (data);
6052 hadjustment_changed (GtkAdjustment *adjustment,
6057 g_return_if_fail (adjustment != NULL);
6058 g_return_if_fail (data != NULL);
6060 clist = GTK_CLIST (data);
6064 vadjustment_value_changed (GtkAdjustment *adjustment,
6071 g_return_if_fail (adjustment != NULL);
6072 g_return_if_fail (data != NULL);
6073 g_return_if_fail (GTK_IS_CLIST (data));
6075 clist = GTK_CLIST (data);
6077 if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->vadjustment)
6080 value = adjustment->value;
6082 if (value > -clist->voffset)
6085 diff = value + clist->voffset;
6087 /* we have to re-draw the whole screen here... */
6088 if (diff >= clist->clist_window_height)
6090 clist->voffset = -value;
6091 draw_rows (clist, NULL);
6095 if ((diff != 0) && (diff != clist->clist_window_height))
6096 gdk_window_copy_area (clist->clist_window, clist->fg_gc,
6097 0, 0, clist->clist_window, 0, diff,
6098 clist->clist_window_width,
6099 clist->clist_window_height - diff);
6102 area.y = clist->clist_window_height - diff;
6103 area.width = clist->clist_window_width;
6109 diff = -clist->voffset - value;
6111 /* we have to re-draw the whole screen here... */
6112 if (diff >= clist->clist_window_height)
6114 clist->voffset = -value;
6115 draw_rows (clist, NULL);
6119 if ((diff != 0) && (diff != clist->clist_window_height))
6120 gdk_window_copy_area (clist->clist_window, clist->fg_gc,
6121 0, diff, clist->clist_window, 0, 0,
6122 clist->clist_window_width,
6123 clist->clist_window_height - diff);
6127 area.width = clist->clist_window_width;
6131 clist->voffset = -value;
6132 if ((diff != 0) && (diff != clist->clist_window_height))
6133 check_exposures (clist);
6135 draw_rows (clist, &area);
6139 hadjustment_value_changed (GtkAdjustment *adjustment,
6149 g_return_if_fail (adjustment != NULL);
6150 g_return_if_fail (data != NULL);
6151 g_return_if_fail (GTK_IS_CLIST (data));
6153 clist = GTK_CLIST (data);
6155 if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->hadjustment)
6158 value = adjustment->value;
6160 /* move the column buttons and resize windows */
6161 for (i = 0; i < clist->columns; i++)
6163 if (clist->column[i].button)
6165 clist->column[i].button->allocation.x -= value + clist->hoffset;
6167 if (clist->column[i].button->window)
6169 gdk_window_move (clist->column[i].button->window,
6170 clist->column[i].button->allocation.x,
6171 clist->column[i].button->allocation.y);
6173 if (clist->column[i].window)
6174 gdk_window_move (clist->column[i].window,
6175 clist->column[i].button->allocation.x +
6176 clist->column[i].button->allocation.width -
6177 (DRAG_WIDTH / 2), 0);
6182 if (value > -clist->hoffset)
6185 diff = value + clist->hoffset;
6187 clist->hoffset = -value;
6189 /* we have to re-draw the whole screen here... */
6190 if (diff >= clist->clist_window_width)
6192 draw_rows (clist, NULL);
6196 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6197 !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
6199 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6201 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
6202 clist->clist_window_width - 1,
6203 clist->row_height - 1);
6205 gdk_window_copy_area (clist->clist_window,
6208 clist->clist_window,
6211 clist->clist_window_width - diff,
6212 clist->clist_window_height);
6214 area.x = clist->clist_window_width - diff;
6219 if (!(diff = -clist->hoffset - value))
6222 clist->hoffset = -value;
6224 /* we have to re-draw the whole screen here... */
6225 if (diff >= clist->clist_window_width)
6227 draw_rows (clist, NULL);
6231 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6232 !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
6234 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6236 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
6237 clist->clist_window_width - 1,
6238 clist->row_height - 1);
6241 gdk_window_copy_area (clist->clist_window,
6244 clist->clist_window,
6247 clist->clist_window_width - diff,
6248 clist->clist_window_height);
6255 area.height = clist->clist_window_height;
6257 check_exposures (clist);
6259 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6260 !GTK_CLIST_CHILD_HAS_FOCUS(clist))
6262 if (GTK_CLIST_ADD_MODE(clist))
6266 focus_row = clist->focus_row;
6267 clist->focus_row = -1;
6268 draw_rows (clist, &area);
6269 clist->focus_row = focus_row;
6271 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
6272 FALSE, 0, y, clist->clist_window_width - 1,
6273 clist->row_height - 1);
6283 x0 = clist->clist_window_width - 1;
6292 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6293 gdk_draw_line (clist->clist_window, clist->xor_gc,
6294 x0, y + 1, x0, y + clist->row_height - 2);
6295 gdk_draw_line (clist->clist_window, clist->xor_gc,
6296 x1, y + 1, x1, y + clist->row_height - 2);
6300 draw_rows (clist, &area);
6304 check_exposures (GtkCList *clist)
6308 if (!GTK_WIDGET_REALIZED (clist))
6311 /* Make sure graphics expose events are processed before scrolling
6313 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
6315 gtk_widget_event (GTK_WIDGET (clist), event);
6316 if (event->expose.count == 0)
6318 gdk_event_free (event);
6321 gdk_event_free (event);
6326 * Memory Allocation/Distruction Routines for GtkCList stuctures
6335 static GtkCListColumn *
6336 columns_new (GtkCList *clist)
6338 GtkCListColumn *column;
6341 column = g_new (GtkCListColumn, clist->columns);
6343 for (i = 0; i < clist->columns; i++)
6345 column[i].area.x = 0;
6346 column[i].area.y = 0;
6347 column[i].area.width = 0;
6348 column[i].area.height = 0;
6349 column[i].title = NULL;
6350 column[i].button = NULL;
6351 column[i].window = NULL;
6352 column[i].width = 0;
6353 column[i].min_width = -1;
6354 column[i].max_width = -1;
6355 column[i].visible = TRUE;
6356 column[i].width_set = FALSE;
6357 column[i].resizeable = TRUE;
6358 column[i].auto_resize = FALSE;
6359 column[i].justification = GTK_JUSTIFY_LEFT;
6366 column_title_new (GtkCList *clist,
6370 if (clist->column[column].title)
6371 g_free (clist->column[column].title);
6373 clist->column[column].title = g_strdup (title);
6377 columns_delete (GtkCList *clist)
6381 for (i = 0; i < clist->columns; i++)
6382 if (clist->column[i].title)
6383 g_free (clist->column[i].title);
6385 g_free (clist->column);
6388 static GtkCListRow *
6389 row_new (GtkCList *clist)
6392 GtkCListRow *clist_row;
6394 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
6395 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
6397 for (i = 0; i < clist->columns; i++)
6399 clist_row->cell[i].type = GTK_CELL_EMPTY;
6400 clist_row->cell[i].vertical = 0;
6401 clist_row->cell[i].horizontal = 0;
6402 clist_row->cell[i].style = NULL;
6405 clist_row->fg_set = FALSE;
6406 clist_row->bg_set = FALSE;
6407 clist_row->style = NULL;
6408 clist_row->selectable = TRUE;
6409 clist_row->state = GTK_STATE_NORMAL;
6410 clist_row->data = NULL;
6411 clist_row->destroy = NULL;
6417 row_delete (GtkCList *clist,
6418 GtkCListRow *clist_row)
6422 for (i = 0; i < clist->columns; i++)
6424 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
6425 (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
6426 if (clist_row->cell[i].style)
6428 if (GTK_WIDGET_REALIZED (clist))
6429 gtk_style_detach (clist_row->cell[i].style);
6430 gtk_style_unref (clist_row->cell[i].style);
6434 if (clist_row->style)
6436 if (GTK_WIDGET_REALIZED (clist))
6437 gtk_style_detach (clist_row->style);
6438 gtk_style_unref (clist_row->style);
6441 if (clist_row->destroy)
6442 clist_row->destroy (clist_row->data);
6444 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
6445 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
6450 * gtk_clist_draw_focus
6451 * gtk_clist_focus_in
6452 * gtk_clist_focus_out
6453 * gtk_clist_set_focus_child
6457 gtk_clist_focus (GtkContainer *container,
6458 GtkDirectionType direction)
6461 GtkWidget *focus_child;
6464 g_return_val_if_fail (container != NULL, FALSE);
6465 g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
6467 if (!GTK_WIDGET_IS_SENSITIVE (container))
6470 clist = GTK_CLIST (container);
6471 focus_child = container->focus_child;
6472 old_row = clist->focus_row;
6478 if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
6480 if (title_focus (clist, direction))
6482 gtk_container_set_focus_child (container, NULL);
6485 gtk_widget_grab_focus (GTK_WIDGET (container));
6488 case GTK_DIR_TAB_FORWARD:
6489 if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
6491 gboolean tf = FALSE;
6493 if (((focus_child && direction == GTK_DIR_DOWN) ||
6494 !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
6497 if (clist->focus_row < 0)
6499 clist->focus_row = 0;
6501 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
6502 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
6504 gtk_signal_emit (GTK_OBJECT (clist),
6505 clist_signals[SELECT_ROW],
6506 clist->focus_row, -1, NULL);
6508 gtk_widget_grab_focus (GTK_WIDGET (container));
6516 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
6519 case GTK_DIR_TAB_BACKWARD:
6521 GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows)
6523 if (clist->focus_row < 0)
6525 clist->focus_row = 0;
6526 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
6527 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
6529 gtk_signal_emit (GTK_OBJECT (clist),
6530 clist_signals[SELECT_ROW],
6531 clist->focus_row, -1, NULL);
6533 gtk_widget_grab_focus (GTK_WIDGET (container));
6537 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
6539 if (title_focus (clist, direction))
6547 gtk_container_set_focus_child (container, NULL);
6552 gtk_clist_draw_focus (GtkWidget *widget)
6556 g_return_if_fail (widget != NULL);
6557 g_return_if_fail (GTK_IS_CLIST (widget));
6559 if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
6562 clist = GTK_CLIST (widget);
6563 if (clist->focus_row >= 0)
6564 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
6565 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
6566 clist->clist_window_width - 1,
6567 clist->row_height - 1);
6571 gtk_clist_focus_in (GtkWidget *widget,
6572 GdkEventFocus *event)
6576 g_return_val_if_fail (widget != NULL, FALSE);
6577 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
6578 g_return_val_if_fail (event != NULL, FALSE);
6580 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
6581 GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
6583 clist = GTK_CLIST (widget);
6585 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
6586 clist->selection == NULL && clist->focus_row > -1)
6590 list = g_list_nth (clist->row_list, clist->focus_row);
6591 if (list && GTK_CLIST_ROW (list)->selectable)
6592 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6593 clist->focus_row, -1, event);
6595 gtk_widget_draw_focus (widget);
6598 gtk_widget_draw_focus (widget);
6604 gtk_clist_focus_out (GtkWidget *widget,
6605 GdkEventFocus *event)
6609 g_return_val_if_fail (widget != NULL, FALSE);
6610 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
6611 g_return_val_if_fail (event != NULL, FALSE);
6613 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
6614 GTK_CLIST_SET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
6616 gtk_widget_draw_focus (widget);
6618 clist = GTK_CLIST (widget);
6620 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
6621 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
6627 gtk_clist_set_focus_child (GtkContainer *container,
6630 g_return_if_fail (container != NULL);
6631 g_return_if_fail (GTK_IS_CLIST (container));
6635 g_return_if_fail (GTK_IS_WIDGET (child));
6636 GTK_CLIST_SET_FLAG (container, CLIST_CHILD_HAS_FOCUS);
6639 parent_class->set_focus_child (container, child);
6643 title_focus (GtkCList *clist,
6646 GtkWidget *focus_child;
6647 gboolean return_val = FALSE;
6653 if (!GTK_CLIST_SHOW_TITLES(clist))
6656 focus_child = GTK_CONTAINER (clist)->focus_child;
6658 for (last_column = clist->columns - 1;
6659 last_column >= 0 && !clist->column[last_column].visible; last_column--)
6664 case GTK_DIR_TAB_BACKWARD:
6666 if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist))
6668 if (dir == GTK_DIR_UP)
6669 i = COLUMN_FROM_XPIXEL (clist, 0);
6672 focus_child = clist->column[i].button;
6673 dir = GTK_DIR_TAB_FORWARD;
6683 focus_child = clist->column[i].button;
6690 focus_child = clist->column[i].button;
6696 while (i < clist->columns)
6698 if (clist->column[i].button == focus_child)
6700 if (clist->column[i].button &&
6701 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
6702 GTK_IS_CONTAINER (clist->column[i].button) &&
6703 !GTK_WIDGET_HAS_FOCUS(clist->column[i].button))
6704 if (gtk_container_focus
6705 (GTK_CONTAINER (clist->column[i].button), dir))
6710 if (!return_val && dir == GTK_DIR_UP)
6721 while (j >= 0 && j < clist->columns)
6723 if (clist->column[j].button &&
6724 GTK_WIDGET_VISIBLE (clist->column[j].button))
6726 if (GTK_IS_CONTAINER (clist->column[j].button) &&
6728 (GTK_CONTAINER (clist->column[j].button), dir))
6733 else if (GTK_WIDGET_CAN_FOCUS (clist->column[j].button))
6735 gtk_widget_grab_focus (clist->column[j].button);
6745 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
6746 gtk_clist_moveto (clist, -1, j, 0, 0);
6747 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
6748 clist->clist_window_width)
6750 if (j == last_column)
6751 gtk_clist_moveto (clist, -1, j, 0, 0);
6753 gtk_clist_moveto (clist, -1, j, 0, 1);
6759 /* PRIVATE SCROLLING FUNCTIONS
6765 * horizontal_timeout
6770 move_focus_row (GtkCList *clist,
6771 GtkScrollType scroll_type,
6776 g_return_if_fail (clist != 0);
6777 g_return_if_fail (GTK_IS_CLIST (clist));
6779 widget = GTK_WIDGET (clist);
6781 switch (scroll_type)
6783 case GTK_SCROLL_STEP_BACKWARD:
6784 if (clist->focus_row <= 0)
6786 gtk_clist_draw_focus (widget);
6788 gtk_clist_draw_focus (widget);
6790 case GTK_SCROLL_STEP_FORWARD:
6791 if (clist->focus_row >= clist->rows - 1)
6793 gtk_clist_draw_focus (widget);
6795 gtk_clist_draw_focus (widget);
6797 case GTK_SCROLL_PAGE_BACKWARD:
6798 if (clist->focus_row <= 0)
6800 gtk_clist_draw_focus (widget);
6801 clist->focus_row = MAX (0, clist->focus_row -
6802 (2 * clist->clist_window_height -
6803 clist->row_height - CELL_SPACING) /
6804 (2 * (clist->row_height + CELL_SPACING)));
6805 gtk_clist_draw_focus (widget);
6807 case GTK_SCROLL_PAGE_FORWARD:
6808 if (clist->focus_row >= clist->rows - 1)
6810 gtk_clist_draw_focus (widget);
6811 clist->focus_row = MIN (clist->rows - 1, 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_JUMP:
6818 if (position >= 0 && position <= 1)
6820 gtk_clist_draw_focus (widget);
6821 clist->focus_row = position * (clist->rows - 1);
6822 gtk_clist_draw_focus (widget);
6831 scroll_horizontal (GtkCList *clist,
6832 GtkScrollType scroll_type,
6838 g_return_if_fail (clist != 0);
6839 g_return_if_fail (GTK_IS_CLIST (clist));
6841 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
6844 for (last_column = clist->columns - 1;
6845 last_column >= 0 && !clist->column[last_column].visible; last_column--)
6848 switch (scroll_type)
6850 case GTK_SCROLL_STEP_BACKWARD:
6851 column = COLUMN_FROM_XPIXEL (clist, 0);
6852 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
6856 case GTK_SCROLL_STEP_FORWARD:
6857 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
6860 if (COLUMN_LEFT_XPIXEL (clist, column) +
6861 clist->column[column].area.width +
6862 CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
6863 column < last_column)
6866 case GTK_SCROLL_PAGE_BACKWARD:
6867 case GTK_SCROLL_PAGE_FORWARD:
6869 case GTK_SCROLL_JUMP:
6870 if (position >= 0 && position <= 1)
6872 gint vis_columns = 0;
6875 for (i = 0; i <= last_column; i++)
6876 if (clist->column[i].visible)
6879 column = position * vis_columns;
6881 for (i = 0; i <= last_column && column > 0; i++)
6882 if (clist->column[i].visible)
6894 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
6895 gtk_clist_moveto (clist, -1, column, 0, 0);
6896 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
6897 + clist->column[column].area.width > clist->clist_window_width)
6899 if (column == last_column)
6900 gtk_clist_moveto (clist, -1, column, 0, 0);
6902 gtk_clist_moveto (clist, -1, column, 0, 1);
6907 scroll_vertical (GtkCList *clist,
6908 GtkScrollType scroll_type,
6913 g_return_if_fail (clist != NULL);
6914 g_return_if_fail (GTK_IS_CLIST (clist));
6916 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
6919 switch (clist->selection_mode)
6921 case GTK_SELECTION_EXTENDED:
6922 if (clist->anchor >= 0)
6924 case GTK_SELECTION_BROWSE:
6926 old_focus_row = clist->focus_row;
6927 move_focus_row (clist, scroll_type, position);
6929 if (old_focus_row != clist->focus_row)
6931 if (clist->selection_mode == GTK_SELECTION_BROWSE)
6932 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
6933 old_focus_row, -1, NULL);
6934 else if (!GTK_CLIST_ADD_MODE(clist))
6936 gtk_clist_unselect_all (clist);
6937 clist->undo_anchor = old_focus_row;
6941 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
6943 case GTK_VISIBILITY_NONE:
6944 if (old_focus_row != clist->focus_row &&
6945 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
6946 GTK_CLIST_ADD_MODE(clist)))
6947 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6948 clist->focus_row, -1, NULL);
6949 switch (scroll_type)
6951 case GTK_SCROLL_STEP_BACKWARD:
6952 case GTK_SCROLL_PAGE_BACKWARD:
6953 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6955 case GTK_SCROLL_STEP_FORWARD:
6956 case GTK_SCROLL_PAGE_FORWARD:
6957 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6959 case GTK_SCROLL_JUMP:
6960 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
6966 case GTK_VISIBILITY_PARTIAL:
6967 switch (scroll_type)
6969 case GTK_SCROLL_STEP_BACKWARD:
6970 case GTK_SCROLL_PAGE_BACKWARD:
6971 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6973 case GTK_SCROLL_STEP_FORWARD:
6974 case GTK_SCROLL_PAGE_FORWARD:
6975 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6977 case GTK_SCROLL_JUMP:
6978 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
6984 if (old_focus_row != clist->focus_row &&
6985 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
6986 GTK_CLIST_ADD_MODE(clist)))
6987 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6988 clist->focus_row, -1, NULL);
6993 move_focus_row (clist, scroll_type, position);
6995 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
6996 clist->clist_window_height)
6997 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6998 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
6999 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
7005 move_horizontal (GtkCList *clist,
7010 if (!clist->hadjustment)
7013 value = CLAMP (clist->hadjustment->value + diff, 0.0,
7014 clist->hadjustment->upper - clist->hadjustment->page_size);
7015 gtk_adjustment_set_value(clist->hadjustment, value);
7019 move_vertical (GtkCList *clist,
7025 if (!clist->vadjustment)
7028 value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
7029 align * (clist->clist_window_height - clist->row_height) +
7030 (2 * align - 1) * CELL_SPACING);
7032 if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
7033 value = clist->vadjustment->upper - clist->vadjustment->page_size;
7035 gtk_adjustment_set_value(clist->vadjustment, value);
7039 horizontal_timeout (GtkCList *clist)
7042 GdkEventMotion event;
7043 GdkModifierType mask;
7045 GDK_THREADS_ENTER ();
7048 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
7055 gtk_clist_motion (GTK_WIDGET (clist), &event);
7057 GDK_THREADS_LEAVE ();
7063 vertical_timeout (GtkCList *clist)
7066 GdkEventMotion event;
7067 GdkModifierType mask;
7069 GDK_THREADS_ENTER ();
7072 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
7079 gtk_clist_motion (GTK_WIDGET (clist), &event);
7081 GDK_THREADS_LEAVE ();
7087 remove_grab (GtkCList *clist)
7089 if (GTK_WIDGET_HAS_GRAB (clist))
7091 gtk_grab_remove (GTK_WIDGET (clist));
7092 if (gdk_pointer_is_grabbed ())
7093 gdk_pointer_ungrab (GDK_CURRENT_TIME);
7098 gtk_timeout_remove (clist->htimer);
7104 gtk_timeout_remove (clist->vtimer);
7109 /* PUBLIC SORTING FUNCTIONS
7111 * gtk_clist_set_compare_func
7112 * gtk_clist_set_auto_sort
7113 * gtk_clist_set_sort_type
7114 * gtk_clist_set_sort_column
7117 gtk_clist_sort (GtkCList *clist)
7119 g_return_if_fail (clist != NULL);
7120 g_return_if_fail (GTK_IS_CLIST (clist));
7122 GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
7126 gtk_clist_set_compare_func (GtkCList *clist,
7127 GtkCListCompareFunc cmp_func)
7129 g_return_if_fail (clist != NULL);
7130 g_return_if_fail (GTK_IS_CLIST (clist));
7132 clist->compare = (cmp_func) ? cmp_func : default_compare;
7136 gtk_clist_set_auto_sort (GtkCList *clist,
7139 g_return_if_fail (clist != NULL);
7140 g_return_if_fail (GTK_IS_CLIST (clist));
7142 if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
7143 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
7144 else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
7146 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
7147 gtk_clist_sort (clist);
7152 gtk_clist_set_sort_type (GtkCList *clist,
7153 GtkSortType sort_type)
7155 g_return_if_fail (clist != NULL);
7156 g_return_if_fail (GTK_IS_CLIST (clist));
7158 clist->sort_type = sort_type;
7162 gtk_clist_set_sort_column (GtkCList *clist,
7165 g_return_if_fail (clist != NULL);
7166 g_return_if_fail (GTK_IS_CLIST (clist));
7168 if (column < 0 || column >= clist->columns)
7171 clist->sort_column = column;
7174 /* PRIVATE SORTING FUNCTIONS
7178 * gtk_clist_mergesort
7181 default_compare (GtkCList *clist,
7188 GtkCListRow *row1 = (GtkCListRow *) ptr1;
7189 GtkCListRow *row2 = (GtkCListRow *) ptr2;
7191 switch (row1->cell[clist->sort_column].type)
7194 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
7196 case GTK_CELL_PIXTEXT:
7197 text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
7203 switch (row2->cell[clist->sort_column].type)
7206 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
7208 case GTK_CELL_PIXTEXT:
7209 text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
7216 return (text1 != NULL);
7221 return strcmp (text1, text2);
7225 real_sort_list (GtkCList *clist)
7231 g_return_if_fail (clist != NULL);
7232 g_return_if_fail (GTK_IS_CLIST (clist));
7234 if (clist->rows <= 1)
7237 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
7240 gtk_clist_freeze (clist);
7242 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
7244 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7245 g_list_free (clist->undo_selection);
7246 g_list_free (clist->undo_unselection);
7247 clist->undo_selection = NULL;
7248 clist->undo_unselection = NULL;
7251 clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
7253 work = clist->selection;
7255 for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
7257 if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
7259 work->data = GINT_TO_POINTER (i);
7263 if (i == clist->rows - 1)
7264 clist->row_list_end = list;
7267 gtk_clist_thaw (clist);
7271 gtk_clist_merge (GtkCList *clist,
7272 GList *a, /* first list to merge */
7273 GList *b) /* second list to merge */
7275 GList z = { 0 }; /* auxiliary node */
7301 cmp = clist->compare (clist, GTK_CLIST_ROW (a), GTK_CLIST_ROW (b));
7302 if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
7303 (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
7325 gtk_clist_mergesort (GtkCList *clist,
7326 GList *list, /* the list to sort */
7327 gint num) /* the list's length */
7338 /* move "half" to the middle */
7340 for (i = 0; i < num / 2; i++)
7343 /* cut the list in two */
7344 half->prev->next = NULL;
7347 /* recursively sort both lists */
7348 return gtk_clist_merge (clist,
7349 gtk_clist_mergesort (clist, list, num / 2),
7350 gtk_clist_mergesort (clist, half, num - num / 2));
7354 /************************/
7357 drag_source_info_destroy (gpointer data)
7359 GtkCListCellInfo *info = data;
7365 drag_dest_info_destroy (gpointer data)
7367 GtkCListDestInfo *info = data;
7373 gtk_clist_drag_begin (GtkWidget *widget,
7374 GdkDragContext *context)
7377 GtkCListCellInfo *info;
7379 g_return_if_fail (widget != NULL);
7380 g_return_if_fail (GTK_IS_CLIST (widget));
7381 g_return_if_fail (context != NULL);
7383 clist = GTK_CLIST (widget);
7385 clist->drag_button = 0;
7386 remove_grab (clist);
7388 switch (clist->selection_mode)
7390 case GTK_SELECTION_EXTENDED:
7391 update_extended_selection (clist, clist->focus_row);
7392 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7394 case GTK_SELECTION_SINGLE:
7395 case GTK_SELECTION_MULTIPLE:
7397 case GTK_SELECTION_BROWSE:
7401 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7405 info = g_new (GtkCListCellInfo, 1);
7407 if (clist->click_cell.row < 0)
7408 clist->click_cell.row = 0;
7409 else if (clist->click_cell.row >= clist->rows)
7410 clist->click_cell.row = clist->rows - 1;
7411 info->row = clist->click_cell.row;
7412 info->column = clist->click_cell.column;
7414 g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
7415 drag_source_info_destroy);
7418 if (GTK_CLIST_USE_DRAG_ICONS (clist))
7419 gtk_drag_set_icon_default (context);
7423 gtk_clist_drag_end (GtkWidget *widget,
7424 GdkDragContext *context)
7428 g_return_if_fail (widget != NULL);
7429 g_return_if_fail (GTK_IS_CLIST (widget));
7430 g_return_if_fail (context != NULL);
7432 clist = GTK_CLIST (widget);
7434 clist->click_cell.row = -1;
7435 clist->click_cell.column = -1;
7439 gtk_clist_drag_leave (GtkWidget *widget,
7440 GdkDragContext *context,
7444 GtkCListDestInfo *dest_info;
7446 g_return_if_fail (widget != NULL);
7447 g_return_if_fail (GTK_IS_CLIST (widget));
7448 g_return_if_fail (context != NULL);
7450 clist = GTK_CLIST (widget);
7452 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7456 if (dest_info->cell.row >= 0 &&
7457 GTK_CLIST_REORDERABLE(clist) &&
7458 gtk_drag_get_source_widget (context) == widget)
7461 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7463 list = context->targets;
7466 if (atom == GPOINTER_TO_INT (list->data))
7468 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7470 g_list_nth (clist->row_list, dest_info->cell.row)->data,
7471 dest_info->cell.row, dest_info->insert_pos);
7477 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7482 gtk_clist_drag_motion (GtkWidget *widget,
7483 GdkDragContext *context,
7490 GtkCListDestInfo *dest_info;
7492 gint insert_pos = GTK_CLIST_DRAG_NONE;
7495 g_return_val_if_fail (widget != NULL, FALSE);
7496 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7498 clist = GTK_CLIST (widget);
7500 y -= (GTK_CONTAINER (widget)->border_width +
7501 widget->style->klass->ythickness + clist->column_title_area.height);
7502 row = ROW_FROM_YPIXEL (clist, y);
7504 if (row >= clist->rows)
7506 row = clist->rows - 1;
7507 y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
7512 x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
7513 column = COLUMN_FROM_XPIXEL (clist, x);
7517 y_delta = y - ROW_TOP_YPIXEL (clist, row);
7519 if (GTK_CLIST_DRAW_DRAG_RECT(clist))
7521 insert_pos = GTK_CLIST_DRAG_INTO;
7522 h = clist->row_height / 4;
7524 else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7526 insert_pos = GTK_CLIST_DRAG_BEFORE;
7527 h = clist->row_height / 2;
7530 if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7533 insert_pos = GTK_CLIST_DRAG_BEFORE;
7534 else if (clist->row_height - y_delta < h)
7535 insert_pos = GTK_CLIST_DRAG_AFTER;
7539 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7543 dest_info = g_new (GtkCListDestInfo, 1);
7545 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
7546 dest_info->cell.row = -1;
7547 dest_info->cell.column = -1;
7549 g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
7550 drag_dest_info_destroy);
7553 if (GTK_CLIST_REORDERABLE (clist))
7556 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7558 list = context->targets;
7561 if (atom == GPOINTER_TO_INT (list->data))
7568 if (gtk_drag_get_source_widget (context) != widget ||
7569 insert_pos == GTK_CLIST_DRAG_NONE ||
7570 row == clist->click_cell.row ||
7571 (row == clist->click_cell.row - 1 &&
7572 insert_pos == GTK_CLIST_DRAG_AFTER) ||
7573 (row == clist->click_cell.row + 1 &&
7574 insert_pos == GTK_CLIST_DRAG_BEFORE))
7576 if (dest_info->cell.row < 0)
7578 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
7584 if (row != dest_info->cell.row ||
7585 (row == dest_info->cell.row &&
7586 dest_info->insert_pos != insert_pos))
7588 if (dest_info->cell.row >= 0)
7589 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7590 (clist, g_list_nth (clist->row_list,
7591 dest_info->cell.row)->data,
7592 dest_info->cell.row, dest_info->insert_pos);
7594 dest_info->insert_pos = insert_pos;
7595 dest_info->cell.row = row;
7596 dest_info->cell.column = column;
7598 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7599 (clist, g_list_nth (clist->row_list,
7600 dest_info->cell.row)->data,
7601 dest_info->cell.row, dest_info->insert_pos);
7603 gdk_drag_status (context, context->suggested_action, time);
7609 dest_info->insert_pos = insert_pos;
7610 dest_info->cell.row = row;
7611 dest_info->cell.column = column;
7616 gtk_clist_drag_drop (GtkWidget *widget,
7617 GdkDragContext *context,
7622 g_return_val_if_fail (widget != NULL, FALSE);
7623 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7624 g_return_val_if_fail (context != NULL, FALSE);
7626 if (GTK_CLIST_REORDERABLE (widget) &&
7627 gtk_drag_get_source_widget (context) == widget)
7630 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7632 list = context->targets;
7635 if (atom == GPOINTER_TO_INT (list->data))
7644 gtk_clist_drag_data_received (GtkWidget *widget,
7645 GdkDragContext *context,
7648 GtkSelectionData *selection_data,
7654 g_return_if_fail (widget != NULL);
7655 g_return_if_fail (GTK_IS_CLIST (widget));
7656 g_return_if_fail (context != NULL);
7657 g_return_if_fail (selection_data != NULL);
7659 clist = GTK_CLIST (widget);
7661 if (GTK_CLIST_REORDERABLE (clist) &&
7662 gtk_drag_get_source_widget (context) == widget &&
7663 selection_data->target ==
7664 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
7665 selection_data->format == GTK_TYPE_POINTER &&
7666 selection_data->length == sizeof (GtkCListCellInfo))
7668 GtkCListCellInfo *source_info;
7669 GtkCListDestInfo *dest_info;
7671 source_info = (GtkCListCellInfo *)(selection_data->data);
7672 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7674 if (dest_info && source_info)
7676 if (dest_info->insert_pos == GTK_CLIST_DRAG_AFTER)
7677 dest_info->cell.row++;
7678 if (source_info->row < dest_info->cell.row)
7679 dest_info->cell.row--;
7681 if (dest_info->cell.row != source_info->row)
7682 gtk_clist_row_move (GTK_CLIST (widget),
7684 dest_info->cell.row);
7685 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7691 gtk_clist_drag_data_get (GtkWidget *widget,
7692 GdkDragContext *context,
7693 GtkSelectionData *selection_data,
7697 g_return_if_fail (widget != NULL);
7698 g_return_if_fail (GTK_IS_CLIST (widget));
7699 g_return_if_fail (context != NULL);
7700 g_return_if_fail (selection_data != NULL);
7702 if (selection_data->target ==
7703 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
7705 GtkCListCellInfo *info;
7707 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7711 GtkCListCellInfo *ret_info;
7713 ret_info = g_new (GtkCListCellInfo, 1);
7714 ret_info->row = info->row;
7715 ret_info->column = info->column;
7717 gtk_selection_data_set (selection_data,
7718 selection_data->target,
7720 (guchar *) ret_info,
7721 sizeof (GtkCListCellInfo));
7724 gtk_selection_data_set (selection_data, selection_data->target,
7725 GTK_TYPE_POINTER, NULL, 0);
7730 draw_drag_highlight (GtkCList *clist,
7731 GtkCListRow *dest_row,
7732 gint dest_row_number,
7733 GtkCListDragPos drag_pos)
7737 y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
7741 case GTK_CLIST_DRAG_NONE:
7743 case GTK_CLIST_DRAG_AFTER:
7744 y += clist->row_height + 1;
7745 case GTK_CLIST_DRAG_BEFORE:
7746 gdk_draw_line (clist->clist_window, clist->xor_gc,
7747 0, y, clist->clist_window_width, y);
7749 case GTK_CLIST_DRAG_INTO:
7750 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
7751 clist->clist_window_width - 1, clist->row_height);
7757 gtk_clist_set_reorderable (GtkCList *clist,
7758 gboolean reorderable)
7762 g_return_if_fail (clist != NULL);
7763 g_return_if_fail (GTK_IS_CLIST (clist));
7765 if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
7768 widget = GTK_WIDGET (clist);
7772 GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
7773 gtk_drag_dest_set (widget,
7774 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
7775 &clist_target_table, 1, GDK_ACTION_MOVE);
7779 GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
7780 gtk_drag_dest_unset (GTK_WIDGET (clist));
7785 gtk_clist_set_use_drag_icons (GtkCList *clist,
7788 g_return_if_fail (clist != NULL);
7789 g_return_if_fail (GTK_IS_CLIST (clist));
7792 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7794 GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7798 gtk_clist_set_button_actions (GtkCList *clist,
7800 guint8 button_actions)
7802 g_return_if_fail (clist != NULL);
7803 g_return_if_fail (GTK_IS_CLIST (clist));
7805 if (button <= MAX_BUTTON)
7807 if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
7809 remove_grab (clist);
7810 clist->drag_button = 0;
7813 if (clist->anchor >= 0 &&
7814 clist->selection_mode == GTK_SELECTION_EXTENDED)
7815 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7817 clist->button_actions[button] = button_actions;