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 64
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,
446 static gint column_title_passive_func (GtkWidget *widget,
452 static GtkContainerClass *parent_class = NULL;
453 static guint clist_signals[LAST_SIGNAL] = {0};
455 static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
458 gtk_clist_get_type (void)
460 static GtkType clist_type = 0;
464 static const GtkTypeInfo clist_info =
468 sizeof (GtkCListClass),
469 (GtkClassInitFunc) gtk_clist_class_init,
470 (GtkObjectInitFunc) gtk_clist_init,
471 /* reserved_1 */ NULL,
472 /* reserved_2 */ NULL,
473 (GtkClassInitFunc) NULL,
476 clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
483 gtk_clist_class_init (GtkCListClass *klass)
485 GtkObjectClass *object_class;
486 GtkWidgetClass *widget_class;
487 GtkContainerClass *container_class;
488 GtkBindingSet *binding_set;
490 object_class = (GtkObjectClass *) klass;
491 widget_class = (GtkWidgetClass *) klass;
492 container_class = (GtkContainerClass *) klass;
494 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
496 gtk_object_add_arg_type ("GtkCList::n_columns",
498 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
500 gtk_object_add_arg_type ("GtkCList::shadow_type",
501 GTK_TYPE_SHADOW_TYPE,
504 gtk_object_add_arg_type ("GtkCList::selection_mode",
505 GTK_TYPE_SELECTION_MODE,
508 gtk_object_add_arg_type ("GtkCList::row_height",
512 gtk_object_add_arg_type ("GtkCList::reorderable",
516 gtk_object_add_arg_type ("GtkCList::titles_active",
520 gtk_object_add_arg_type ("GtkCList::use_drag_icons",
525 object_class->set_arg = gtk_clist_set_arg;
526 object_class->get_arg = gtk_clist_get_arg;
527 object_class->destroy = gtk_clist_destroy;
528 object_class->finalize = gtk_clist_finalize;
531 widget_class->set_scroll_adjustments_signal =
532 gtk_signal_new ("set_scroll_adjustments",
535 GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
536 gtk_marshal_NONE__POINTER_POINTER,
537 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
539 clist_signals[SELECT_ROW] =
540 gtk_signal_new ("select_row",
543 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
544 gtk_marshal_NONE__INT_INT_POINTER,
549 clist_signals[UNSELECT_ROW] =
550 gtk_signal_new ("unselect_row",
553 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
554 gtk_marshal_NONE__INT_INT_POINTER,
555 GTK_TYPE_NONE, 3, GTK_TYPE_INT,
556 GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
557 clist_signals[ROW_MOVE] =
558 gtk_signal_new ("row_move",
561 GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
562 gtk_marshal_NONE__INT_INT,
563 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
564 clist_signals[CLICK_COLUMN] =
565 gtk_signal_new ("click_column",
568 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
569 gtk_marshal_NONE__INT,
570 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
571 clist_signals[RESIZE_COLUMN] =
572 gtk_signal_new ("resize_column",
575 GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
576 gtk_marshal_NONE__INT_INT,
577 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
579 clist_signals[TOGGLE_FOCUS_ROW] =
580 gtk_signal_new ("toggle_focus_row",
581 GTK_RUN_LAST | GTK_RUN_ACTION,
583 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
584 gtk_marshal_NONE__NONE,
586 clist_signals[SELECT_ALL] =
587 gtk_signal_new ("select_all",
588 GTK_RUN_LAST | GTK_RUN_ACTION,
590 GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
591 gtk_marshal_NONE__NONE,
593 clist_signals[UNSELECT_ALL] =
594 gtk_signal_new ("unselect_all",
595 GTK_RUN_LAST | GTK_RUN_ACTION,
597 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
598 gtk_marshal_NONE__NONE,
600 clist_signals[UNDO_SELECTION] =
601 gtk_signal_new ("undo_selection",
602 GTK_RUN_LAST | GTK_RUN_ACTION,
604 GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
605 gtk_marshal_NONE__NONE,
607 clist_signals[START_SELECTION] =
608 gtk_signal_new ("start_selection",
609 GTK_RUN_LAST | GTK_RUN_ACTION,
611 GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
612 gtk_marshal_NONE__NONE,
614 clist_signals[END_SELECTION] =
615 gtk_signal_new ("end_selection",
616 GTK_RUN_LAST | GTK_RUN_ACTION,
618 GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
619 gtk_marshal_NONE__NONE,
621 clist_signals[TOGGLE_ADD_MODE] =
622 gtk_signal_new ("toggle_add_mode",
623 GTK_RUN_LAST | GTK_RUN_ACTION,
625 GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
626 gtk_marshal_NONE__NONE,
628 clist_signals[EXTEND_SELECTION] =
629 gtk_signal_new ("extend_selection",
630 GTK_RUN_LAST | GTK_RUN_ACTION,
632 GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
633 gtk_marshal_NONE__ENUM_FLOAT_BOOL,
635 GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
636 clist_signals[SCROLL_VERTICAL] =
637 gtk_signal_new ("scroll_vertical",
638 GTK_RUN_LAST | GTK_RUN_ACTION,
640 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
641 gtk_marshal_NONE__ENUM_FLOAT,
642 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
643 clist_signals[SCROLL_HORIZONTAL] =
644 gtk_signal_new ("scroll_horizontal",
645 GTK_RUN_LAST | GTK_RUN_ACTION,
647 GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
648 gtk_marshal_NONE__ENUM_FLOAT,
649 GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
650 clist_signals[ABORT_COLUMN_RESIZE] =
651 gtk_signal_new ("abort_column_resize",
652 GTK_RUN_LAST | GTK_RUN_ACTION,
654 GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
655 gtk_marshal_NONE__NONE,
657 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
659 widget_class->realize = gtk_clist_realize;
660 widget_class->unrealize = gtk_clist_unrealize;
661 widget_class->map = gtk_clist_map;
662 widget_class->unmap = gtk_clist_unmap;
663 widget_class->draw = gtk_clist_draw;
664 widget_class->button_press_event = gtk_clist_button_press;
665 widget_class->button_release_event = gtk_clist_button_release;
666 widget_class->motion_notify_event = gtk_clist_motion;
667 widget_class->expose_event = gtk_clist_expose;
668 widget_class->size_request = gtk_clist_size_request;
669 widget_class->size_allocate = gtk_clist_size_allocate;
670 widget_class->key_press_event = gtk_clist_key_press;
671 widget_class->focus_in_event = gtk_clist_focus_in;
672 widget_class->focus_out_event = gtk_clist_focus_out;
673 widget_class->draw_focus = gtk_clist_draw_focus;
674 widget_class->style_set = gtk_clist_style_set;
675 widget_class->drag_begin = gtk_clist_drag_begin;
676 widget_class->drag_end = gtk_clist_drag_end;
677 widget_class->drag_motion = gtk_clist_drag_motion;
678 widget_class->drag_leave = gtk_clist_drag_leave;
679 widget_class->drag_drop = gtk_clist_drag_drop;
680 widget_class->drag_data_get = gtk_clist_drag_data_get;
681 widget_class->drag_data_received = gtk_clist_drag_data_received;
683 /* container_class->add = NULL; use the default GtkContainerClass warning */
684 /* container_class->remove=NULL; use the default GtkContainerClass warning */
686 container_class->forall = gtk_clist_forall;
687 container_class->focus = gtk_clist_focus;
688 container_class->set_focus_child = gtk_clist_set_focus_child;
690 klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
691 klass->refresh = clist_refresh;
692 klass->select_row = real_select_row;
693 klass->unselect_row = real_unselect_row;
694 klass->row_move = real_row_move;
695 klass->undo_selection = real_undo_selection;
696 klass->resync_selection = resync_selection;
697 klass->selection_find = selection_find;
698 klass->click_column = NULL;
699 klass->resize_column = real_resize_column;
700 klass->draw_row = draw_row;
701 klass->draw_drag_highlight = draw_drag_highlight;
702 klass->insert_row = real_insert_row;
703 klass->remove_row = real_remove_row;
704 klass->clear = real_clear;
705 klass->sort_list = real_sort_list;
706 klass->select_all = real_select_all;
707 klass->unselect_all = real_unselect_all;
708 klass->fake_unselect_all = fake_unselect_all;
709 klass->scroll_horizontal = scroll_horizontal;
710 klass->scroll_vertical = scroll_vertical;
711 klass->extend_selection = extend_selection;
712 klass->toggle_focus_row = toggle_focus_row;
713 klass->toggle_add_mode = toggle_add_mode;
714 klass->start_selection = start_selection;
715 klass->end_selection = end_selection;
716 klass->abort_column_resize = abort_column_resize;
717 klass->set_cell_contents = set_cell_contents;
718 klass->cell_size_request = cell_size_request;
720 binding_set = gtk_binding_set_by_class (klass);
721 gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
722 "scroll_vertical", 2,
723 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
724 GTK_TYPE_FLOAT, 0.0);
725 gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
726 "scroll_vertical", 2,
727 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
728 GTK_TYPE_FLOAT, 0.0);
729 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
730 "scroll_vertical", 2,
731 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
732 GTK_TYPE_FLOAT, 0.0);
733 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
734 "scroll_vertical", 2,
735 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
736 GTK_TYPE_FLOAT, 0.0);
737 gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
738 "scroll_vertical", 2,
739 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
740 GTK_TYPE_FLOAT, 0.0);
741 gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
742 "scroll_vertical", 2,
743 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
744 GTK_TYPE_FLOAT, 1.0);
746 gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
747 "extend_selection", 3,
748 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
749 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
750 gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
751 "extend_selection", 3,
752 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
753 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
754 gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
755 "extend_selection", 3,
756 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
757 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
758 gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
759 "extend_selection", 3,
760 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
761 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
762 gtk_binding_entry_add_signal (binding_set, GDK_Home,
763 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
764 "extend_selection", 3,
765 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
766 GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
767 gtk_binding_entry_add_signal (binding_set, GDK_End,
768 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
769 "extend_selection", 3,
770 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
771 GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
773 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
774 "scroll_horizontal", 2,
775 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
776 GTK_TYPE_FLOAT, 0.0);
777 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
778 "scroll_horizontal", 2,
779 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
780 GTK_TYPE_FLOAT, 0.0);
781 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
782 "scroll_horizontal", 2,
783 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
784 GTK_TYPE_FLOAT, 0.0);
785 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
786 "scroll_horizontal", 2,
787 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
788 GTK_TYPE_FLOAT, 1.0);
790 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
791 "undo_selection", 0);
792 gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
793 "abort_column_resize", 0);
794 gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
795 "toggle_focus_row", 0);
796 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
797 "toggle_add_mode", 0);
798 gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
800 gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
802 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
803 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
805 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
806 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
808 gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
809 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
812 gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
813 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
819 gtk_clist_set_arg (GtkObject *object,
825 clist = GTK_CLIST (object);
829 case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
830 gtk_clist_construct (clist, MAX (1, GTK_VALUE_UINT (*arg)), NULL);
832 case ARG_SHADOW_TYPE:
833 gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
835 case ARG_SELECTION_MODE:
836 gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
839 gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
841 case ARG_REORDERABLE:
842 gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
844 case ARG_TITLES_ACTIVE:
845 if (GTK_VALUE_BOOL (*arg))
846 gtk_clist_column_titles_active (clist);
848 gtk_clist_column_titles_passive (clist);
850 case ARG_USE_DRAG_ICONS:
851 gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
859 gtk_clist_get_arg (GtkObject *object,
865 clist = GTK_CLIST (object);
872 GTK_VALUE_UINT (*arg) = clist->columns;
874 case ARG_SHADOW_TYPE:
875 GTK_VALUE_ENUM (*arg) = clist->shadow_type;
877 case ARG_SELECTION_MODE:
878 GTK_VALUE_ENUM (*arg) = clist->selection_mode;
881 GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
883 case ARG_REORDERABLE:
884 GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
886 case ARG_TITLES_ACTIVE:
887 GTK_VALUE_BOOL (*arg) = TRUE;
888 for (i = 0; i < clist->columns; i++)
889 if (clist->column[i].button &&
890 !GTK_WIDGET_SENSITIVE (clist->column[i].button))
892 GTK_VALUE_BOOL (*arg) = FALSE;
896 case ARG_USE_DRAG_ICONS:
897 GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
900 arg->type = GTK_TYPE_INVALID;
906 gtk_clist_init (GtkCList *clist)
910 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
911 GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
912 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
913 GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
914 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
916 clist->row_mem_chunk = NULL;
917 clist->cell_mem_chunk = NULL;
919 clist->freeze_count = 0;
922 clist->row_center_offset = 0;
923 clist->row_height = 0;
924 clist->row_list = NULL;
925 clist->row_list_end = NULL;
929 clist->title_window = NULL;
930 clist->column_title_area.x = 0;
931 clist->column_title_area.y = 0;
932 clist->column_title_area.width = 1;
933 clist->column_title_area.height = 1;
935 clist->clist_window = NULL;
936 clist->clist_window_width = 1;
937 clist->clist_window_height = 1;
942 clist->shadow_type = GTK_SHADOW_IN;
943 clist->vadjustment = NULL;
944 clist->hadjustment = NULL;
946 clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
947 clist->button_actions[1] = GTK_BUTTON_IGNORED;
948 clist->button_actions[2] = GTK_BUTTON_IGNORED;
949 clist->button_actions[3] = GTK_BUTTON_IGNORED;
950 clist->button_actions[4] = GTK_BUTTON_IGNORED;
952 clist->cursor_drag = NULL;
953 clist->xor_gc = NULL;
958 clist->selection_mode = GTK_SELECTION_SINGLE;
959 clist->selection = NULL;
960 clist->selection_end = NULL;
961 clist->undo_selection = NULL;
962 clist->undo_unselection = NULL;
964 clist->focus_row = -1;
965 clist->undo_anchor = -1;
968 clist->anchor_state = GTK_STATE_SELECTED;
969 clist->drag_pos = -1;
973 clist->click_cell.row = -1;
974 clist->click_cell.column = -1;
976 clist->compare = default_compare;
977 clist->sort_type = GTK_SORT_ASCENDING;
978 clist->sort_column = 0;
983 gtk_clist_construct (GtkCList *clist,
987 g_return_if_fail (clist != NULL);
988 g_return_if_fail (GTK_IS_CLIST (clist));
989 g_return_if_fail (columns > 0);
990 g_return_if_fail (GTK_OBJECT_CONSTRUCTED (clist) == FALSE);
992 /* mark the object as constructed */
993 gtk_object_constructed (GTK_OBJECT (clist));
995 /* initalize memory chunks, if this has not been done by any
996 * possibly derived widget
998 if (!clist->row_mem_chunk)
999 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
1000 sizeof (GtkCListRow),
1001 sizeof (GtkCListRow) *
1005 if (!clist->cell_mem_chunk)
1006 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
1007 sizeof (GtkCell) * columns,
1008 sizeof (GtkCell) * columns *
1012 /* set number of columns, allocate memory */
1013 clist->columns = columns;
1014 clist->column = columns_new (clist);
1016 /* there needs to be at least one column button
1017 * because there is alot of code that will break if it
1019 column_button_create (clist, 0);
1025 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1026 for (i = 0; i < columns; i++)
1027 gtk_clist_set_column_title (clist, i, titles[i]);
1031 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1035 /* GTKCLIST PUBLIC INTERFACE
1037 * gtk_clist_new_with_titles
1038 * gtk_clist_set_hadjustment
1039 * gtk_clist_set_vadjustment
1040 * gtk_clist_get_hadjustment
1041 * gtk_clist_get_vadjustment
1042 * gtk_clist_set_shadow_type
1043 * gtk_clist_set_selection_mode
1048 gtk_clist_new (gint columns)
1050 return gtk_clist_new_with_titles (columns, NULL);
1054 gtk_clist_new_with_titles (gint columns,
1059 widget = gtk_type_new (GTK_TYPE_CLIST);
1060 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
1066 gtk_clist_set_hadjustment (GtkCList *clist,
1067 GtkAdjustment *adjustment)
1069 GtkAdjustment *old_adjustment;
1071 g_return_if_fail (clist != NULL);
1072 g_return_if_fail (GTK_IS_CLIST (clist));
1074 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1076 if (clist->hadjustment == adjustment)
1079 old_adjustment = clist->hadjustment;
1081 if (clist->hadjustment)
1083 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
1084 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
1087 clist->hadjustment = adjustment;
1089 if (clist->hadjustment)
1091 gtk_object_ref (GTK_OBJECT (clist->hadjustment));
1092 gtk_object_sink (GTK_OBJECT (clist->hadjustment));
1094 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
1095 (GtkSignalFunc) hadjustment_changed,
1097 gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
1098 (GtkSignalFunc) hadjustment_value_changed,
1102 if (!clist->hadjustment || !old_adjustment)
1103 gtk_widget_queue_resize (GTK_WIDGET (clist));
1107 gtk_clist_get_hadjustment (GtkCList *clist)
1109 g_return_val_if_fail (clist != NULL, NULL);
1110 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1112 return clist->hadjustment;
1116 gtk_clist_set_vadjustment (GtkCList *clist,
1117 GtkAdjustment *adjustment)
1119 GtkAdjustment *old_adjustment;
1121 g_return_if_fail (clist != NULL);
1122 g_return_if_fail (GTK_IS_CLIST (clist));
1124 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
1126 if (clist->vadjustment == adjustment)
1129 old_adjustment = clist->vadjustment;
1131 if (clist->vadjustment)
1133 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
1134 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
1137 clist->vadjustment = adjustment;
1139 if (clist->vadjustment)
1141 gtk_object_ref (GTK_OBJECT (clist->vadjustment));
1142 gtk_object_sink (GTK_OBJECT (clist->vadjustment));
1144 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
1145 (GtkSignalFunc) vadjustment_changed,
1147 gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
1148 (GtkSignalFunc) vadjustment_value_changed,
1152 if (!clist->vadjustment || !old_adjustment)
1153 gtk_widget_queue_resize (GTK_WIDGET (clist));
1157 gtk_clist_get_vadjustment (GtkCList *clist)
1159 g_return_val_if_fail (clist != NULL, NULL);
1160 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1162 return clist->vadjustment;
1166 gtk_clist_set_scroll_adjustments (GtkCList *clist,
1167 GtkAdjustment *hadjustment,
1168 GtkAdjustment *vadjustment)
1170 if (clist->hadjustment != hadjustment)
1171 gtk_clist_set_hadjustment (clist, hadjustment);
1172 if (clist->vadjustment != vadjustment)
1173 gtk_clist_set_vadjustment (clist, vadjustment);
1177 gtk_clist_set_shadow_type (GtkCList *clist,
1180 g_return_if_fail (clist != NULL);
1181 g_return_if_fail (GTK_IS_CLIST (clist));
1183 clist->shadow_type = type;
1185 if (GTK_WIDGET_VISIBLE (clist))
1186 gtk_widget_queue_resize (GTK_WIDGET (clist));
1190 gtk_clist_set_selection_mode (GtkCList *clist,
1191 GtkSelectionMode mode)
1193 g_return_if_fail (clist != NULL);
1194 g_return_if_fail (GTK_IS_CLIST (clist));
1196 if (mode == clist->selection_mode)
1199 clist->selection_mode = mode;
1201 clist->anchor_state = GTK_STATE_SELECTED;
1202 clist->drag_pos = -1;
1203 clist->undo_anchor = clist->focus_row;
1205 g_list_free (clist->undo_selection);
1206 g_list_free (clist->undo_unselection);
1207 clist->undo_selection = NULL;
1208 clist->undo_unselection = NULL;
1212 case GTK_SELECTION_MULTIPLE:
1213 case GTK_SELECTION_EXTENDED:
1215 case GTK_SELECTION_BROWSE:
1216 case GTK_SELECTION_SINGLE:
1217 gtk_clist_unselect_all (clist);
1223 gtk_clist_freeze (GtkCList *clist)
1225 g_return_if_fail (clist != NULL);
1226 g_return_if_fail (GTK_IS_CLIST (clist));
1228 clist->freeze_count++;
1232 gtk_clist_thaw (GtkCList *clist)
1234 g_return_if_fail (clist != NULL);
1235 g_return_if_fail (GTK_IS_CLIST (clist));
1237 if (clist->freeze_count)
1239 clist->freeze_count--;
1240 CLIST_REFRESH (clist);
1244 /* PUBLIC COLUMN FUNCTIONS
1245 * gtk_clist_column_titles_show
1246 * gtk_clist_column_titles_hide
1247 * gtk_clist_column_title_active
1248 * gtk_clist_column_title_passive
1249 * gtk_clist_column_titles_active
1250 * gtk_clist_column_titles_passive
1251 * gtk_clist_set_column_title
1252 * gtk_clist_get_column_title
1253 * gtk_clist_set_column_widget
1254 * gtk_clist_set_column_justification
1255 * gtk_clist_set_column_visibility
1256 * gtk_clist_set_column_resizeable
1257 * gtk_clist_set_column_auto_resize
1258 * gtk_clist_optimal_column_width
1259 * gtk_clist_set_column_width
1260 * gtk_clist_set_column_min_width
1261 * gtk_clist_set_column_max_width
1264 gtk_clist_column_titles_show (GtkCList *clist)
1266 g_return_if_fail (clist != NULL);
1267 g_return_if_fail (GTK_IS_CLIST (clist));
1269 if (!GTK_CLIST_SHOW_TITLES(clist))
1271 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
1272 if (clist->title_window)
1273 gdk_window_show (clist->title_window);
1274 gtk_widget_queue_resize (GTK_WIDGET (clist));
1279 gtk_clist_column_titles_hide (GtkCList *clist)
1281 g_return_if_fail (clist != NULL);
1282 g_return_if_fail (GTK_IS_CLIST (clist));
1284 if (GTK_CLIST_SHOW_TITLES(clist))
1286 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
1287 if (clist->title_window)
1288 gdk_window_hide (clist->title_window);
1289 gtk_widget_queue_resize (GTK_WIDGET (clist));
1294 gtk_clist_column_title_active (GtkCList *clist,
1299 g_return_if_fail (clist != NULL);
1300 g_return_if_fail (GTK_IS_CLIST (clist));
1302 if (column < 0 || column >= clist->columns)
1304 if (!clist->column[column].button || !clist->column[column].button_passive)
1307 object = GTK_OBJECT (clist->column[column].button);
1309 clist->column[column].button_passive = FALSE;
1311 gtk_signal_disconnect_by_func (object,
1312 (GtkSignalFunc) column_title_passive_func,
1313 GINT_TO_POINTER (gtk_signal_lookup
1314 ("button_press_event",
1316 gtk_signal_disconnect_by_func (object,
1317 (GtkSignalFunc) column_title_passive_func,
1318 GINT_TO_POINTER (gtk_signal_lookup
1319 ("button_release_event",
1321 gtk_signal_disconnect_by_func (object,
1322 (GtkSignalFunc) column_title_passive_func,
1323 GINT_TO_POINTER (gtk_signal_lookup
1324 ("motion_notify_event",
1326 gtk_signal_disconnect_by_func (object,
1327 (GtkSignalFunc) column_title_passive_func,
1328 GINT_TO_POINTER (gtk_signal_lookup
1329 ("enter_notify_event",
1331 gtk_signal_disconnect_by_func (object,
1332 (GtkSignalFunc) column_title_passive_func,
1333 GINT_TO_POINTER (gtk_signal_lookup
1334 ("leave_notify_event",
1337 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
1338 if (GTK_WIDGET_VISIBLE (clist))
1339 gtk_widget_queue_draw (clist->column[column].button);
1343 gtk_clist_column_title_passive (GtkCList *clist,
1349 g_return_if_fail (clist != NULL);
1350 g_return_if_fail (GTK_IS_CLIST (clist));
1352 if (column < 0 || column >= clist->columns)
1354 if (!clist->column[column].button || clist->column[column].button_passive)
1357 object = GTK_OBJECT (clist->column[column].button);
1358 button = GTK_BUTTON (clist->column[column].button);
1360 clist->column[column].button_passive = TRUE;
1364 gtk_signal_connect (object, "button_press_event",
1365 (GtkSignalFunc) column_title_passive_func,
1366 GINT_TO_POINTER (gtk_signal_lookup
1367 ("button_press_event",
1370 if (button->button_down)
1371 gtk_button_released (button);
1373 gtk_signal_connect (object, "button_release_event",
1374 (GtkSignalFunc) column_title_passive_func,
1375 GINT_TO_POINTER (gtk_signal_lookup
1376 ("button_release_event",
1378 gtk_signal_connect (object, "motion_notify_event",
1379 (GtkSignalFunc) column_title_passive_func,
1380 GINT_TO_POINTER (gtk_signal_lookup
1381 ("motion_notify_event",
1383 gtk_signal_connect (object, "enter_notify_event",
1384 (GtkSignalFunc) column_title_passive_func,
1385 GINT_TO_POINTER (gtk_signal_lookup
1386 ("enter_notify_event",
1389 if (button->in_button)
1390 gtk_button_leave (button);
1392 gtk_signal_connect (object, "leave_notify_event",
1393 (GtkSignalFunc) column_title_passive_func,
1394 GINT_TO_POINTER (gtk_signal_lookup
1395 ("leave_notify_event",
1398 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
1399 if (GTK_WIDGET_VISIBLE (clist))
1400 gtk_widget_queue_draw (clist->column[column].button);
1404 gtk_clist_column_titles_active (GtkCList *clist)
1408 g_return_if_fail (clist != NULL);
1409 g_return_if_fail (GTK_IS_CLIST (clist));
1411 if (!GTK_CLIST_SHOW_TITLES(clist))
1414 for (i = 0; i < clist->columns; i++)
1415 gtk_clist_column_title_active (clist, i);
1419 gtk_clist_column_titles_passive (GtkCList *clist)
1423 g_return_if_fail (clist != NULL);
1424 g_return_if_fail (GTK_IS_CLIST (clist));
1426 if (!GTK_CLIST_SHOW_TITLES(clist))
1429 for (i = 0; i < clist->columns; i++)
1430 gtk_clist_column_title_passive (clist, i);
1434 gtk_clist_set_column_title (GtkCList *clist,
1438 gint new_button = 0;
1439 GtkWidget *old_widget;
1440 GtkWidget *alignment = NULL;
1443 g_return_if_fail (clist != NULL);
1444 g_return_if_fail (GTK_IS_CLIST (clist));
1446 if (column < 0 || column >= clist->columns)
1449 /* if the column button doesn't currently exist,
1450 * it has to be created first */
1451 if (!clist->column[column].button)
1453 column_button_create (clist, column);
1457 column_title_new (clist, column, title);
1459 /* remove and destroy the old widget */
1460 old_widget = GTK_BIN (clist->column[column].button)->child;
1462 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
1464 /* create new alignment based no column justification */
1465 switch (clist->column[column].justification)
1467 case GTK_JUSTIFY_LEFT:
1468 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
1471 case GTK_JUSTIFY_RIGHT:
1472 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
1475 case GTK_JUSTIFY_CENTER:
1476 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1479 case GTK_JUSTIFY_FILL:
1480 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1484 gtk_widget_push_composite_child ();
1485 label = gtk_label_new (clist->column[column].title);
1486 gtk_widget_pop_composite_child ();
1487 gtk_container_add (GTK_CONTAINER (alignment), label);
1488 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
1489 gtk_widget_show (label);
1490 gtk_widget_show (alignment);
1492 /* if this button didn't previously exist, then the
1493 * column button positions have to be re-computed */
1494 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1495 size_allocate_title_buttons (clist);
1499 gtk_clist_get_column_title (GtkCList *clist,
1502 g_return_val_if_fail (clist != NULL, NULL);
1503 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1505 if (column < 0 || column >= clist->columns)
1508 return clist->column[column].title;
1512 gtk_clist_set_column_widget (GtkCList *clist,
1516 gint new_button = 0;
1517 GtkWidget *old_widget;
1519 g_return_if_fail (clist != NULL);
1520 g_return_if_fail (GTK_IS_CLIST (clist));
1522 if (column < 0 || column >= clist->columns)
1525 /* if the column button doesn't currently exist,
1526 * it has to be created first */
1527 if (!clist->column[column].button)
1529 column_button_create (clist, column);
1533 column_title_new (clist, column, NULL);
1535 /* remove and destroy the old widget */
1536 old_widget = GTK_BIN (clist->column[column].button)->child;
1538 gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
1541 /* add and show the widget */
1544 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1545 gtk_widget_show (widget);
1548 /* if this button didn't previously exist, then the
1549 * column button positions have to be re-computed */
1550 if (GTK_WIDGET_VISIBLE (clist) && new_button)
1551 size_allocate_title_buttons (clist);
1555 gtk_clist_get_column_widget (GtkCList *clist,
1558 g_return_val_if_fail (clist != NULL, NULL);
1559 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1561 if (column < 0 || column >= clist->columns)
1564 if (clist->column[column].button)
1565 return GTK_BUTTON (clist->column[column].button)->child;
1571 gtk_clist_set_column_justification (GtkCList *clist,
1573 GtkJustification justification)
1575 GtkWidget *alignment;
1577 g_return_if_fail (clist != NULL);
1578 g_return_if_fail (GTK_IS_CLIST (clist));
1580 if (column < 0 || column >= clist->columns)
1583 clist->column[column].justification = justification;
1585 /* change the alinment of the button title if it's not a
1587 if (clist->column[column].title)
1589 alignment = GTK_BIN (clist->column[column].button)->child;
1591 switch (clist->column[column].justification)
1593 case GTK_JUSTIFY_LEFT:
1594 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1597 case GTK_JUSTIFY_RIGHT:
1598 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1601 case GTK_JUSTIFY_CENTER:
1602 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1605 case GTK_JUSTIFY_FILL:
1606 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1614 if (CLIST_UNFROZEN (clist))
1615 draw_rows (clist, NULL);
1619 gtk_clist_set_column_visibility (GtkCList *clist,
1623 g_return_if_fail (clist != NULL);
1624 g_return_if_fail (GTK_IS_CLIST (clist));
1626 if (column < 0 || column >= clist->columns)
1628 if (clist->column[column].visible == visible)
1631 /* don't hide last visible column */
1635 gint vis_columns = 0;
1637 for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
1638 if (clist->column[i].visible)
1641 if (vis_columns < 2)
1645 clist->column[column].visible = visible;
1647 if (clist->column[column].button)
1650 gtk_widget_show (clist->column[column].button);
1652 gtk_widget_hide (clist->column[column].button);
1655 gtk_widget_queue_resize (GTK_WIDGET(clist));
1659 gtk_clist_set_column_resizeable (GtkCList *clist,
1663 g_return_if_fail (clist != NULL);
1664 g_return_if_fail (GTK_IS_CLIST (clist));
1666 if (column < 0 || column >= clist->columns)
1668 if (clist->column[column].resizeable == resizeable)
1671 clist->column[column].resizeable = resizeable;
1673 clist->column[column].auto_resize = FALSE;
1675 if (GTK_WIDGET_VISIBLE (clist))
1676 size_allocate_title_buttons (clist);
1680 gtk_clist_set_column_auto_resize (GtkCList *clist,
1682 gboolean auto_resize)
1684 g_return_if_fail (clist != NULL);
1685 g_return_if_fail (GTK_IS_CLIST (clist));
1687 if (column < 0 || column >= clist->columns)
1689 if (clist->column[column].auto_resize == auto_resize)
1692 clist->column[column].auto_resize = auto_resize;
1695 clist->column[column].resizeable = FALSE;
1696 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
1700 width = gtk_clist_optimal_column_width (clist, column);
1701 gtk_clist_set_column_width (clist, column, width);
1705 if (GTK_WIDGET_VISIBLE (clist))
1706 size_allocate_title_buttons (clist);
1710 gtk_clist_columns_autosize (GtkCList *clist)
1715 g_return_val_if_fail (clist != NULL, 0);
1716 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
1718 gtk_clist_freeze (clist);
1720 for (i = 0; i < clist->columns; i++)
1722 gtk_clist_set_column_width (clist, i,
1723 gtk_clist_optimal_column_width (clist, i));
1725 width += clist->column[i].width;
1728 gtk_clist_thaw (clist);
1733 gtk_clist_optimal_column_width (GtkCList *clist,
1736 GtkRequisition requisition;
1740 g_return_val_if_fail (clist != NULL, 0);
1741 g_return_val_if_fail (GTK_CLIST (clist), 0);
1743 if (column < 0 || column > clist->columns)
1746 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1747 width = (clist->column[column].button->requisition.width)
1749 (CELL_SPACING + (2 * COLUMN_INSET)))
1755 for (list = clist->row_list; list; list = list->next)
1757 GTK_CLIST_CLASS_FW (clist)->cell_size_request
1758 (clist, GTK_CLIST_ROW (list), column, &requisition);
1759 width = MAX (width, requisition.width);
1766 gtk_clist_set_column_width (GtkCList *clist,
1770 g_return_if_fail (clist != NULL);
1771 g_return_if_fail (GTK_IS_CLIST (clist));
1773 if (column < 0 || column >= clist->columns)
1776 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
1781 gtk_clist_set_column_min_width (GtkCList *clist,
1785 g_return_if_fail (clist != NULL);
1786 g_return_if_fail (GTK_IS_CLIST (clist));
1788 if (column < 0 || column >= clist->columns)
1790 if (clist->column[column].min_width == min_width)
1793 if (clist->column[column].max_width >= 0 &&
1794 clist->column[column].max_width < min_width)
1795 clist->column[column].min_width = clist->column[column].max_width;
1797 clist->column[column].min_width = min_width;
1799 if (clist->column[column].area.width < clist->column[column].min_width)
1800 gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
1804 gtk_clist_set_column_max_width (GtkCList *clist,
1808 g_return_if_fail (clist != NULL);
1809 g_return_if_fail (GTK_IS_CLIST (clist));
1811 if (column < 0 || column >= clist->columns)
1813 if (clist->column[column].max_width == max_width)
1816 if (clist->column[column].min_width >= 0 && max_width >= 0 &&
1817 clist->column[column].min_width > max_width)
1818 clist->column[column].max_width = clist->column[column].min_width;
1820 clist->column[column].max_width = max_width;
1822 if (clist->column[column].area.width > clist->column[column].max_width)
1823 gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
1826 /* PRIVATE COLUMN FUNCTIONS
1827 * column_auto_resize
1828 * real_resize_column
1829 * abort_column_resize
1830 * size_allocate_title_buttons
1831 * size_allocate_columns
1832 * list_requisition_width
1834 * column_button_create
1835 * column_button_clicked
1836 * column_title_passive_func
1839 column_auto_resize (GtkCList *clist,
1840 GtkCListRow *clist_row,
1844 /* resize column if needed for auto_resize */
1845 GtkRequisition requisition;
1847 if (!clist->column[column].auto_resize ||
1848 GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
1852 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
1853 column, &requisition);
1855 requisition.width = 0;
1857 if (requisition.width > clist->column[column].width)
1858 gtk_clist_set_column_width (clist, column, requisition.width);
1859 else if (requisition.width < old_width &&
1860 old_width == clist->column[column].width)
1865 /* run a "gtk_clist_optimal_column_width" but break, if
1866 * the column doesn't shrink */
1867 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
1868 new_width = (clist->column[column].button->requisition.width -
1869 (CELL_SPACING + (2 * COLUMN_INSET)));
1873 for (list = clist->row_list; list; list = list->next)
1875 GTK_CLIST_CLASS_FW (clist)->cell_size_request
1876 (clist, GTK_CLIST_ROW (list), column, &requisition);
1877 new_width = MAX (new_width, requisition.width);
1878 if (new_width == clist->column[column].width)
1881 if (new_width < clist->column[column].width)
1882 gtk_clist_set_column_width
1883 (clist, column, MAX (new_width, clist->column[column].min_width));
1888 real_resize_column (GtkCList *clist,
1892 g_return_if_fail (clist != NULL);
1893 g_return_if_fail (GTK_IS_CLIST (clist));
1895 if (column < 0 || column >= clist->columns)
1898 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
1899 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
1900 if (clist->column[column].max_width >= 0 &&
1901 width > clist->column[column].max_width)
1902 width = clist->column[column].max_width;
1904 clist->column[column].width = width;
1905 clist->column[column].width_set = TRUE;
1907 /* FIXME: this is quite expensive to do if the widget hasn't
1908 * been size_allocated yet, and pointless. Should
1911 size_allocate_columns (clist, TRUE);
1912 size_allocate_title_buttons (clist);
1914 CLIST_REFRESH (clist);
1918 abort_column_resize (GtkCList *clist)
1920 g_return_if_fail (clist != NULL);
1921 g_return_if_fail (GTK_IS_CLIST (clist));
1923 if (!GTK_CLIST_IN_DRAG(clist))
1926 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
1927 gtk_grab_remove (GTK_WIDGET (clist));
1928 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1929 clist->drag_pos = -1;
1931 if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
1932 draw_xor_line (clist);
1934 if (GTK_CLIST_ADD_MODE(clist))
1936 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
1937 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
1942 size_allocate_title_buttons (GtkCList *clist)
1944 GtkAllocation button_allocation;
1946 gint last_button = 0;
1949 if (!GTK_WIDGET_REALIZED (clist))
1952 button_allocation.x = clist->hoffset;
1953 button_allocation.y = 0;
1954 button_allocation.width = 0;
1955 button_allocation.height = clist->column_title_area.height;
1957 /* find last visible column */
1958 for (last_column = clist->columns - 1; last_column >= 0; last_column--)
1959 if (clist->column[last_column].visible)
1962 for (i = 0; i < last_column; i++)
1964 if (!clist->column[i].visible)
1966 last_button = i + 1;
1967 gdk_window_hide (clist->column[i].window);
1971 button_allocation.width += (clist->column[i].area.width +
1972 CELL_SPACING + 2 * COLUMN_INSET);
1974 if (!clist->column[i + 1].button)
1976 gdk_window_hide (clist->column[i].window);
1980 gtk_widget_size_allocate (clist->column[last_button].button,
1981 &button_allocation);
1982 button_allocation.x += button_allocation.width;
1983 button_allocation.width = 0;
1985 if (clist->column[last_button].resizeable)
1987 gdk_window_show (clist->column[last_button].window);
1988 gdk_window_move_resize (clist->column[last_button].window,
1989 button_allocation.x - (DRAG_WIDTH / 2),
1991 clist->column_title_area.height);
1994 gdk_window_hide (clist->column[last_button].window);
1996 last_button = i + 1;
1999 button_allocation.width += (clist->column[last_column].area.width +
2000 2 * (CELL_SPACING + COLUMN_INSET));
2001 gtk_widget_size_allocate (clist->column[last_button].button,
2002 &button_allocation);
2004 if (clist->column[last_button].resizeable)
2006 button_allocation.x += button_allocation.width;
2008 gdk_window_show (clist->column[last_button].window);
2009 gdk_window_move_resize (clist->column[last_button].window,
2010 button_allocation.x - (DRAG_WIDTH / 2),
2011 0, DRAG_WIDTH, clist->column_title_area.height);
2014 gdk_window_hide (clist->column[last_button].window);
2018 size_allocate_columns (GtkCList *clist,
2019 gboolean block_resize)
2021 gint xoffset = CELL_SPACING + COLUMN_INSET;
2025 /* find last visible column and calculate correct column width */
2026 for (last_column = clist->columns - 1;
2027 last_column >= 0 && !clist->column[last_column].visible; last_column--);
2029 if (last_column < 0)
2032 for (i = 0; i <= last_column; i++)
2034 if (!clist->column[i].visible)
2036 clist->column[i].area.x = xoffset;
2037 if (clist->column[i].width_set)
2039 if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
2040 clist->column[i].auto_resize && clist->column[i].button)
2044 width = (clist->column[i].button->requisition.width -
2045 (CELL_SPACING + (2 * COLUMN_INSET)));
2047 if (width > clist->column[i].width)
2048 gtk_clist_set_column_width (clist, i, width);
2051 clist->column[i].area.width = clist->column[i].width;
2052 xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
2054 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2056 clist->column[i].area.width =
2057 clist->column[i].button->requisition.width -
2058 (CELL_SPACING + (2 * COLUMN_INSET));
2059 xoffset += clist->column[i].button->requisition.width;
2063 clist->column[last_column].area.width = clist->column[last_column].area.width
2064 + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
2068 list_requisition_width (GtkCList *clist)
2070 gint width = CELL_SPACING;
2073 for (i = clist->columns - 1; i >= 0; i--)
2075 if (!clist->column[i].visible)
2078 if (clist->column[i].width_set)
2079 width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
2080 else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2081 width += clist->column[i].button->requisition.width;
2087 /* this function returns the new width of the column being resized given
2088 * the column and x position of the cursor; the x cursor position is passed
2089 * in as a pointer and automagicly corrected if it's beyond min/max limits */
2091 new_column_width (GtkCList *clist,
2095 gint xthickness = GTK_WIDGET (clist)->style->klass->xthickness;
2101 /* first translate the x position from widget->window
2102 * to clist->clist_window */
2103 cx = *x - xthickness;
2105 for (last_column = clist->columns - 1;
2106 last_column >= 0 && !clist->column[last_column].visible; last_column--);
2108 /* calculate new column width making sure it doesn't end up
2109 * less than the minimum width */
2110 dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
2111 (column < last_column) * CELL_SPACING);
2114 if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
2116 width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
2118 *x = cx + xthickness;
2120 else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
2121 width > clist->column[column].max_width)
2123 width = clist->column[column].max_width;
2124 cx = dx + clist->column[column].max_width;
2125 *x = cx + xthickness;
2128 if (cx < 0 || cx > clist->clist_window_width)
2135 column_button_create (GtkCList *clist,
2140 gtk_widget_push_composite_child ();
2141 button = clist->column[column].button = gtk_button_new ();
2142 gtk_widget_pop_composite_child ();
2144 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
2145 gtk_widget_set_parent_window (clist->column[column].button,
2146 clist->title_window);
2147 gtk_widget_set_parent (button, GTK_WIDGET (clist));
2149 gtk_signal_connect (GTK_OBJECT (button), "clicked",
2150 (GtkSignalFunc) column_button_clicked,
2153 gtk_widget_show (button);
2157 column_button_clicked (GtkWidget *widget,
2163 g_return_if_fail (widget != NULL);
2164 g_return_if_fail (GTK_IS_CLIST (data));
2166 clist = GTK_CLIST (data);
2168 /* find the column who's button was pressed */
2169 for (i = 0; i < clist->columns; i++)
2170 if (clist->column[i].button == widget)
2173 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
2177 column_title_passive_func (GtkWidget *widget,
2181 gtk_signal_emit_stop (GTK_OBJECT (widget), GPOINTER_TO_INT (data));
2186 /* PUBLIC CELL FUNCTIONS
2187 * gtk_clist_get_cell_type
2188 * gtk_clist_set_text
2189 * gtk_clist_get_text
2190 * gtk_clist_set_pixmap
2191 * gtk_clist_get_pixmap
2192 * gtk_clist_set_pixtext
2193 * gtk_clist_get_pixtext
2194 * gtk_clist_set_shift
2197 gtk_clist_get_cell_type (GtkCList *clist,
2201 GtkCListRow *clist_row;
2203 g_return_val_if_fail (clist != NULL, -1);
2204 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2206 if (row < 0 || row >= clist->rows)
2208 if (column < 0 || column >= clist->columns)
2211 clist_row = (g_list_nth (clist->row_list, row))->data;
2213 return clist_row->cell[column].type;
2217 gtk_clist_set_text (GtkCList *clist,
2222 GtkCListRow *clist_row;
2224 g_return_if_fail (clist != NULL);
2225 g_return_if_fail (GTK_IS_CLIST (clist));
2227 if (row < 0 || row >= clist->rows)
2229 if (column < 0 || column >= clist->columns)
2232 clist_row = (g_list_nth (clist->row_list, row))->data;
2234 /* if text is null, then the cell is empty */
2235 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2236 (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
2238 /* redraw the list if it's not frozen */
2239 if (CLIST_UNFROZEN (clist))
2241 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2242 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2247 gtk_clist_get_text (GtkCList *clist,
2252 GtkCListRow *clist_row;
2254 g_return_val_if_fail (clist != NULL, 0);
2255 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2257 if (row < 0 || row >= clist->rows)
2259 if (column < 0 || column >= clist->columns)
2262 clist_row = (g_list_nth (clist->row_list, row))->data;
2264 if (clist_row->cell[column].type != GTK_CELL_TEXT)
2268 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
2274 gtk_clist_set_pixmap (GtkCList *clist,
2280 GtkCListRow *clist_row;
2282 g_return_if_fail (clist != NULL);
2283 g_return_if_fail (GTK_IS_CLIST (clist));
2285 if (row < 0 || row >= clist->rows)
2287 if (column < 0 || column >= clist->columns)
2290 clist_row = (g_list_nth (clist->row_list, row))->data;
2292 gdk_pixmap_ref (pixmap);
2294 if (mask) gdk_pixmap_ref (mask);
2296 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2297 (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
2299 /* redraw the list if it's not frozen */
2300 if (CLIST_UNFROZEN (clist))
2302 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2303 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2308 gtk_clist_get_pixmap (GtkCList *clist,
2314 GtkCListRow *clist_row;
2316 g_return_val_if_fail (clist != NULL, 0);
2317 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2319 if (row < 0 || row >= clist->rows)
2321 if (column < 0 || column >= clist->columns)
2324 clist_row = (g_list_nth (clist->row_list, row))->data;
2326 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
2331 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
2332 /* mask can be NULL */
2333 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
2340 gtk_clist_set_pixtext (GtkCList *clist,
2348 GtkCListRow *clist_row;
2350 g_return_if_fail (clist != NULL);
2351 g_return_if_fail (GTK_IS_CLIST (clist));
2353 if (row < 0 || row >= clist->rows)
2355 if (column < 0 || column >= clist->columns)
2358 clist_row = (g_list_nth (clist->row_list, row))->data;
2360 gdk_pixmap_ref (pixmap);
2361 if (mask) gdk_pixmap_ref (mask);
2362 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2363 (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
2365 /* redraw the list if it's not frozen */
2366 if (CLIST_UNFROZEN (clist))
2368 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2369 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2374 gtk_clist_get_pixtext (GtkCList *clist,
2382 GtkCListRow *clist_row;
2384 g_return_val_if_fail (clist != NULL, 0);
2385 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2387 if (row < 0 || row >= clist->rows)
2389 if (column < 0 || column >= clist->columns)
2392 clist_row = (g_list_nth (clist->row_list, row))->data;
2394 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
2398 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
2400 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2402 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
2404 /* mask can be NULL */
2405 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
2411 gtk_clist_set_shift (GtkCList *clist,
2417 GtkRequisition requisition;
2418 GtkCListRow *clist_row;
2420 g_return_if_fail (clist != NULL);
2421 g_return_if_fail (GTK_IS_CLIST (clist));
2423 if (row < 0 || row >= clist->rows)
2425 if (column < 0 || column >= clist->columns)
2428 clist_row = (g_list_nth (clist->row_list, row))->data;
2430 if (clist->column[column].auto_resize &&
2431 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2432 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2433 column, &requisition);
2435 clist_row->cell[column].vertical = vertical;
2436 clist_row->cell[column].horizontal = horizontal;
2438 column_auto_resize (clist, clist_row, column, requisition.width);
2440 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2441 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
2444 /* PRIVATE CELL FUNCTIONS
2449 set_cell_contents (GtkCList *clist,
2450 GtkCListRow *clist_row,
2458 GtkRequisition requisition;
2460 g_return_if_fail (clist != NULL);
2461 g_return_if_fail (GTK_IS_CLIST (clist));
2462 g_return_if_fail (clist_row != NULL);
2464 if (clist->column[column].auto_resize &&
2465 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2466 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2467 column, &requisition);
2469 switch (clist_row->cell[column].type)
2471 case GTK_CELL_EMPTY:
2474 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2476 case GTK_CELL_PIXMAP:
2477 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2478 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
2479 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2481 case GTK_CELL_PIXTEXT:
2482 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2483 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2484 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
2485 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2487 case GTK_CELL_WIDGET:
2494 clist_row->cell[column].type = GTK_CELL_EMPTY;
2501 clist_row->cell[column].type = GTK_CELL_TEXT;
2502 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2505 case GTK_CELL_PIXMAP:
2508 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2509 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2510 /* We set the mask even if it is NULL */
2511 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2514 case GTK_CELL_PIXTEXT:
2517 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2518 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2519 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2520 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2521 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2528 if (clist->column[column].auto_resize &&
2529 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
2530 column_auto_resize (clist, clist_row, column, requisition.width);
2534 cell_size_request (GtkCList *clist,
2535 GtkCListRow *clist_row,
2537 GtkRequisition *requisition)
2543 g_return_if_fail (clist != NULL);
2544 g_return_if_fail (GTK_IS_CLIST (clist));
2545 g_return_if_fail (requisition != NULL);
2547 get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
2550 switch (clist_row->cell[column].type)
2553 requisition->width =
2554 gdk_string_width (style->font,
2555 GTK_CELL_TEXT (clist_row->cell[column])->text);
2556 requisition->height = style->font->ascent + style->font->descent;
2558 case GTK_CELL_PIXTEXT:
2559 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
2561 requisition->width = width +
2562 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing +
2563 gdk_string_width (style->font,
2564 GTK_CELL_TEXT (clist_row->cell[column])->text);
2566 requisition->height = MAX (style->font->ascent + style->font->descent,
2569 case GTK_CELL_PIXMAP:
2570 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
2572 requisition->width = width;
2573 requisition->height = height;
2576 requisition->width = 0;
2577 requisition->height = 0;
2581 requisition->width += clist_row->cell[column].horizontal;
2582 requisition->height += clist_row->cell[column].vertical;
2585 /* PUBLIC INSERT/REMOVE ROW FUNCTIONS
2593 gtk_clist_prepend (GtkCList *clist,
2596 g_return_val_if_fail (clist != NULL, -1);
2597 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2598 g_return_val_if_fail (text != NULL, -1);
2600 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, 0, text);
2604 gtk_clist_append (GtkCList *clist,
2607 g_return_val_if_fail (clist != NULL, -1);
2608 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2609 g_return_val_if_fail (text != NULL, -1);
2611 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
2615 gtk_clist_insert (GtkCList *clist,
2619 g_return_val_if_fail (clist != NULL, -1);
2620 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2621 g_return_val_if_fail (text != NULL, -1);
2623 if (row < 0 || row > clist->rows)
2626 return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
2630 gtk_clist_remove (GtkCList *clist,
2633 GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
2637 gtk_clist_clear (GtkCList *clist)
2639 g_return_if_fail (clist != NULL);
2640 g_return_if_fail (GTK_IS_CLIST (clist));
2642 GTK_CLIST_CLASS_FW (clist)->clear (clist);
2645 /* PRIVATE INSERT/REMOVE ROW FUNCTIONS
2652 real_insert_row (GtkCList *clist,
2657 GtkCListRow *clist_row;
2659 g_return_val_if_fail (clist != NULL, -1);
2660 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
2661 g_return_val_if_fail (text != NULL, -1);
2663 /* return if out of bounds */
2664 if (row < 0 || row > clist->rows)
2667 /* create the row */
2668 clist_row = row_new (clist);
2670 /* set the text in the row's columns */
2671 for (i = 0; i < clist->columns; i++)
2673 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
2674 (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
2678 clist->row_list = g_list_append (clist->row_list, clist_row);
2679 clist->row_list_end = clist->row_list;
2683 if (GTK_CLIST_AUTO_SORT(clist)) /* override insertion pos */
2688 work = clist->row_list;
2690 if (clist->sort_type == GTK_SORT_ASCENDING)
2692 while (row < clist->rows &&
2693 clist->compare (clist, clist_row,
2694 GTK_CLIST_ROW (work)) > 0)
2702 while (row < clist->rows &&
2703 clist->compare (clist, clist_row,
2704 GTK_CLIST_ROW (work)) < 0)
2712 /* reset the row end pointer if we're inserting at the end of the list */
2713 if (row == clist->rows)
2714 clist->row_list_end = (g_list_append (clist->row_list_end,
2717 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
2722 if (row < ROW_FROM_YPIXEL (clist, 0))
2723 clist->voffset -= (clist->row_height + CELL_SPACING);
2725 /* syncronize the selection list */
2726 sync_selection (clist, row, SYNC_INSERT);
2728 if (clist->rows == 1)
2730 clist->focus_row = 0;
2731 if (clist->selection_mode == GTK_SELECTION_BROWSE)
2732 gtk_clist_select_row (clist, 0, -1);
2735 /* redraw the list if it isn't frozen */
2736 if (CLIST_UNFROZEN (clist))
2738 adjust_adjustments (clist, FALSE);
2740 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
2741 draw_rows (clist, NULL);
2748 real_remove_row (GtkCList *clist,
2751 gint was_visible, was_selected;
2753 GtkCListRow *clist_row;
2755 g_return_if_fail (clist != NULL);
2756 g_return_if_fail (GTK_IS_CLIST (clist));
2758 /* return if out of bounds */
2759 if (row < 0 || row > (clist->rows - 1))
2762 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
2765 /* get the row we're going to delete */
2766 list = g_list_nth (clist->row_list, row);
2767 g_assert (list != NULL);
2768 clist_row = list->data;
2770 /* if we're removing a selected row, we have to make sure
2771 * it's properly unselected, and then sync up the clist->selected
2772 * list to reflect the deincrimented indexies of rows after the
2774 if (clist_row->state == GTK_STATE_SELECTED)
2775 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2778 /* reset the row end pointer if we're removing at the
2779 * end of the list */
2781 if (clist->row_list == list)
2782 clist->row_list = g_list_next (list);
2783 if (clist->row_list_end == list)
2784 clist->row_list_end = g_list_previous (list);
2785 g_list_remove (list, clist_row);
2787 /*if (clist->focus_row >=0 &&
2788 (row <= clist->focus_row || clist->focus_row >= clist->rows))
2789 clist->focus_row--;*/
2791 if (row < ROW_FROM_YPIXEL (clist, 0))
2792 clist->voffset += clist->row_height + CELL_SPACING;
2794 sync_selection (clist, row, SYNC_REMOVE);
2796 if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
2797 clist->focus_row >= 0)
2798 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2799 clist->focus_row, -1, NULL);
2802 row_delete (clist, clist_row);
2804 /* redraw the row if it isn't frozen */
2805 if (CLIST_UNFROZEN (clist))
2807 adjust_adjustments (clist, FALSE);
2810 draw_rows (clist, NULL);
2815 real_clear (GtkCList *clist)
2821 g_return_if_fail (clist != NULL);
2822 g_return_if_fail (GTK_IS_CLIST (clist));
2824 /* free up the selection list */
2825 g_list_free (clist->selection);
2826 g_list_free (clist->undo_selection);
2827 g_list_free (clist->undo_unselection);
2829 clist->selection = NULL;
2830 clist->selection_end = NULL;
2831 clist->undo_selection = NULL;
2832 clist->undo_unselection = NULL;
2834 clist->focus_row = -1;
2836 clist->undo_anchor = -1;
2837 clist->anchor_state = GTK_STATE_SELECTED;
2838 clist->drag_pos = -1;
2840 /* remove all the rows */
2841 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2842 free_list = clist->row_list;
2843 clist->row_list = NULL;
2844 clist->row_list_end = NULL;
2846 for (list = free_list; list; list = list->next)
2847 row_delete (clist, GTK_CLIST_ROW (list));
2848 g_list_free (free_list);
2849 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
2850 for (i = 0; i < clist->columns; i++)
2851 if (clist->column[i].auto_resize)
2853 if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
2854 gtk_clist_set_column_width
2855 (clist, i, (clist->column[i].button->requisition.width -
2856 (CELL_SPACING + (2 * COLUMN_INSET))));
2858 gtk_clist_set_column_width (clist, i, 0);
2860 /* zero-out the scrollbars */
2861 if (clist->vadjustment)
2863 gtk_adjustment_set_value (clist->vadjustment, 0.0);
2864 CLIST_REFRESH (clist);
2867 gtk_widget_queue_resize (GTK_WIDGET (clist));
2871 real_row_move (GtkCList *clist,
2875 GtkCListRow *clist_row;
2880 g_return_if_fail (clist != NULL);
2881 g_return_if_fail (GTK_IS_CLIST (clist));
2883 if (GTK_CLIST_AUTO_SORT(clist))
2886 if (source_row < 0 || source_row >= clist->rows ||
2887 dest_row < 0 || dest_row >= clist->rows ||
2888 source_row == dest_row)
2891 gtk_clist_freeze (clist);
2893 /* unlink source row */
2894 clist_row = g_list_nth_data (clist->row_list, source_row);
2895 if (source_row == clist->rows - 1)
2896 clist->row_list_end = clist->row_list_end->prev;
2897 clist->row_list = g_list_remove (clist->row_list, clist_row);
2900 /* relink source row */
2901 clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
2902 if (dest_row == clist->rows)
2903 clist->row_list_end = clist->row_list_end->next;
2906 /* sync selection */
2907 if (source_row > dest_row)
2920 for (list = clist->selection; list; list = list->next)
2922 if (list->data == GINT_TO_POINTER (source_row))
2923 list->data = GINT_TO_POINTER (dest_row);
2924 else if (first <= GPOINTER_TO_INT (list->data) &&
2925 last >= GPOINTER_TO_INT (list->data))
2926 list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
2929 if (clist->focus_row == source_row)
2930 clist->focus_row = dest_row;
2931 else if (clist->focus_row > first)
2932 clist->focus_row += d;
2934 gtk_clist_thaw (clist);
2937 /* PUBLIC ROW FUNCTIONS
2939 * gtk_clist_set_row_height
2940 * gtk_clist_set_row_data
2941 * gtk_clist_set_row_data_full
2942 * gtk_clist_get_row_data
2943 * gtk_clist_find_row_from_data
2944 * gtk_clist_swap_rows
2945 * gtk_clist_row_move
2946 * gtk_clist_row_is_visible
2947 * gtk_clist_set_foreground
2948 * gtk_clist_set_background
2951 gtk_clist_moveto (GtkCList *clist,
2957 g_return_if_fail (clist != NULL);
2958 g_return_if_fail (GTK_IS_CLIST (clist));
2960 if (row < -1 || row >= clist->rows)
2962 if (column < -1 || column >= clist->columns)
2965 row_align = CLAMP (row_align, 0, 1);
2966 col_align = CLAMP (col_align, 0, 1);
2968 /* adjust horizontal scrollbar */
2969 if (clist->hadjustment && column >= 0)
2973 x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
2974 (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
2975 CELL_SPACING - clist->column[column].area.width)));
2977 gtk_adjustment_set_value (clist->hadjustment, 0.0);
2978 else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
2979 gtk_adjustment_set_value
2980 (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
2982 gtk_adjustment_set_value (clist->hadjustment, x);
2985 /* adjust vertical scrollbar */
2986 if (clist->vadjustment && row >= 0)
2987 move_vertical (clist, row, row_align);
2991 gtk_clist_set_row_height (GtkCList *clist,
2996 g_return_if_fail (clist != NULL);
2997 g_return_if_fail (GTK_IS_CLIST (clist));
2999 widget = GTK_WIDGET (clist);
3003 clist->row_height = height;
3004 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
3008 GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
3009 clist->row_height = 0;
3012 if (GTK_WIDGET_REALIZED (clist))
3014 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
3016 clist->row_height = (widget->style->font->ascent +
3017 widget->style->font->descent + 1);
3018 clist->row_center_offset = widget->style->font->ascent + 1.5;
3021 clist->row_center_offset = 1.5 + (clist->row_height +
3022 widget->style->font->ascent -
3023 widget->style->font->descent - 1) / 2;
3026 CLIST_REFRESH (clist);
3030 gtk_clist_set_row_data (GtkCList *clist,
3034 gtk_clist_set_row_data_full (clist, row, data, NULL);
3038 gtk_clist_set_row_data_full (GtkCList *clist,
3041 GtkDestroyNotify destroy)
3043 GtkCListRow *clist_row;
3045 g_return_if_fail (clist != NULL);
3046 g_return_if_fail (GTK_IS_CLIST (clist));
3048 if (row < 0 || row > (clist->rows - 1))
3051 clist_row = (g_list_nth (clist->row_list, row))->data;
3052 clist_row->data = data;
3053 clist_row->destroy = destroy;
3057 gtk_clist_get_row_data (GtkCList *clist,
3060 GtkCListRow *clist_row;
3062 g_return_val_if_fail (clist != NULL, NULL);
3063 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3065 if (row < 0 || row > (clist->rows - 1))
3068 clist_row = (g_list_nth (clist->row_list, row))->data;
3069 return clist_row->data;
3073 gtk_clist_find_row_from_data (GtkCList *clist,
3079 g_return_val_if_fail (clist != NULL, -1);
3080 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
3082 for (n = 0, list = clist->row_list; list; n++, list = list->next)
3083 if (GTK_CLIST_ROW (list)->data == data)
3090 gtk_clist_swap_rows (GtkCList *clist,
3096 g_return_if_fail (clist != NULL);
3097 g_return_if_fail (GTK_IS_CLIST (clist));
3098 g_return_if_fail (row1 != row2);
3100 if (GTK_CLIST_AUTO_SORT(clist))
3103 gtk_clist_freeze (clist);
3105 first = MIN (row1, row2);
3106 last = MAX (row1, row2);
3108 gtk_clist_row_move (clist, last, first);
3109 gtk_clist_row_move (clist, first + 1, last);
3111 gtk_clist_thaw (clist);
3115 gtk_clist_row_move (GtkCList *clist,
3119 g_return_if_fail (clist != NULL);
3120 g_return_if_fail (GTK_IS_CLIST (clist));
3122 if (GTK_CLIST_AUTO_SORT(clist))
3125 if (source_row < 0 || source_row >= clist->rows ||
3126 dest_row < 0 || dest_row >= clist->rows ||
3127 source_row == dest_row)
3130 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE],
3131 source_row, dest_row);
3135 gtk_clist_row_is_visible (GtkCList *clist,
3140 g_return_val_if_fail (clist != NULL, 0);
3141 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3143 if (row < 0 || row >= clist->rows)
3144 return GTK_VISIBILITY_NONE;
3146 if (clist->row_height == 0)
3147 return GTK_VISIBILITY_NONE;
3149 if (row < ROW_FROM_YPIXEL (clist, 0))
3150 return GTK_VISIBILITY_NONE;
3152 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
3153 return GTK_VISIBILITY_NONE;
3155 top = ROW_TOP_YPIXEL (clist, row);
3158 || ((top + clist->row_height) >= clist->clist_window_height))
3159 return GTK_VISIBILITY_PARTIAL;
3161 return GTK_VISIBILITY_FULL;
3165 gtk_clist_set_foreground (GtkCList *clist,
3169 GtkCListRow *clist_row;
3171 g_return_if_fail (clist != NULL);
3172 g_return_if_fail (GTK_IS_CLIST (clist));
3174 if (row < 0 || row >= clist->rows)
3177 clist_row = (g_list_nth (clist->row_list, row))->data;
3181 clist_row->foreground = *color;
3182 clist_row->fg_set = TRUE;
3183 if (GTK_WIDGET_REALIZED (clist))
3184 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3185 &clist_row->foreground);
3188 clist_row->fg_set = FALSE;
3190 if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3191 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3195 gtk_clist_set_background (GtkCList *clist,
3199 GtkCListRow *clist_row;
3201 g_return_if_fail (clist != NULL);
3202 g_return_if_fail (GTK_IS_CLIST (clist));
3204 if (row < 0 || row >= clist->rows)
3207 clist_row = (g_list_nth (clist->row_list, row))->data;
3211 clist_row->background = *color;
3212 clist_row->bg_set = TRUE;
3213 if (GTK_WIDGET_REALIZED (clist))
3214 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
3215 &clist_row->background);
3218 clist_row->bg_set = FALSE;
3220 if (CLIST_UNFROZEN (clist)
3221 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3222 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3225 /* PUBLIC ROW/CELL STYLE FUNCTIONS
3226 * gtk_clist_set_cell_style
3227 * gtk_clist_get_cell_style
3228 * gtk_clist_set_row_style
3229 * gtk_clist_get_row_style
3232 gtk_clist_set_cell_style (GtkCList *clist,
3237 GtkRequisition requisition;
3238 GtkCListRow *clist_row;
3240 g_return_if_fail (clist != NULL);
3241 g_return_if_fail (GTK_IS_CLIST (clist));
3243 if (row < 0 || row >= clist->rows)
3245 if (column < 0 || column >= clist->columns)
3248 clist_row = (g_list_nth (clist->row_list, row))->data;
3250 if (clist_row->cell[column].style == style)
3253 if (clist->column[column].auto_resize &&
3254 !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3255 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3256 column, &requisition);
3258 if (clist_row->cell[column].style)
3260 if (GTK_WIDGET_REALIZED (clist))
3261 gtk_style_detach (clist_row->cell[column].style);
3262 gtk_style_unref (clist_row->cell[column].style);
3265 clist_row->cell[column].style = style;
3267 if (clist_row->cell[column].style)
3269 gtk_style_ref (clist_row->cell[column].style);
3271 if (GTK_WIDGET_REALIZED (clist))
3272 clist_row->cell[column].style =
3273 gtk_style_attach (clist_row->cell[column].style,
3274 clist->clist_window);
3277 column_auto_resize (clist, clist_row, column, requisition.width);
3279 /* redraw the list if it's not frozen */
3280 if (CLIST_UNFROZEN (clist))
3282 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3283 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3288 gtk_clist_get_cell_style (GtkCList *clist,
3292 GtkCListRow *clist_row;
3294 g_return_val_if_fail (clist != NULL, NULL);
3295 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3297 if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
3300 clist_row = (g_list_nth (clist->row_list, row))->data;
3302 return clist_row->cell[column].style;
3306 gtk_clist_set_row_style (GtkCList *clist,
3310 GtkRequisition requisition;
3311 GtkCListRow *clist_row;
3315 g_return_if_fail (clist != NULL);
3316 g_return_if_fail (GTK_IS_CLIST (clist));
3318 if (row < 0 || row >= clist->rows)
3321 clist_row = (g_list_nth (clist->row_list, row))->data;
3323 if (clist_row->style == style)
3326 old_width = g_new (gint, clist->columns);
3328 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3330 for (i = 0; i < clist->columns; i++)
3331 if (clist->column[i].auto_resize)
3333 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3335 old_width[i] = requisition.width;
3339 if (clist_row->style)
3341 if (GTK_WIDGET_REALIZED (clist))
3342 gtk_style_detach (clist_row->style);
3343 gtk_style_unref (clist_row->style);
3346 clist_row->style = style;
3348 if (clist_row->style)
3350 gtk_style_ref (clist_row->style);
3352 if (GTK_WIDGET_REALIZED (clist))
3353 clist_row->style = gtk_style_attach (clist_row->style,
3354 clist->clist_window);
3357 if (GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
3358 for (i = 0; i < clist->columns; i++)
3359 column_auto_resize (clist, clist_row, i, old_width[i]);
3363 /* redraw the list if it's not frozen */
3364 if (CLIST_UNFROZEN (clist))
3366 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3367 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3372 gtk_clist_get_row_style (GtkCList *clist,
3375 GtkCListRow *clist_row;
3377 g_return_val_if_fail (clist != NULL, NULL);
3378 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
3380 if (row < 0 || row >= clist->rows)
3383 clist_row = (g_list_nth (clist->row_list, row))->data;
3385 return clist_row->style;
3388 /* PUBLIC SELECTION FUNCTIONS
3389 * gtk_clist_set_selectable
3390 * gtk_clist_get_selectable
3391 * gtk_clist_select_row
3392 * gtk_clist_unselect_row
3393 * gtk_clist_select_all
3394 * gtk_clist_unselect_all
3395 * gtk_clist_undo_selection
3398 gtk_clist_set_selectable (GtkCList *clist,
3400 gboolean selectable)
3402 GtkCListRow *clist_row;
3404 g_return_if_fail (clist != NULL);
3405 g_return_if_fail (GTK_IS_CLIST (clist));
3407 if (row < 0 || row >= clist->rows)
3410 clist_row = (g_list_nth (clist->row_list, row))->data;
3412 if (selectable == clist_row->selectable)
3415 clist_row->selectable = selectable;
3417 if (!selectable && clist_row->state == GTK_STATE_SELECTED)
3419 if (clist->anchor >= 0 &&
3420 clist->selection_mode == GTK_SELECTION_EXTENDED)
3422 clist->drag_button = 0;
3423 remove_grab (clist);
3424 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3426 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3432 gtk_clist_get_selectable (GtkCList *clist,
3435 g_return_val_if_fail (clist != NULL, FALSE);
3436 g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
3438 if (row < 0 || row >= clist->rows)
3441 return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
3445 gtk_clist_select_row (GtkCList *clist,
3449 g_return_if_fail (clist != NULL);
3450 g_return_if_fail (GTK_IS_CLIST (clist));
3452 if (row < 0 || row >= clist->rows)
3454 if (column < -1 || column >= clist->columns)
3457 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3462 gtk_clist_unselect_row (GtkCList *clist,
3466 g_return_if_fail (clist != NULL);
3467 g_return_if_fail (GTK_IS_CLIST (clist));
3469 if (row < 0 || row >= clist->rows)
3471 if (column < -1 || column >= clist->columns)
3474 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3479 gtk_clist_select_all (GtkCList *clist)
3481 g_return_if_fail (clist != NULL);
3482 g_return_if_fail (GTK_IS_CLIST (clist));
3484 GTK_CLIST_CLASS_FW (clist)->select_all (clist);
3488 gtk_clist_unselect_all (GtkCList *clist)
3490 g_return_if_fail (clist != NULL);
3491 g_return_if_fail (GTK_IS_CLIST (clist));
3493 GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
3497 gtk_clist_undo_selection (GtkCList *clist)
3499 g_return_if_fail (clist != NULL);
3500 g_return_if_fail (GTK_IS_CLIST (clist));
3502 if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
3503 (clist->undo_selection || clist->undo_unselection))
3504 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
3507 /* PRIVATE SELECTION FUNCTIONS
3518 * real_undo_selection
3521 * update_extended_selection
3528 selection_find (GtkCList *clist,
3530 GList *row_list_element)
3532 return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
3536 toggle_row (GtkCList *clist,
3541 GtkCListRow *clist_row;
3543 switch (clist->selection_mode)
3545 case GTK_SELECTION_EXTENDED:
3546 case GTK_SELECTION_MULTIPLE:
3547 case GTK_SELECTION_SINGLE:
3548 clist_row = g_list_nth (clist->row_list, row)->data;
3553 if (clist_row->state == GTK_STATE_SELECTED)
3555 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3556 row, column, event);
3559 case GTK_SELECTION_BROWSE:
3560 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3561 row, column, event);
3567 fake_toggle_row (GtkCList *clist,
3572 work = g_list_nth (clist->row_list, row);
3574 if (!work || !GTK_CLIST_ROW (work)->selectable)
3577 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
3578 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3580 clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3582 if (CLIST_UNFROZEN (clist) &&
3583 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3584 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
3585 GTK_CLIST_ROW (work));
3589 toggle_focus_row (GtkCList *clist)
3591 g_return_if_fail (clist != 0);
3592 g_return_if_fail (GTK_IS_CLIST (clist));
3594 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3595 clist->focus_row < 0 || clist->focus_row >= clist->rows)
3598 switch (clist->selection_mode)
3600 case GTK_SELECTION_SINGLE:
3601 case GTK_SELECTION_MULTIPLE:
3602 toggle_row (clist, clist->focus_row, 0, NULL);
3604 case GTK_SELECTION_EXTENDED:
3605 g_list_free (clist->undo_selection);
3606 g_list_free (clist->undo_unselection);
3607 clist->undo_selection = NULL;
3608 clist->undo_unselection = NULL;
3610 clist->anchor = clist->focus_row;
3611 clist->drag_pos = clist->focus_row;
3612 clist->undo_anchor = clist->focus_row;
3614 if (GTK_CLIST_ADD_MODE(clist))
3615 fake_toggle_row (clist, clist->focus_row);
3617 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
3619 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3627 toggle_add_mode (GtkCList *clist)
3629 g_return_if_fail (clist != 0);
3630 g_return_if_fail (GTK_IS_CLIST (clist));
3632 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3633 clist->selection_mode != GTK_SELECTION_EXTENDED)
3636 gtk_clist_draw_focus (GTK_WIDGET (clist));
3637 if (!GTK_CLIST_ADD_MODE(clist))
3639 GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
3640 gdk_gc_set_line_attributes (clist->xor_gc, 1,
3641 GDK_LINE_ON_OFF_DASH, 0, 0);
3642 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
3646 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
3647 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
3648 clist->anchor_state = GTK_STATE_SELECTED;
3650 gtk_clist_draw_focus (GTK_WIDGET (clist));
3654 real_select_row (GtkCList *clist,
3659 GtkCListRow *clist_row;
3662 gboolean row_selected;
3664 g_return_if_fail (clist != NULL);
3665 g_return_if_fail (GTK_IS_CLIST (clist));
3667 if (row < 0 || row > (clist->rows - 1))
3670 switch (clist->selection_mode)
3672 case GTK_SELECTION_SINGLE:
3673 case GTK_SELECTION_BROWSE:
3675 row_selected = FALSE;
3676 list = clist->selection;
3680 sel_row = GPOINTER_TO_INT (list->data);
3684 row_selected = TRUE;
3686 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3687 sel_row, column, event);
3697 clist_row = (g_list_nth (clist->row_list, row))->data;
3699 if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
3702 clist_row->state = GTK_STATE_SELECTED;
3703 if (!clist->selection)
3705 clist->selection = g_list_append (clist->selection,
3706 GINT_TO_POINTER (row));
3707 clist->selection_end = clist->selection;
3710 clist->selection_end =
3711 g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
3713 if (CLIST_UNFROZEN (clist)
3714 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3715 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3719 real_unselect_row (GtkCList *clist,
3724 GtkCListRow *clist_row;
3726 g_return_if_fail (clist != NULL);
3727 g_return_if_fail (GTK_IS_CLIST (clist));
3729 if (row < 0 || row > (clist->rows - 1))
3732 clist_row = (g_list_nth (clist->row_list, row))->data;
3734 if (clist_row->state == GTK_STATE_SELECTED)
3736 clist_row->state = GTK_STATE_NORMAL;
3738 if (clist->selection_end &&
3739 clist->selection_end->data == GINT_TO_POINTER (row))
3740 clist->selection_end = clist->selection_end->prev;
3742 clist->selection = g_list_remove (clist->selection,
3743 GINT_TO_POINTER (row));
3745 if (CLIST_UNFROZEN (clist)
3746 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3747 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
3752 real_select_all (GtkCList *clist)
3757 g_return_if_fail (clist != NULL);
3758 g_return_if_fail (GTK_IS_CLIST (clist));
3760 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
3763 switch (clist->selection_mode)
3765 case GTK_SELECTION_SINGLE:
3766 case GTK_SELECTION_BROWSE:
3769 case GTK_SELECTION_EXTENDED:
3770 g_list_free (clist->undo_selection);
3771 g_list_free (clist->undo_unselection);
3772 clist->undo_selection = NULL;
3773 clist->undo_unselection = NULL;
3776 ((GtkCListRow *) (clist->row_list->data))->state !=
3778 fake_toggle_row (clist, 0);
3780 clist->anchor_state = GTK_STATE_SELECTED;
3782 clist->drag_pos = 0;
3783 clist->undo_anchor = clist->focus_row;
3784 update_extended_selection (clist, clist->rows);
3785 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3788 case GTK_SELECTION_MULTIPLE:
3789 for (i = 0, list = clist->row_list; list; i++, list = list->next)
3791 if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
3792 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3800 real_unselect_all (GtkCList *clist)
3805 g_return_if_fail (clist != NULL);
3806 g_return_if_fail (GTK_IS_CLIST (clist));
3808 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
3811 switch (clist->selection_mode)
3813 case GTK_SELECTION_BROWSE:
3814 if (clist->focus_row >= 0)
3816 gtk_signal_emit (GTK_OBJECT (clist),
3817 clist_signals[SELECT_ROW],
3818 clist->focus_row, -1, NULL);
3822 case GTK_SELECTION_EXTENDED:
3823 g_list_free (clist->undo_selection);
3824 g_list_free (clist->undo_unselection);
3825 clist->undo_selection = NULL;
3826 clist->undo_unselection = NULL;
3829 clist->drag_pos = -1;
3830 clist->undo_anchor = clist->focus_row;
3836 list = clist->selection;
3839 i = GPOINTER_TO_INT (list->data);
3841 gtk_signal_emit (GTK_OBJECT (clist),
3842 clist_signals[UNSELECT_ROW], i, -1, NULL);
3847 fake_unselect_all (GtkCList *clist,
3854 if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
3856 if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
3857 GTK_CLIST_ROW (work)->selectable)
3859 GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
3861 if (CLIST_UNFROZEN (clist) &&
3862 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
3863 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
3864 GTK_CLIST_ROW (work));
3868 clist->undo_selection = clist->selection;
3869 clist->selection = NULL;
3870 clist->selection_end = NULL;
3872 for (list = clist->undo_selection; list; list = list->next)
3874 if ((i = GPOINTER_TO_INT (list->data)) == row ||
3875 !(work = g_list_nth (clist->row_list, i)))
3878 GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
3879 if (CLIST_UNFROZEN (clist) &&
3880 gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
3881 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
3882 GTK_CLIST_ROW (work));
3887 real_undo_selection (GtkCList *clist)
3891 g_return_if_fail (clist != NULL);
3892 g_return_if_fail (GTK_IS_CLIST (clist));
3894 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
3895 clist->selection_mode != GTK_SELECTION_EXTENDED)
3898 if (clist->anchor >= 0)
3899 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
3901 if (!(clist->undo_selection || clist->undo_unselection))
3903 gtk_clist_unselect_all (clist);
3907 for (work = clist->undo_selection; work; work = work->next)
3908 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3909 GPOINTER_TO_INT (work->data), -1, NULL);
3911 for (work = clist->undo_unselection; work; work = work->next)
3912 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3913 GPOINTER_TO_INT (work->data), -1, NULL);
3915 if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
3917 gtk_clist_draw_focus (GTK_WIDGET (clist));
3918 clist->focus_row = clist->undo_anchor;
3919 gtk_clist_draw_focus (GTK_WIDGET (clist));
3922 clist->focus_row = clist->undo_anchor;
3924 clist->undo_anchor = -1;
3926 g_list_free (clist->undo_selection);
3927 g_list_free (clist->undo_unselection);
3928 clist->undo_selection = NULL;
3929 clist->undo_unselection = NULL;
3931 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
3932 clist->clist_window_height)
3933 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
3934 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
3935 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
3939 set_anchor (GtkCList *clist,
3944 g_return_if_fail (clist != NULL);
3945 g_return_if_fail (GTK_IS_CLIST (clist));
3947 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
3950 g_list_free (clist->undo_selection);
3951 g_list_free (clist->undo_unselection);
3952 clist->undo_selection = NULL;
3953 clist->undo_unselection = NULL;
3956 fake_toggle_row (clist, anchor);
3959 GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
3960 clist->anchor_state = GTK_STATE_SELECTED;
3963 clist->anchor = anchor;
3964 clist->drag_pos = anchor;
3965 clist->undo_anchor = undo_anchor;
3969 resync_selection (GtkCList *clist,
3976 GtkCListRow *clist_row;
3978 if (clist->anchor < 0)
3981 gtk_clist_freeze (clist);
3983 i = MIN (clist->anchor, clist->drag_pos);
3984 e = MAX (clist->anchor, clist->drag_pos);
3986 if (clist->undo_selection)
3988 list = clist->selection;
3989 clist->selection = clist->undo_selection;
3990 clist->selection_end = g_list_last (clist->selection);
3991 clist->undo_selection = list;
3992 list = clist->selection;
3995 row = GPOINTER_TO_INT (list->data);
3997 if (row < i || row > e)
3999 clist_row = g_list_nth (clist->row_list, row)->data;
4000 if (clist_row->selectable)
4002 clist_row->state = GTK_STATE_SELECTED;
4003 gtk_signal_emit (GTK_OBJECT (clist),
4004 clist_signals[UNSELECT_ROW],
4006 clist->undo_selection = g_list_prepend
4007 (clist->undo_selection, GINT_TO_POINTER (row));
4013 if (clist->anchor < clist->drag_pos)
4015 for (list = g_list_nth (clist->row_list, i); i <= e;
4016 i++, list = list->next)
4017 if (GTK_CLIST_ROW (list)->selectable)
4019 if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
4021 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
4023 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4024 gtk_signal_emit (GTK_OBJECT (clist),
4025 clist_signals[UNSELECT_ROW],
4027 clist->undo_selection =
4028 g_list_prepend (clist->undo_selection,
4029 GINT_TO_POINTER (i));
4032 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
4034 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4035 clist->undo_unselection =
4036 g_list_prepend (clist->undo_unselection,
4037 GINT_TO_POINTER (i));
4043 for (list = g_list_nth (clist->row_list, e); i <= e;
4044 e--, list = list->prev)
4045 if (GTK_CLIST_ROW (list)->selectable)
4047 if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
4049 if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
4051 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4052 gtk_signal_emit (GTK_OBJECT (clist),
4053 clist_signals[UNSELECT_ROW],
4055 clist->undo_selection =
4056 g_list_prepend (clist->undo_selection,
4057 GINT_TO_POINTER (e));
4060 else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
4062 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4063 clist->undo_unselection =
4064 g_list_prepend (clist->undo_unselection,
4065 GINT_TO_POINTER (e));
4070 for (list = g_list_reverse (clist->undo_unselection); list;
4072 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
4073 GPOINTER_TO_INT (list->data), -1, event);
4076 clist->drag_pos = -1;
4078 gtk_clist_thaw (clist);
4082 update_extended_selection (GtkCList *clist,
4092 gint y1 = clist->clist_window_height;
4093 gint y2 = clist->clist_window_height;
4098 if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
4103 if (row >= clist->rows)
4104 row = clist->rows - 1;
4106 /* extending downwards */
4107 if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
4109 s2 = clist->drag_pos + 1;
4112 /* extending upwards */
4113 else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
4116 e2 = clist->drag_pos - 1;
4118 else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
4120 e1 = clist->drag_pos;
4121 /* row and drag_pos on different sides of anchor :
4122 take back the selection between anchor and drag_pos,
4123 select between anchor and row */
4124 if (row < clist->anchor)
4126 s1 = clist->anchor + 1;
4128 e2 = clist->anchor - 1;
4130 /* take back the selection between anchor and drag_pos */
4134 else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
4136 s1 = clist->drag_pos;
4137 /* row and drag_pos on different sides of anchor :
4138 take back the selection between anchor and drag_pos,
4139 select between anchor and row */
4140 if (row > clist->anchor)
4142 e1 = clist->anchor - 1;
4143 s2 = clist->anchor + 1;
4146 /* take back the selection between anchor and drag_pos */
4151 clist->drag_pos = row;
4154 area.width = clist->clist_window_width;
4156 /* restore the elements between s1 and e1 */
4159 for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
4160 i++, list = list->next)
4161 if (GTK_CLIST_ROW (list)->selectable)
4163 if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
4164 GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
4166 GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
4169 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4171 if (top + clist->row_height <= 0)
4174 area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
4175 draw_rows (clist, &area);
4176 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4178 else if (top >= clist->clist_window_height)
4180 area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
4181 area.height = clist->clist_window_height - area.y;
4182 draw_rows (clist, &area);
4183 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4186 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4187 else if (top + clist->row_height > clist->clist_window_height)
4188 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4190 y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
4191 h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
4194 /* extend the selection between s2 and e2 */
4197 for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
4198 i++, list = list->next)
4199 if (GTK_CLIST_ROW (list)->selectable &&
4200 GTK_CLIST_ROW (list)->state != clist->anchor_state)
4201 GTK_CLIST_ROW (list)->state = clist->anchor_state;
4203 top = ROW_TOP_YPIXEL (clist, clist->focus_row);
4205 if (top + clist->row_height <= 0)
4208 area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
4209 draw_rows (clist, &area);
4210 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4212 else if (top >= clist->clist_window_height)
4214 area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
4215 area.height = clist->clist_window_height - area.y;
4216 draw_rows (clist, &area);
4217 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4220 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4221 else if (top + clist->row_height > clist->clist_window_height)
4222 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4224 y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
4225 h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
4228 area.y = MAX (0, MIN (y1, y2));
4229 if (area.y > clist->clist_window_height)
4231 area.height = MIN (clist->clist_window_height, h1 + h2);
4232 if (s1 >= 0 && s2 >= 0)
4233 area.height += (clist->row_height + CELL_SPACING);
4234 draw_rows (clist, &area);
4238 start_selection (GtkCList *clist)
4240 g_return_if_fail (clist != NULL);
4241 g_return_if_fail (GTK_IS_CLIST (clist));
4243 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4246 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4251 end_selection (GtkCList *clist)
4253 g_return_if_fail (clist != NULL);
4254 g_return_if_fail (GTK_IS_CLIST (clist));
4256 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist)) ||
4257 clist->anchor == -1)
4260 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4264 extend_selection (GtkCList *clist,
4265 GtkScrollType scroll_type,
4267 gboolean auto_start_selection)
4269 g_return_if_fail (clist != NULL);
4270 g_return_if_fail (GTK_IS_CLIST (clist));
4272 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
4273 clist->selection_mode != GTK_SELECTION_EXTENDED)
4276 if (auto_start_selection)
4277 set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
4279 else if (clist->anchor == -1)
4282 move_focus_row (clist, scroll_type, position);
4284 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
4285 clist->clist_window_height)
4286 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
4287 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
4288 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
4290 update_extended_selection (clist, clist->focus_row);
4294 sync_selection (GtkCList *clist,
4301 if (mode == SYNC_INSERT)
4306 if (clist->focus_row >= row)
4308 if (d > 0 || clist->focus_row > row)
4309 clist->focus_row += d;
4310 if (clist->focus_row == -1 && clist->rows >= 1)
4311 clist->focus_row = 0;
4312 else if (clist->focus_row >= clist->rows)
4313 clist->focus_row = clist->rows - 1;
4316 if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
4317 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4319 g_list_free (clist->undo_selection);
4320 g_list_free (clist->undo_unselection);
4321 clist->undo_selection = NULL;
4322 clist->undo_unselection = NULL;
4325 clist->drag_pos = -1;
4326 clist->undo_anchor = clist->focus_row;
4328 list = clist->selection;
4332 if (GPOINTER_TO_INT (list->data) >= row)
4333 list->data = ((gchar*) list->data) + d;
4340 * gtk_clist_finalize
4343 gtk_clist_destroy (GtkObject *object)
4348 g_return_if_fail (object != NULL);
4349 g_return_if_fail (GTK_IS_CLIST (object));
4351 clist = GTK_CLIST (object);
4353 /* freeze the list */
4354 clist->freeze_count++;
4356 /* get rid of all the rows */
4357 gtk_clist_clear (clist);
4359 /* Since we don't have a _remove method, unparent the children
4360 * instead of destroying them so the focus will be unset properly.
4361 * (For other containers, the _remove method takes care of the
4362 * unparent) The destroy will happen when the refcount drops
4366 /* unref adjustments */
4367 if (clist->hadjustment)
4369 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
4370 gtk_object_unref (GTK_OBJECT (clist->hadjustment));
4371 clist->hadjustment = NULL;
4373 if (clist->vadjustment)
4375 gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
4376 gtk_object_unref (GTK_OBJECT (clist->vadjustment));
4377 clist->vadjustment = NULL;
4380 remove_grab (clist);
4382 /* destroy the column buttons */
4383 for (i = 0; i < clist->columns; i++)
4384 if (clist->column[i].button)
4386 gtk_widget_unparent (clist->column[i].button);
4387 clist->column[i].button = NULL;
4390 if (GTK_OBJECT_CLASS (parent_class)->destroy)
4391 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
4395 gtk_clist_finalize (GtkObject *object)
4399 g_return_if_fail (object != NULL);
4400 g_return_if_fail (GTK_IS_CLIST (object));
4402 clist = GTK_CLIST (object);
4404 columns_delete (clist);
4406 g_mem_chunk_destroy (clist->cell_mem_chunk);
4407 g_mem_chunk_destroy (clist->row_mem_chunk);
4409 if (GTK_OBJECT_CLASS (parent_class)->finalize)
4410 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
4415 * gtk_clist_unrealize
4420 * gtk_clist_style_set
4421 * gtk_clist_key_press
4422 * gtk_clist_button_press
4423 * gtk_clist_button_release
4425 * gtk_clist_size_request
4426 * gtk_clist_size_allocate
4429 gtk_clist_realize (GtkWidget *widget)
4432 GdkWindowAttr attributes;
4434 GtkCListRow *clist_row;
4436 gint attributes_mask;
4441 g_return_if_fail (widget != NULL);
4442 g_return_if_fail (GTK_IS_CLIST (widget));
4444 clist = GTK_CLIST (widget);
4446 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
4448 border_width = GTK_CONTAINER (widget)->border_width;
4450 attributes.window_type = GDK_WINDOW_CHILD;
4451 attributes.x = widget->allocation.x + border_width;
4452 attributes.y = widget->allocation.y + border_width;
4453 attributes.width = widget->allocation.width - border_width * 2;
4454 attributes.height = widget->allocation.height - border_width * 2;
4455 attributes.wclass = GDK_INPUT_OUTPUT;
4456 attributes.visual = gtk_widget_get_visual (widget);
4457 attributes.colormap = gtk_widget_get_colormap (widget);
4458 attributes.event_mask = gtk_widget_get_events (widget);
4459 attributes.event_mask |= (GDK_EXPOSURE_MASK |
4460 GDK_BUTTON_PRESS_MASK |
4461 GDK_BUTTON_RELEASE_MASK |
4462 GDK_KEY_PRESS_MASK |
4463 GDK_KEY_RELEASE_MASK);
4464 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
4467 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
4468 &attributes, attributes_mask);
4469 gdk_window_set_user_data (widget->window, clist);
4471 widget->style = gtk_style_attach (widget->style, widget->window);
4473 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
4475 /* column-title window */
4477 attributes.x = clist->column_title_area.x;
4478 attributes.y = clist->column_title_area.y;
4479 attributes.width = clist->column_title_area.width;
4480 attributes.height = clist->column_title_area.height;
4482 clist->title_window = gdk_window_new (widget->window, &attributes,
4484 gdk_window_set_user_data (clist->title_window, clist);
4486 gtk_style_set_background (widget->style, clist->title_window,
4488 gdk_window_show (clist->title_window);
4490 /* set things up so column buttons are drawn in title window */
4491 for (i = 0; i < clist->columns; i++)
4492 if (clist->column[i].button)
4493 gtk_widget_set_parent_window (clist->column[i].button,
4494 clist->title_window);
4497 attributes.x = (clist->internal_allocation.x +
4498 widget->style->klass->xthickness);
4499 attributes.y = (clist->internal_allocation.y +
4500 widget->style->klass->ythickness +
4501 clist->column_title_area.height);
4502 attributes.width = clist->clist_window_width;
4503 attributes.height = clist->clist_window_height;
4505 clist->clist_window = gdk_window_new (widget->window, &attributes,
4507 gdk_window_set_user_data (clist->clist_window, clist);
4509 gdk_window_set_background (clist->clist_window,
4510 &widget->style->base[GTK_STATE_NORMAL]);
4511 gdk_window_show (clist->clist_window);
4512 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
4513 &clist->clist_window_height);
4515 /* create resize windows */
4516 attributes.wclass = GDK_INPUT_ONLY;
4517 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
4518 GDK_BUTTON_RELEASE_MASK |
4519 GDK_POINTER_MOTION_MASK |
4520 GDK_POINTER_MOTION_HINT_MASK |
4521 GDK_KEY_PRESS_MASK);
4522 attributes_mask = GDK_WA_CURSOR;
4523 attributes.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
4524 clist->cursor_drag = attributes.cursor;
4526 attributes.x = LIST_WIDTH (clist) + 1;
4528 attributes.width = 0;
4529 attributes.height = 0;
4531 for (i = 0; i < clist->columns; i++)
4533 clist->column[i].window = gdk_window_new (clist->title_window,
4534 &attributes, attributes_mask);
4535 gdk_window_set_user_data (clist->column[i].window, clist);
4538 /* This is slightly less efficient than creating them with the
4539 * right size to begin with, but easier
4541 size_allocate_title_buttons (clist);
4544 clist->fg_gc = gdk_gc_new (widget->window);
4545 clist->bg_gc = gdk_gc_new (widget->window);
4547 /* We'll use this gc to do scrolling as well */
4548 gdk_gc_set_exposures (clist->fg_gc, TRUE);
4550 values.foreground = widget->style->white;
4551 values.function = GDK_XOR;
4552 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
4553 clist->xor_gc = gdk_gc_new_with_values (widget->window,
4559 /* attach optional row/cell styles, allocate foreground/background colors */
4560 list = clist->row_list;
4561 for (i = 0; i < clist->rows; i++)
4563 clist_row = list->data;
4566 if (clist_row->style)
4567 clist_row->style = gtk_style_attach (clist_row->style,
4568 clist->clist_window);
4570 if (clist_row->fg_set || clist_row->bg_set)
4572 GdkColormap *colormap;
4574 colormap = gtk_widget_get_colormap (widget);
4575 if (clist_row->fg_set)
4576 gdk_color_alloc (colormap, &clist_row->foreground);
4577 if (clist_row->bg_set)
4578 gdk_color_alloc (colormap, &clist_row->background);
4581 for (j = 0; j < clist->columns; j++)
4582 if (clist_row->cell[j].style)
4583 clist_row->cell[j].style =
4584 gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
4589 gtk_clist_unrealize (GtkWidget *widget)
4594 g_return_if_fail (widget != NULL);
4595 g_return_if_fail (GTK_IS_CLIST (widget));
4597 clist = GTK_CLIST (widget);
4599 /* freeze the list */
4600 clist->freeze_count++;
4602 /* detach optional row/cell styles */
4604 if (GTK_WIDGET_REALIZED (widget))
4606 GtkCListRow *clist_row;
4610 list = clist->row_list;
4611 for (i = 0; i < clist->rows; i++)
4613 clist_row = list->data;
4616 if (clist_row->style)
4617 gtk_style_detach (clist_row->style);
4618 for (j = 0; j < clist->columns; j++)
4619 if (clist_row->cell[j].style)
4620 gtk_style_detach (clist_row->cell[j].style);
4624 gdk_cursor_destroy (clist->cursor_drag);
4625 gdk_gc_destroy (clist->xor_gc);
4626 gdk_gc_destroy (clist->fg_gc);
4627 gdk_gc_destroy (clist->bg_gc);
4629 for (i = 0; i < clist->columns; i++)
4630 if (clist->column[i].window)
4632 gdk_window_set_user_data (clist->column[i].window, NULL);
4633 gdk_window_destroy (clist->column[i].window);
4634 clist->column[i].window = NULL;
4637 gdk_window_set_user_data (clist->clist_window, NULL);
4638 gdk_window_destroy (clist->clist_window);
4639 clist->clist_window = NULL;
4641 gdk_window_set_user_data (clist->title_window, NULL);
4642 gdk_window_destroy (clist->title_window);
4643 clist->title_window = NULL;
4645 clist->cursor_drag = NULL;
4646 clist->xor_gc = NULL;
4647 clist->fg_gc = NULL;
4648 clist->bg_gc = NULL;
4650 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
4651 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
4655 gtk_clist_map (GtkWidget *widget)
4660 g_return_if_fail (widget != NULL);
4661 g_return_if_fail (GTK_IS_CLIST (widget));
4663 clist = GTK_CLIST (widget);
4665 if (!GTK_WIDGET_MAPPED (widget))
4667 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
4669 /* map column buttons */
4670 for (i = 0; i < clist->columns; i++)
4671 if (clist->column[i].button &&
4672 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
4673 !GTK_WIDGET_MAPPED (clist->column[i].button))
4674 gtk_widget_map (clist->column[i].button);
4676 for (i = 0; i < clist->columns; i++)
4677 if (clist->column[i].window && clist->column[i].button)
4679 gdk_window_raise (clist->column[i].window);
4680 gdk_window_show (clist->column[i].window);
4683 gdk_window_show (clist->title_window);
4684 gdk_window_show (clist->clist_window);
4685 gdk_window_show (widget->window);
4687 /* unfreeze the list */
4688 clist->freeze_count = 0;
4693 gtk_clist_unmap (GtkWidget *widget)
4698 g_return_if_fail (widget != NULL);
4699 g_return_if_fail (GTK_IS_CLIST (widget));
4701 clist = GTK_CLIST (widget);
4703 if (GTK_WIDGET_MAPPED (widget))
4705 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
4707 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4709 remove_grab (clist);
4711 if (clist->anchor != -1 &&
4712 clist->selection_mode == GTK_SELECTION_EXTENDED)
4713 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
4715 clist->click_cell.row = -1;
4716 clist->click_cell.column = -1;
4717 clist->drag_button = 0;
4719 if (GTK_CLIST_IN_DRAG(clist))
4723 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
4724 drag_data = gtk_object_get_data (GTK_OBJECT (clist),
4727 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
4732 for (i = 0; i < clist->columns; i++)
4733 if (clist->column[i].window)
4734 gdk_window_hide (clist->column[i].window);
4736 gdk_window_hide (clist->clist_window);
4737 gdk_window_hide (clist->title_window);
4738 gdk_window_hide (widget->window);
4740 /* unmap column buttons */
4741 for (i = 0; i < clist->columns; i++)
4742 if (clist->column[i].button &&
4743 GTK_WIDGET_MAPPED (clist->column[i].button))
4744 gtk_widget_unmap (clist->column[i].button);
4746 /* freeze the list */
4747 clist->freeze_count++;
4752 gtk_clist_draw (GtkWidget *widget,
4757 GdkRectangle child_area;
4760 g_return_if_fail (widget != NULL);
4761 g_return_if_fail (GTK_IS_CLIST (widget));
4762 g_return_if_fail (area != NULL);
4764 if (GTK_WIDGET_DRAWABLE (widget))
4766 clist = GTK_CLIST (widget);
4767 border_width = GTK_CONTAINER (widget)->border_width;
4769 gdk_window_clear_area (widget->window,
4770 area->x - border_width,
4771 area->y - border_width,
4772 area->width, area->height);
4774 /* draw list shadow/border */
4775 gtk_draw_shadow (widget->style, widget->window,
4776 GTK_STATE_NORMAL, clist->shadow_type,
4778 clist->clist_window_width +
4779 (2 * widget->style->klass->xthickness),
4780 clist->clist_window_height +
4781 (2 * widget->style->klass->ythickness) +
4782 clist->column_title_area.height);
4784 gdk_window_clear_area (clist->clist_window, 0, 0, -1, -1);
4785 draw_rows (clist, NULL);
4787 for (i = 0; i < clist->columns; i++)
4789 if (!clist->column[i].visible)
4791 if (clist->column[i].button &&
4792 gtk_widget_intersect(clist->column[i].button, area, &child_area))
4793 gtk_widget_draw (clist->column[i].button, &child_area);
4799 gtk_clist_expose (GtkWidget *widget,
4800 GdkEventExpose *event)
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_DRAWABLE (widget))
4810 clist = GTK_CLIST (widget);
4813 if (event->window == widget->window)
4814 gtk_draw_shadow (widget->style, widget->window,
4815 GTK_STATE_NORMAL, clist->shadow_type,
4817 clist->clist_window_width +
4818 (2 * widget->style->klass->xthickness),
4819 clist->clist_window_height +
4820 (2 * widget->style->klass->ythickness) +
4821 clist->column_title_area.height);
4823 /* exposure events on the list */
4824 if (event->window == clist->clist_window)
4825 draw_rows (clist, &event->area);
4832 gtk_clist_style_set (GtkWidget *widget,
4833 GtkStyle *previous_style)
4837 g_return_if_fail (widget != NULL);
4838 g_return_if_fail (GTK_IS_CLIST (widget));
4840 if (GTK_WIDGET_CLASS (parent_class)->style_set)
4841 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
4843 clist = GTK_CLIST (widget);
4845 if (GTK_WIDGET_REALIZED (widget))
4847 gtk_style_set_background (widget->style, widget->window, widget->state);
4848 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
4849 gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
4852 /* Fill in data after widget has correct style */
4854 /* text properties */
4855 if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
4857 clist->row_height = (widget->style->font->ascent +
4858 widget->style->font->descent + 1);
4859 clist->row_center_offset = widget->style->font->ascent + 1.5;
4862 clist->row_center_offset = 1.5 + (clist->row_height +
4863 widget->style->font->ascent -
4864 widget->style->font->descent - 1) / 2;
4867 if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
4872 for (i = 0; i < clist->columns; i++)
4873 if (clist->column[i].auto_resize)
4875 width = gtk_clist_optimal_column_width (clist, i);
4876 if (width != clist->column[i].width)
4877 gtk_clist_set_column_width (clist, i, width);
4883 gtk_clist_key_press (GtkWidget *widget,
4886 g_return_val_if_fail (widget != NULL, FALSE);
4887 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4888 g_return_val_if_fail (event != NULL, FALSE);
4890 if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
4891 GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
4894 switch (event->keyval)
4897 case GDK_ISO_Left_Tab:
4898 if (event->state & GDK_SHIFT_MASK)
4899 return gtk_container_focus (GTK_CONTAINER (widget),
4900 GTK_DIR_TAB_BACKWARD);
4902 return gtk_container_focus (GTK_CONTAINER (widget),
4903 GTK_DIR_TAB_FORWARD);
4911 gtk_clist_button_press (GtkWidget *widget,
4912 GdkEventButton *event)
4920 gint button_actions;
4922 g_return_val_if_fail (widget != NULL, FALSE);
4923 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
4924 g_return_val_if_fail (event != NULL, FALSE);
4926 clist = GTK_CLIST (widget);
4928 button_actions = clist->button_actions[event->button - 1];
4930 if (button_actions == GTK_BUTTON_IGNORED)
4933 /* selections on the list */
4934 if (event->window == clist->clist_window)
4939 if (get_selection_info (clist, x, y, &row, &column))
4941 gint old_row = clist->focus_row;
4943 if (clist->focus_row == -1)
4946 if (event->type == GDK_BUTTON_PRESS)
4948 GdkEventMask mask = ((1 << (4 + event->button)) |
4949 GDK_POINTER_MOTION_HINT_MASK |
4950 GDK_BUTTON_RELEASE_MASK);
4952 if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
4953 NULL, NULL, event->time))
4955 gtk_grab_add (widget);
4957 clist->click_cell.row = row;
4958 clist->click_cell.column = column;
4959 clist->drag_button = event->button;
4963 clist->click_cell.row = -1;
4964 clist->click_cell.column = -1;
4966 clist->drag_button = 0;
4967 remove_grab (clist);
4970 if (button_actions & GTK_BUTTON_SELECTS)
4972 if (GTK_CLIST_ADD_MODE(clist))
4974 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
4975 if (GTK_WIDGET_HAS_FOCUS(widget))
4977 gtk_clist_draw_focus (widget);
4978 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4979 GDK_LINE_SOLID, 0, 0);
4980 clist->focus_row = row;
4981 gtk_clist_draw_focus (widget);
4985 gdk_gc_set_line_attributes (clist->xor_gc, 1,
4986 GDK_LINE_SOLID, 0, 0);
4987 clist->focus_row = row;
4990 else if (row != clist->focus_row)
4992 if (GTK_WIDGET_HAS_FOCUS(widget))
4994 gtk_clist_draw_focus (widget);
4995 clist->focus_row = row;
4996 gtk_clist_draw_focus (widget);
4999 clist->focus_row = row;
5003 if (!GTK_WIDGET_HAS_FOCUS(widget))
5004 gtk_widget_grab_focus (widget);
5006 if (button_actions & GTK_BUTTON_SELECTS)
5008 switch (clist->selection_mode)
5010 case GTK_SELECTION_SINGLE:
5011 case GTK_SELECTION_MULTIPLE:
5012 if (event->type != GDK_BUTTON_PRESS)
5013 gtk_signal_emit (GTK_OBJECT (clist),
5014 clist_signals[SELECT_ROW],
5015 row, column, event);
5017 clist->anchor = row;
5019 case GTK_SELECTION_BROWSE:
5020 gtk_signal_emit (GTK_OBJECT (clist),
5021 clist_signals[SELECT_ROW],
5022 row, column, event);
5024 case GTK_SELECTION_EXTENDED:
5025 if (event->type != GDK_BUTTON_PRESS)
5027 if (clist->anchor != -1)
5029 update_extended_selection (clist, clist->focus_row);
5030 GTK_CLIST_CLASS_FW (clist)->resync_selection
5031 (clist, (GdkEvent *) event);
5033 gtk_signal_emit (GTK_OBJECT (clist),
5034 clist_signals[SELECT_ROW],
5035 row, column, event);
5039 if (event->state & GDK_CONTROL_MASK)
5041 if (event->state & GDK_SHIFT_MASK)
5043 if (clist->anchor < 0)
5045 g_list_free (clist->undo_selection);
5046 g_list_free (clist->undo_unselection);
5047 clist->undo_selection = NULL;
5048 clist->undo_unselection = NULL;
5049 clist->anchor = old_row;
5050 clist->drag_pos = old_row;
5051 clist->undo_anchor = old_row;
5053 update_extended_selection (clist, clist->focus_row);
5057 if (clist->anchor == -1)
5058 set_anchor (clist, TRUE, row, old_row);
5060 update_extended_selection (clist,
5066 if (event->state & GDK_SHIFT_MASK)
5068 set_anchor (clist, FALSE, old_row, old_row);
5069 update_extended_selection (clist, clist->focus_row);
5073 if (clist->anchor == -1)
5074 set_anchor (clist, FALSE, row, old_row);
5076 update_extended_selection (clist, clist->focus_row);
5086 /* press on resize windows */
5087 for (i = 0; i < clist->columns; i++)
5088 if (clist->column[i].resizeable && clist->column[i].window &&
5089 event->window == clist->column[i].window)
5093 if (gdk_pointer_grab (clist->column[i].window, FALSE,
5094 GDK_POINTER_MOTION_HINT_MASK |
5095 GDK_BUTTON1_MOTION_MASK |
5096 GDK_BUTTON_RELEASE_MASK,
5097 NULL, NULL, event->time))
5100 gtk_grab_add (widget);
5101 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
5103 /* block attached dnd signal handler */
5104 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5106 gtk_signal_handler_block_by_data (GTK_OBJECT (clist), drag_data);
5108 if (!GTK_WIDGET_HAS_FOCUS(widget))
5109 gtk_widget_grab_focus (widget);
5111 clist->drag_pos = i;
5112 clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
5113 clist->column[i].area.width + CELL_SPACING);
5115 if (GTK_CLIST_ADD_MODE(clist))
5116 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
5117 draw_xor_line (clist);
5123 gtk_clist_button_release (GtkWidget *widget,
5124 GdkEventButton *event)
5127 gint button_actions;
5129 g_return_val_if_fail (widget != NULL, FALSE);
5130 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5131 g_return_val_if_fail (event != NULL, FALSE);
5133 clist = GTK_CLIST (widget);
5135 button_actions = clist->button_actions[event->button - 1];
5136 if (button_actions == GTK_BUTTON_IGNORED)
5139 /* release on resize windows */
5140 if (GTK_CLIST_IN_DRAG(clist))
5147 i = clist->drag_pos;
5148 clist->drag_pos = -1;
5150 /* unblock attached dnd signal handler */
5151 drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
5153 gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
5155 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
5156 gtk_widget_get_pointer (widget, &x, NULL);
5157 gtk_grab_remove (widget);
5158 gdk_pointer_ungrab (event->time);
5160 if (clist->x_drag >= 0)
5161 draw_xor_line (clist);
5163 if (GTK_CLIST_ADD_MODE(clist))
5165 gdk_gc_set_line_attributes (clist->xor_gc, 1,
5166 GDK_LINE_ON_OFF_DASH, 0, 0);
5167 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
5170 width = new_column_width (clist, i, &x);
5171 gtk_clist_set_column_width (clist, i, width);
5175 if (clist->drag_button == event->button)
5180 clist->drag_button = 0;
5181 clist->click_cell.row = -1;
5182 clist->click_cell.column = -1;
5184 remove_grab (clist);
5186 if (button_actions & GTK_BUTTON_SELECTS)
5188 switch (clist->selection_mode)
5190 case GTK_SELECTION_EXTENDED:
5191 if (!(event->state & GDK_SHIFT_MASK) ||
5192 event->x < 0 || event->x >= clist->clist_window_width ||
5193 event->y < 0 || event->y >= clist->clist_window_height)
5194 GTK_CLIST_CLASS_FW (clist)->resync_selection
5195 (clist, (GdkEvent *) event);
5197 case GTK_SELECTION_SINGLE:
5198 case GTK_SELECTION_MULTIPLE:
5199 if (get_selection_info (clist, event->x, event->y,
5202 if (row >= 0 && row < clist->rows && clist->anchor == row)
5203 toggle_row (clist, row, column, (GdkEvent *) event);
5216 gtk_clist_motion (GtkWidget *widget,
5217 GdkEventMotion *event)
5224 gint button_actions = 0;
5226 g_return_val_if_fail (widget != NULL, FALSE);
5227 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
5229 clist = GTK_CLIST (widget);
5230 if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
5233 if (clist->drag_button > 0)
5234 button_actions = clist->button_actions[clist->drag_button - 1];
5236 if (GTK_CLIST_IN_DRAG(clist))
5238 if (event->is_hint || event->window != widget->window)
5239 gtk_widget_get_pointer (widget, &x, NULL);
5243 new_width = new_column_width (clist, clist->drag_pos, &x);
5244 if (x != clist->x_drag)
5246 /* x_drag < 0 indicates that the xor line is already invisible */
5247 if (clist->x_drag >= 0)
5248 draw_xor_line (clist);
5252 if (clist->x_drag >= 0)
5253 draw_xor_line (clist);
5256 if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
5257 clist->column[clist->drag_pos].min_width + 1))
5259 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
5260 gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
5263 if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
5264 new_width >= clist->column[clist->drag_pos].max_width)
5266 if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
5267 clist->clist_window_width && x < 0)
5268 move_horizontal (clist,
5269 COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
5270 new_width - clist->clist_window_width +
5271 COLUMN_INSET + CELL_SPACING);
5276 if (event->is_hint || event->window != clist->clist_window)
5277 gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
5279 if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
5281 /* delayed drag start */
5282 if (event->window == clist->clist_window &&
5283 clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
5284 (y < 0 || y >= clist->clist_window_height ||
5285 x < 0 || x >= clist->clist_window_width ||
5286 y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
5287 y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
5288 clist->row_height) ||
5289 x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
5290 x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) +
5291 clist->column[clist->click_cell.column].area.width)))
5293 GtkTargetList *target_list;
5295 target_list = gtk_target_list_new (&clist_target_table, 1);
5296 gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
5297 clist->drag_button, (GdkEvent *)event);
5303 /* horizontal autoscrolling */
5304 if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
5305 (x < 0 || x >= clist->clist_window_width))
5310 clist->htimer = gtk_timeout_add
5311 (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
5313 if (!((x < 0 && clist->hadjustment->value == 0) ||
5314 (x >= clist->clist_window_width &&
5315 clist->hadjustment->value ==
5316 LIST_WIDTH (clist) - clist->clist_window_width)))
5319 move_horizontal (clist, -1 + (x/2));
5321 move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
5325 if (GTK_CLIST_IN_DRAG(clist))
5328 /* vertical autoscrolling */
5329 row = ROW_FROM_YPIXEL (clist, y);
5331 /* don't scroll on last pixel row if it's a cell spacing */
5332 if (y == clist->clist_window_height - 1 &&
5333 y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
5336 if (LIST_HEIGHT (clist) > clist->clist_window_height &&
5337 (y < 0 || y >= clist->clist_window_height))
5342 clist->vtimer = gtk_timeout_add (SCROLL_TIME,
5343 (GtkFunction) vertical_timeout, clist);
5345 if (clist->drag_button &&
5346 ((y < 0 && clist->focus_row == 0) ||
5347 (y >= clist->clist_window_height &&
5348 clist->focus_row == clist->rows - 1)))
5352 row = CLAMP (row, 0, clist->rows - 1);
5354 if (button_actions & GTK_BUTTON_SELECTS &
5355 !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
5357 if (row == clist->focus_row)
5360 gtk_clist_draw_focus (widget);
5361 clist->focus_row = row;
5362 gtk_clist_draw_focus (widget);
5364 switch (clist->selection_mode)
5366 case GTK_SELECTION_BROWSE:
5367 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
5368 clist->focus_row, -1, event);
5370 case GTK_SELECTION_EXTENDED:
5371 update_extended_selection (clist, clist->focus_row);
5378 if (ROW_TOP_YPIXEL(clist, row) < 0)
5379 move_vertical (clist, row, 0);
5380 else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
5381 clist->clist_window_height)
5382 move_vertical (clist, row, 1);
5388 gtk_clist_size_request (GtkWidget *widget,
5389 GtkRequisition *requisition)
5394 g_return_if_fail (widget != NULL);
5395 g_return_if_fail (GTK_IS_CLIST (widget));
5396 g_return_if_fail (requisition != NULL);
5398 clist = GTK_CLIST (widget);
5400 requisition->width = 0;
5401 requisition->height = 0;
5403 /* compute the size of the column title (title) area */
5404 clist->column_title_area.height = 0;
5405 if (GTK_CLIST_SHOW_TITLES(clist))
5406 for (i = 0; i < clist->columns; i++)
5407 if (clist->column[i].button)
5409 GtkRequisition child_requisition;
5411 gtk_widget_size_request (clist->column[i].button,
5412 &child_requisition);
5413 clist->column_title_area.height =
5414 MAX (clist->column_title_area.height,
5415 child_requisition.height);
5418 requisition->width += (widget->style->klass->xthickness +
5419 GTK_CONTAINER (widget)->border_width) * 2;
5420 requisition->height += (clist->column_title_area.height +
5421 (widget->style->klass->ythickness +
5422 GTK_CONTAINER (widget)->border_width) * 2);
5424 /* if (!clist->hadjustment) */
5425 requisition->width += list_requisition_width (clist);
5426 /* if (!clist->vadjustment) */
5427 requisition->height += LIST_HEIGHT (clist);
5431 gtk_clist_size_allocate (GtkWidget *widget,
5432 GtkAllocation *allocation)
5435 GtkAllocation clist_allocation;
5438 g_return_if_fail (widget != NULL);
5439 g_return_if_fail (GTK_IS_CLIST (widget));
5440 g_return_if_fail (allocation != NULL);
5442 clist = GTK_CLIST (widget);
5443 widget->allocation = *allocation;
5444 border_width = GTK_CONTAINER (widget)->border_width;
5446 if (GTK_WIDGET_REALIZED (widget))
5448 gdk_window_move_resize (widget->window,
5449 allocation->x + border_width,
5450 allocation->y + border_width,
5451 allocation->width - border_width * 2,
5452 allocation->height - border_width * 2);
5455 /* use internal allocation structure for all the math
5456 * because it's easier than always subtracting the container
5458 clist->internal_allocation.x = 0;
5459 clist->internal_allocation.y = 0;
5460 clist->internal_allocation.width = MAX (1, (gint)allocation->width -
5462 clist->internal_allocation.height = MAX (1, (gint)allocation->height -
5465 /* allocate clist window assuming no scrollbars */
5466 clist_allocation.x = (clist->internal_allocation.x +
5467 widget->style->klass->xthickness);
5468 clist_allocation.y = (clist->internal_allocation.y +
5469 widget->style->klass->ythickness +
5470 clist->column_title_area.height);
5471 clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width -
5472 (2 * (gint)widget->style->klass->xthickness));
5473 clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
5474 (2 * (gint)widget->style->klass->ythickness) -
5475 (gint)clist->column_title_area.height);
5477 clist->clist_window_width = clist_allocation.width;
5478 clist->clist_window_height = clist_allocation.height;
5480 if (GTK_WIDGET_REALIZED (widget))
5482 gdk_window_move_resize (clist->clist_window,
5485 clist_allocation.width,
5486 clist_allocation.height);
5489 /* position the window which holds the column title buttons */
5490 clist->column_title_area.x = widget->style->klass->xthickness;
5491 clist->column_title_area.y = widget->style->klass->ythickness;
5492 clist->column_title_area.width = clist_allocation.width;
5494 if (GTK_WIDGET_REALIZED (widget))
5496 gdk_window_move_resize (clist->title_window,
5497 clist->column_title_area.x,
5498 clist->column_title_area.y,
5499 clist->column_title_area.width,
5500 clist->column_title_area.height);
5503 /* column button allocation */
5504 size_allocate_columns (clist, FALSE);
5505 size_allocate_title_buttons (clist);
5507 adjust_adjustments (clist, TRUE);
5514 gtk_clist_forall (GtkContainer *container,
5515 gboolean include_internals,
5516 GtkCallback callback,
5517 gpointer callback_data)
5522 g_return_if_fail (container != NULL);
5523 g_return_if_fail (GTK_IS_CLIST (container));
5524 g_return_if_fail (callback != NULL);
5526 if (!include_internals)
5529 clist = GTK_CLIST (container);
5531 /* callback for the column buttons */
5532 for (i = 0; i < clist->columns; i++)
5533 if (clist->column[i].button)
5534 (*callback) (clist->column[i].button, callback_data);
5537 /* PRIVATE DRAWING FUNCTIONS
5546 get_cell_style (GtkCList *clist,
5547 GtkCListRow *clist_row,
5556 if ((state == GTK_STATE_NORMAL) &&
5557 (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
5558 fg_state = GTK_STATE_INSENSITIVE;
5562 if (clist_row->cell[column].style)
5565 *style = clist_row->cell[column].style;
5567 *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
5569 if (state == GTK_STATE_SELECTED)
5570 *bg_gc = clist_row->cell[column].style->bg_gc[state];
5572 *bg_gc = clist_row->cell[column].style->base_gc[state];
5575 else if (clist_row->style)
5578 *style = clist_row->style;
5580 *fg_gc = clist_row->style->fg_gc[fg_state];
5582 if (state == GTK_STATE_SELECTED)
5583 *bg_gc = clist_row->style->bg_gc[state];
5585 *bg_gc = clist_row->style->base_gc[state];
5591 *style = GTK_WIDGET (clist)->style;
5593 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
5595 if (state == GTK_STATE_SELECTED)
5596 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
5598 *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
5601 if (state != GTK_STATE_SELECTED)
5603 if (fg_gc && clist_row->fg_set)
5604 *fg_gc = clist->fg_gc;
5605 if (bg_gc && clist_row->bg_set)
5606 *bg_gc = clist->bg_gc;
5612 draw_cell_pixmap (GdkWindow *window,
5613 GdkRectangle *clip_rectangle,
5627 gdk_gc_set_clip_mask (fg_gc, mask);
5628 gdk_gc_set_clip_origin (fg_gc, x, y);
5631 if (x < clip_rectangle->x)
5633 xsrc = clip_rectangle->x - x;
5635 x = clip_rectangle->x;
5637 if (x + width > clip_rectangle->x + clip_rectangle->width)
5638 width = clip_rectangle->x + clip_rectangle->width - x;
5640 if (y < clip_rectangle->y)
5642 ysrc = clip_rectangle->y - y;
5644 y = clip_rectangle->y;
5646 if (y + height > clip_rectangle->y + clip_rectangle->height)
5647 height = clip_rectangle->y + clip_rectangle->height - y;
5649 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
5650 gdk_gc_set_clip_origin (fg_gc, 0, 0);
5652 gdk_gc_set_clip_mask (fg_gc, NULL);
5654 return x + MAX (width, 0);
5658 draw_row (GtkCList *clist,
5661 GtkCListRow *clist_row)
5665 GdkRectangle row_rectangle;
5666 GdkRectangle cell_rectangle;
5667 GdkRectangle clip_rectangle;
5668 GdkRectangle intersect_rectangle;
5673 g_return_if_fail (clist != NULL);
5675 /* bail now if we arn't drawable yet */
5676 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
5679 widget = GTK_WIDGET (clist);
5681 /* if the function is passed the pointer to the row instead of null,
5682 * it avoids this expensive lookup */
5684 clist_row = (g_list_nth (clist->row_list, row))->data;
5686 /* rectangle of the entire row */
5687 row_rectangle.x = 0;
5688 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
5689 row_rectangle.width = clist->clist_window_width;
5690 row_rectangle.height = clist->row_height;
5692 /* rectangle of the cell spacing above the row */
5693 cell_rectangle.x = 0;
5694 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
5695 cell_rectangle.width = row_rectangle.width;
5696 cell_rectangle.height = CELL_SPACING;
5698 /* rectangle used to clip drawing operations, it's y and height
5699 * positions only need to be set once, so we set them once here.
5700 * the x and width are set withing the drawing loop below once per
5702 clip_rectangle.y = row_rectangle.y;
5703 clip_rectangle.height = row_rectangle.height;
5705 if (clist_row->state == GTK_STATE_NORMAL)
5707 if (clist_row->fg_set)
5708 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
5709 if (clist_row->bg_set)
5710 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
5713 state = clist_row->state;
5715 /* draw the cell borders and background */
5718 rect = &intersect_rectangle;
5719 if (gdk_rectangle_intersect (area, &cell_rectangle,
5720 &intersect_rectangle))
5721 gdk_draw_rectangle (clist->clist_window,
5722 widget->style->base_gc[GTK_STATE_ACTIVE],
5724 intersect_rectangle.x,
5725 intersect_rectangle.y,
5726 intersect_rectangle.width,
5727 intersect_rectangle.height);
5729 /* the last row has to clear it's bottom cell spacing too */
5730 if (clist_row == clist->row_list_end->data)
5732 cell_rectangle.y += clist->row_height + CELL_SPACING;
5734 if (gdk_rectangle_intersect (area, &cell_rectangle,
5735 &intersect_rectangle))
5736 gdk_draw_rectangle (clist->clist_window,
5737 widget->style->base_gc[GTK_STATE_ACTIVE],
5739 intersect_rectangle.x,
5740 intersect_rectangle.y,
5741 intersect_rectangle.width,
5742 intersect_rectangle.height);
5745 if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
5751 rect = &clip_rectangle;
5752 gdk_draw_rectangle (clist->clist_window,
5753 widget->style->base_gc[GTK_STATE_ACTIVE],
5757 cell_rectangle.width,
5758 cell_rectangle.height);
5760 /* the last row has to clear it's bottom cell spacing too */
5761 if (clist_row == clist->row_list_end->data)
5763 cell_rectangle.y += clist->row_height + CELL_SPACING;
5765 gdk_draw_rectangle (clist->clist_window,
5766 widget->style->base_gc[GTK_STATE_ACTIVE],
5770 cell_rectangle.width,
5771 cell_rectangle.height);
5775 for (last_column = clist->columns - 1;
5776 last_column >= 0 && !clist->column[last_column].visible; last_column--)
5779 /* iterate and draw all the columns (row cells) and draw their contents */
5780 for (i = 0; i < clist->columns; i++)
5790 gint row_center_offset;
5792 if (!clist->column[i].visible)
5795 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
5797 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
5798 clip_rectangle.width = clist->column[i].area.width;
5800 /* calculate clipping region clipping region */
5801 clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
5802 clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
5803 (i == last_column) * CELL_SPACING);
5805 if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
5806 &intersect_rectangle))
5809 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
5810 rect->x, rect->y, rect->width, rect->height);
5812 clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
5813 clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
5814 (i == last_column) * CELL_SPACING);
5816 /* calculate real width for column justification */
5819 switch (clist_row->cell[i].type)
5822 width = gdk_string_width (style->font,
5823 GTK_CELL_TEXT (clist_row->cell[i])->text);
5825 case GTK_CELL_PIXMAP:
5826 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5827 &pixmap_width, &height);
5828 width = pixmap_width;
5830 case GTK_CELL_PIXTEXT:
5831 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5832 &pixmap_width, &height);
5833 width = (pixmap_width +
5834 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
5835 gdk_string_width (style->font,
5837 (clist_row->cell[i])->text));
5844 switch (clist->column[i].justification)
5846 case GTK_JUSTIFY_LEFT:
5847 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
5849 case GTK_JUSTIFY_RIGHT:
5850 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5851 clip_rectangle.width - width);
5853 case GTK_JUSTIFY_CENTER:
5854 case GTK_JUSTIFY_FILL:
5855 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
5856 (clip_rectangle.width / 2) - (width / 2));
5860 /* Draw Text and/or Pixmap */
5861 switch (clist_row->cell[i].type)
5863 case GTK_CELL_PIXMAP:
5864 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5865 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
5866 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
5868 clip_rectangle.y + clist_row->cell[i].vertical +
5869 (clip_rectangle.height - height) / 2,
5870 pixmap_width, height);
5872 case GTK_CELL_PIXTEXT:
5874 draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
5875 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
5876 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
5878 clip_rectangle.y + clist_row->cell[i].vertical+
5879 (clip_rectangle.height - height) / 2,
5880 pixmap_width, height);
5881 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
5883 if (style != GTK_WIDGET (clist)->style)
5884 row_center_offset = (((clist->row_height - style->font->ascent -
5885 style->font->descent - 1) / 2) + 1.5 +
5886 style->font->ascent);
5888 row_center_offset = clist->row_center_offset;
5890 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
5891 gdk_draw_string (clist->clist_window, style->font, fg_gc,
5893 row_rectangle.y + row_center_offset +
5894 clist_row->cell[i].vertical,
5895 (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
5896 GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
5897 GTK_CELL_TEXT (clist_row->cell[i])->text);
5898 gdk_gc_set_clip_rectangle (fg_gc, NULL);
5905 /* draw focus rectangle */
5906 if (clist->focus_row == row &&
5907 GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
5910 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5911 row_rectangle.x, row_rectangle.y,
5912 row_rectangle.width - 1, row_rectangle.height - 1);
5913 else if (gdk_rectangle_intersect (area, &row_rectangle,
5914 &intersect_rectangle))
5916 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
5917 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
5918 row_rectangle.x, row_rectangle.y,
5919 row_rectangle.width - 1,
5920 row_rectangle.height - 1);
5921 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
5927 draw_rows (GtkCList *clist,
5931 GtkCListRow *clist_row;
5936 g_return_if_fail (clist != NULL);
5937 g_return_if_fail (GTK_IS_CLIST (clist));
5939 if (clist->row_height == 0 ||
5940 !GTK_WIDGET_DRAWABLE (clist))
5945 first_row = ROW_FROM_YPIXEL (clist, area->y);
5946 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
5950 first_row = ROW_FROM_YPIXEL (clist, 0);
5951 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
5954 /* this is a small special case which exposes the bottom cell line
5955 * on the last row -- it might go away if I change the wall the cell
5956 * spacings are drawn
5958 if (clist->rows == first_row)
5961 list = g_list_nth (clist->row_list, first_row);
5965 clist_row = list->data;
5971 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
5976 gdk_window_clear_area (clist->clist_window,
5977 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
5981 draw_xor_line (GtkCList *clist)
5985 g_return_if_fail (clist != NULL);
5987 widget = GTK_WIDGET (clist);
5989 gdk_draw_line (widget->window, clist->xor_gc,
5991 widget->style->klass->ythickness,
5993 clist->column_title_area.height +
5994 clist->clist_window_height + 1);
5998 clist_refresh (GtkCList *clist)
6000 g_return_if_fail (clist != NULL);
6001 g_return_if_fail (GTK_IS_CLIST (clist));
6003 if (CLIST_UNFROZEN (clist))
6005 adjust_adjustments (clist, FALSE);
6006 draw_rows (clist, NULL);
6010 /* get cell from coordinates
6011 * get_selection_info
6012 * gtk_clist_get_selection_info
6015 get_selection_info (GtkCList *clist,
6023 g_return_val_if_fail (clist != NULL, 0);
6024 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
6026 /* bounds checking, return false if the user clicked
6027 * on a blank area */
6028 trow = ROW_FROM_YPIXEL (clist, y);
6029 if (trow >= clist->rows)
6035 tcol = COLUMN_FROM_XPIXEL (clist, x);
6036 if (tcol >= clist->columns)
6046 gtk_clist_get_selection_info (GtkCList *clist,
6052 g_return_val_if_fail (clist != NULL, 0);
6053 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
6054 return get_selection_info (clist, x, y, row, column);
6057 /* PRIVATE ADJUSTMENT FUNCTIONS
6058 * adjust_adjustments
6059 * vadjustment_changed
6060 * hadjustment_changed
6061 * vadjustment_value_changed
6062 * hadjustment_value_changed
6066 adjust_adjustments (GtkCList *clist,
6067 gboolean block_resize)
6069 if (clist->vadjustment)
6071 clist->vadjustment->page_size = clist->clist_window_height;
6072 clist->vadjustment->page_increment = clist->clist_window_height / 2;
6073 clist->vadjustment->step_increment = clist->row_height;
6074 clist->vadjustment->lower = 0;
6075 clist->vadjustment->upper = LIST_HEIGHT (clist);
6077 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
6079 clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
6080 clist->clist_window_height));
6081 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
6084 gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
6087 if (clist->hadjustment)
6089 clist->hadjustment->page_size = clist->clist_window_width;
6090 clist->hadjustment->page_increment = clist->clist_window_width / 2;
6091 clist->hadjustment->step_increment = 10;
6092 clist->hadjustment->lower = 0;
6093 clist->hadjustment->upper = LIST_WIDTH (clist);
6095 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
6097 clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
6098 clist->clist_window_width));
6099 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
6102 gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
6105 if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
6108 GtkRequisition requisition;
6110 widget = GTK_WIDGET (clist);
6111 gtk_widget_size_request (widget, &requisition);
6113 if ((!clist->hadjustment &&
6114 requisition.width != widget->allocation.width) ||
6115 (!clist->vadjustment &&
6116 requisition.height != widget->allocation.height))
6117 gtk_widget_queue_resize (widget);
6122 vadjustment_changed (GtkAdjustment *adjustment,
6127 g_return_if_fail (adjustment != NULL);
6128 g_return_if_fail (data != NULL);
6130 clist = GTK_CLIST (data);
6134 hadjustment_changed (GtkAdjustment *adjustment,
6139 g_return_if_fail (adjustment != NULL);
6140 g_return_if_fail (data != NULL);
6142 clist = GTK_CLIST (data);
6146 vadjustment_value_changed (GtkAdjustment *adjustment,
6153 g_return_if_fail (adjustment != NULL);
6154 g_return_if_fail (data != NULL);
6155 g_return_if_fail (GTK_IS_CLIST (data));
6157 clist = GTK_CLIST (data);
6159 if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->vadjustment)
6162 value = adjustment->value;
6164 if (value > -clist->voffset)
6167 diff = value + clist->voffset;
6169 /* we have to re-draw the whole screen here... */
6170 if (diff >= clist->clist_window_height)
6172 clist->voffset = -value;
6173 draw_rows (clist, NULL);
6177 if ((diff != 0) && (diff != clist->clist_window_height))
6178 gdk_window_copy_area (clist->clist_window, clist->fg_gc,
6179 0, 0, clist->clist_window, 0, diff,
6180 clist->clist_window_width,
6181 clist->clist_window_height - diff);
6184 area.y = clist->clist_window_height - diff;
6185 area.width = clist->clist_window_width;
6191 diff = -clist->voffset - value;
6193 /* we have to re-draw the whole screen here... */
6194 if (diff >= clist->clist_window_height)
6196 clist->voffset = -value;
6197 draw_rows (clist, NULL);
6201 if ((diff != 0) && (diff != clist->clist_window_height))
6202 gdk_window_copy_area (clist->clist_window, clist->fg_gc,
6203 0, diff, clist->clist_window, 0, 0,
6204 clist->clist_window_width,
6205 clist->clist_window_height - diff);
6209 area.width = clist->clist_window_width;
6213 clist->voffset = -value;
6214 if ((diff != 0) && (diff != clist->clist_window_height))
6215 check_exposures (clist);
6217 draw_rows (clist, &area);
6221 hadjustment_value_changed (GtkAdjustment *adjustment,
6231 g_return_if_fail (adjustment != NULL);
6232 g_return_if_fail (data != NULL);
6233 g_return_if_fail (GTK_IS_CLIST (data));
6235 clist = GTK_CLIST (data);
6237 if (!GTK_WIDGET_DRAWABLE (clist) || adjustment != clist->hadjustment)
6240 value = adjustment->value;
6242 /* move the column buttons and resize windows */
6243 for (i = 0; i < clist->columns; i++)
6245 if (clist->column[i].button)
6247 clist->column[i].button->allocation.x -= value + clist->hoffset;
6249 if (clist->column[i].button->window)
6251 gdk_window_move (clist->column[i].button->window,
6252 clist->column[i].button->allocation.x,
6253 clist->column[i].button->allocation.y);
6255 if (clist->column[i].window)
6256 gdk_window_move (clist->column[i].window,
6257 clist->column[i].button->allocation.x +
6258 clist->column[i].button->allocation.width -
6259 (DRAG_WIDTH / 2), 0);
6264 if (value > -clist->hoffset)
6267 diff = value + clist->hoffset;
6269 clist->hoffset = -value;
6271 /* we have to re-draw the whole screen here... */
6272 if (diff >= clist->clist_window_width)
6274 draw_rows (clist, NULL);
6278 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6279 !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
6281 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6283 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
6284 clist->clist_window_width - 1,
6285 clist->row_height - 1);
6287 gdk_window_copy_area (clist->clist_window,
6290 clist->clist_window,
6293 clist->clist_window_width - diff,
6294 clist->clist_window_height);
6296 area.x = clist->clist_window_width - diff;
6301 if (!(diff = -clist->hoffset - value))
6304 clist->hoffset = -value;
6306 /* we have to re-draw the whole screen here... */
6307 if (diff >= clist->clist_window_width)
6309 draw_rows (clist, NULL);
6313 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6314 !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
6316 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6318 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
6319 clist->clist_window_width - 1,
6320 clist->row_height - 1);
6323 gdk_window_copy_area (clist->clist_window,
6326 clist->clist_window,
6329 clist->clist_window_width - diff,
6330 clist->clist_window_height);
6337 area.height = clist->clist_window_height;
6339 check_exposures (clist);
6341 if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
6342 !GTK_CLIST_CHILD_HAS_FOCUS(clist))
6344 if (GTK_CLIST_ADD_MODE(clist))
6348 focus_row = clist->focus_row;
6349 clist->focus_row = -1;
6350 draw_rows (clist, &area);
6351 clist->focus_row = focus_row;
6353 gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
6354 FALSE, 0, y, clist->clist_window_width - 1,
6355 clist->row_height - 1);
6365 x0 = clist->clist_window_width - 1;
6374 y = ROW_TOP_YPIXEL (clist, clist->focus_row);
6375 gdk_draw_line (clist->clist_window, clist->xor_gc,
6376 x0, y + 1, x0, y + clist->row_height - 2);
6377 gdk_draw_line (clist->clist_window, clist->xor_gc,
6378 x1, y + 1, x1, y + clist->row_height - 2);
6382 draw_rows (clist, &area);
6386 check_exposures (GtkCList *clist)
6390 if (!GTK_WIDGET_REALIZED (clist))
6393 /* Make sure graphics expose events are processed before scrolling
6395 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
6397 gtk_widget_event (GTK_WIDGET (clist), event);
6398 if (event->expose.count == 0)
6400 gdk_event_free (event);
6403 gdk_event_free (event);
6408 * Memory Allocation/Distruction Routines for GtkCList stuctures
6417 static GtkCListColumn *
6418 columns_new (GtkCList *clist)
6420 GtkCListColumn *column;
6423 column = g_new (GtkCListColumn, clist->columns);
6425 for (i = 0; i < clist->columns; i++)
6427 column[i].area.x = 0;
6428 column[i].area.y = 0;
6429 column[i].area.width = 0;
6430 column[i].area.height = 0;
6431 column[i].title = NULL;
6432 column[i].button = NULL;
6433 column[i].window = NULL;
6434 column[i].width = 0;
6435 column[i].min_width = -1;
6436 column[i].max_width = -1;
6437 column[i].visible = TRUE;
6438 column[i].width_set = FALSE;
6439 column[i].resizeable = TRUE;
6440 column[i].auto_resize = FALSE;
6441 column[i].button_passive = FALSE;
6442 column[i].justification = GTK_JUSTIFY_LEFT;
6449 column_title_new (GtkCList *clist,
6453 if (clist->column[column].title)
6454 g_free (clist->column[column].title);
6456 clist->column[column].title = g_strdup (title);
6460 columns_delete (GtkCList *clist)
6464 for (i = 0; i < clist->columns; i++)
6465 if (clist->column[i].title)
6466 g_free (clist->column[i].title);
6468 g_free (clist->column);
6471 static GtkCListRow *
6472 row_new (GtkCList *clist)
6475 GtkCListRow *clist_row;
6477 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
6478 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
6480 for (i = 0; i < clist->columns; i++)
6482 clist_row->cell[i].type = GTK_CELL_EMPTY;
6483 clist_row->cell[i].vertical = 0;
6484 clist_row->cell[i].horizontal = 0;
6485 clist_row->cell[i].style = NULL;
6488 clist_row->fg_set = FALSE;
6489 clist_row->bg_set = FALSE;
6490 clist_row->style = NULL;
6491 clist_row->selectable = TRUE;
6492 clist_row->state = GTK_STATE_NORMAL;
6493 clist_row->data = NULL;
6494 clist_row->destroy = NULL;
6500 row_delete (GtkCList *clist,
6501 GtkCListRow *clist_row)
6505 for (i = 0; i < clist->columns; i++)
6507 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
6508 (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
6509 if (clist_row->cell[i].style)
6511 if (GTK_WIDGET_REALIZED (clist))
6512 gtk_style_detach (clist_row->cell[i].style);
6513 gtk_style_unref (clist_row->cell[i].style);
6517 if (clist_row->style)
6519 if (GTK_WIDGET_REALIZED (clist))
6520 gtk_style_detach (clist_row->style);
6521 gtk_style_unref (clist_row->style);
6524 if (clist_row->destroy)
6525 clist_row->destroy (clist_row->data);
6527 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
6528 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
6533 * gtk_clist_draw_focus
6534 * gtk_clist_focus_in
6535 * gtk_clist_focus_out
6536 * gtk_clist_set_focus_child
6540 gtk_clist_focus (GtkContainer *container,
6541 GtkDirectionType direction)
6544 GtkWidget *focus_child;
6547 g_return_val_if_fail (container != NULL, FALSE);
6548 g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
6550 if (!GTK_WIDGET_IS_SENSITIVE (container))
6553 clist = GTK_CLIST (container);
6554 focus_child = container->focus_child;
6555 old_row = clist->focus_row;
6561 if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
6563 if (title_focus (clist, direction))
6565 gtk_container_set_focus_child (container, NULL);
6568 gtk_widget_grab_focus (GTK_WIDGET (container));
6571 case GTK_DIR_TAB_FORWARD:
6572 if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
6574 gboolean tf = FALSE;
6576 if (((focus_child && direction == GTK_DIR_DOWN) ||
6577 !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
6580 if (clist->focus_row < 0)
6582 clist->focus_row = 0;
6584 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
6585 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
6587 gtk_signal_emit (GTK_OBJECT (clist),
6588 clist_signals[SELECT_ROW],
6589 clist->focus_row, -1, NULL);
6591 gtk_widget_grab_focus (GTK_WIDGET (container));
6599 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
6602 case GTK_DIR_TAB_BACKWARD:
6604 GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows)
6606 if (clist->focus_row < 0)
6608 clist->focus_row = 0;
6609 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
6610 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
6612 gtk_signal_emit (GTK_OBJECT (clist),
6613 clist_signals[SELECT_ROW],
6614 clist->focus_row, -1, NULL);
6616 gtk_widget_grab_focus (GTK_WIDGET (container));
6620 GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
6622 if (title_focus (clist, direction))
6630 gtk_container_set_focus_child (container, NULL);
6635 gtk_clist_draw_focus (GtkWidget *widget)
6639 g_return_if_fail (widget != NULL);
6640 g_return_if_fail (GTK_IS_CLIST (widget));
6642 if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
6645 clist = GTK_CLIST (widget);
6646 if (clist->focus_row >= 0)
6647 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
6648 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
6649 clist->clist_window_width - 1,
6650 clist->row_height - 1);
6654 gtk_clist_focus_in (GtkWidget *widget,
6655 GdkEventFocus *event)
6659 g_return_val_if_fail (widget != NULL, FALSE);
6660 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
6661 g_return_val_if_fail (event != NULL, FALSE);
6663 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
6664 GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
6666 clist = GTK_CLIST (widget);
6668 if (clist->selection_mode == GTK_SELECTION_BROWSE &&
6669 clist->selection == NULL && clist->focus_row > -1)
6673 list = g_list_nth (clist->row_list, clist->focus_row);
6674 if (list && GTK_CLIST_ROW (list)->selectable)
6675 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
6676 clist->focus_row, -1, event);
6678 gtk_widget_draw_focus (widget);
6681 gtk_widget_draw_focus (widget);
6687 gtk_clist_focus_out (GtkWidget *widget,
6688 GdkEventFocus *event)
6692 g_return_val_if_fail (widget != NULL, FALSE);
6693 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
6694 g_return_val_if_fail (event != NULL, FALSE);
6696 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
6697 GTK_CLIST_SET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
6699 gtk_widget_draw_focus (widget);
6701 clist = GTK_CLIST (widget);
6703 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
6704 GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
6710 gtk_clist_set_focus_child (GtkContainer *container,
6713 g_return_if_fail (container != NULL);
6714 g_return_if_fail (GTK_IS_CLIST (container));
6718 g_return_if_fail (GTK_IS_WIDGET (child));
6719 GTK_CLIST_SET_FLAG (container, CLIST_CHILD_HAS_FOCUS);
6722 parent_class->set_focus_child (container, child);
6726 title_focus (GtkCList *clist,
6729 GtkWidget *focus_child;
6730 gboolean return_val = FALSE;
6736 if (!GTK_CLIST_SHOW_TITLES(clist))
6739 focus_child = GTK_CONTAINER (clist)->focus_child;
6741 for (last_column = clist->columns - 1;
6742 last_column >= 0 && !clist->column[last_column].visible; last_column--)
6747 case GTK_DIR_TAB_BACKWARD:
6749 if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist))
6751 if (dir == GTK_DIR_UP)
6752 i = COLUMN_FROM_XPIXEL (clist, 0);
6755 focus_child = clist->column[i].button;
6756 dir = GTK_DIR_TAB_FORWARD;
6766 focus_child = clist->column[i].button;
6773 focus_child = clist->column[i].button;
6779 while (i < clist->columns)
6781 if (clist->column[i].button == focus_child)
6783 if (clist->column[i].button &&
6784 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
6785 GTK_IS_CONTAINER (clist->column[i].button) &&
6786 !GTK_WIDGET_HAS_FOCUS(clist->column[i].button))
6787 if (gtk_container_focus
6788 (GTK_CONTAINER (clist->column[i].button), dir))
6793 if (!return_val && dir == GTK_DIR_UP)
6804 while (j >= 0 && j < clist->columns)
6806 if (clist->column[j].button &&
6807 GTK_WIDGET_VISIBLE (clist->column[j].button))
6809 if (GTK_IS_CONTAINER (clist->column[j].button) &&
6811 (GTK_CONTAINER (clist->column[j].button), dir))
6816 else if (GTK_WIDGET_CAN_FOCUS (clist->column[j].button))
6818 gtk_widget_grab_focus (clist->column[j].button);
6828 if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
6829 gtk_clist_moveto (clist, -1, j, 0, 0);
6830 else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
6831 clist->clist_window_width)
6833 if (j == last_column)
6834 gtk_clist_moveto (clist, -1, j, 0, 0);
6836 gtk_clist_moveto (clist, -1, j, 0, 1);
6842 /* PRIVATE SCROLLING FUNCTIONS
6848 * horizontal_timeout
6853 move_focus_row (GtkCList *clist,
6854 GtkScrollType scroll_type,
6859 g_return_if_fail (clist != 0);
6860 g_return_if_fail (GTK_IS_CLIST (clist));
6862 widget = GTK_WIDGET (clist);
6864 switch (scroll_type)
6866 case GTK_SCROLL_STEP_BACKWARD:
6867 if (clist->focus_row <= 0)
6869 gtk_clist_draw_focus (widget);
6871 gtk_clist_draw_focus (widget);
6873 case GTK_SCROLL_STEP_FORWARD:
6874 if (clist->focus_row >= clist->rows - 1)
6876 gtk_clist_draw_focus (widget);
6878 gtk_clist_draw_focus (widget);
6880 case GTK_SCROLL_PAGE_BACKWARD:
6881 if (clist->focus_row <= 0)
6883 gtk_clist_draw_focus (widget);
6884 clist->focus_row = MAX (0, clist->focus_row -
6885 (2 * clist->clist_window_height -
6886 clist->row_height - CELL_SPACING) /
6887 (2 * (clist->row_height + CELL_SPACING)));
6888 gtk_clist_draw_focus (widget);
6890 case GTK_SCROLL_PAGE_FORWARD:
6891 if (clist->focus_row >= clist->rows - 1)
6893 gtk_clist_draw_focus (widget);
6894 clist->focus_row = MIN (clist->rows - 1, clist->focus_row +
6895 (2 * clist->clist_window_height -
6896 clist->row_height - CELL_SPACING) /
6897 (2 * (clist->row_height + CELL_SPACING)));
6898 gtk_clist_draw_focus (widget);
6900 case GTK_SCROLL_JUMP:
6901 if (position >= 0 && position <= 1)
6903 gtk_clist_draw_focus (widget);
6904 clist->focus_row = position * (clist->rows - 1);
6905 gtk_clist_draw_focus (widget);
6914 scroll_horizontal (GtkCList *clist,
6915 GtkScrollType scroll_type,
6921 g_return_if_fail (clist != 0);
6922 g_return_if_fail (GTK_IS_CLIST (clist));
6924 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
6927 for (last_column = clist->columns - 1;
6928 last_column >= 0 && !clist->column[last_column].visible; last_column--)
6931 switch (scroll_type)
6933 case GTK_SCROLL_STEP_BACKWARD:
6934 column = COLUMN_FROM_XPIXEL (clist, 0);
6935 if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
6939 case GTK_SCROLL_STEP_FORWARD:
6940 column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
6943 if (COLUMN_LEFT_XPIXEL (clist, column) +
6944 clist->column[column].area.width +
6945 CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
6946 column < last_column)
6949 case GTK_SCROLL_PAGE_BACKWARD:
6950 case GTK_SCROLL_PAGE_FORWARD:
6952 case GTK_SCROLL_JUMP:
6953 if (position >= 0 && position <= 1)
6955 gint vis_columns = 0;
6958 for (i = 0; i <= last_column; i++)
6959 if (clist->column[i].visible)
6962 column = position * vis_columns;
6964 for (i = 0; i <= last_column && column > 0; i++)
6965 if (clist->column[i].visible)
6977 if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
6978 gtk_clist_moveto (clist, -1, column, 0, 0);
6979 else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
6980 + clist->column[column].area.width > clist->clist_window_width)
6982 if (column == last_column)
6983 gtk_clist_moveto (clist, -1, column, 0, 0);
6985 gtk_clist_moveto (clist, -1, column, 0, 1);
6990 scroll_vertical (GtkCList *clist,
6991 GtkScrollType scroll_type,
6996 g_return_if_fail (clist != NULL);
6997 g_return_if_fail (GTK_IS_CLIST (clist));
6999 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
7002 switch (clist->selection_mode)
7004 case GTK_SELECTION_EXTENDED:
7005 if (clist->anchor >= 0)
7007 case GTK_SELECTION_BROWSE:
7009 old_focus_row = clist->focus_row;
7010 move_focus_row (clist, scroll_type, position);
7012 if (old_focus_row != clist->focus_row)
7014 if (clist->selection_mode == GTK_SELECTION_BROWSE)
7015 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
7016 old_focus_row, -1, NULL);
7017 else if (!GTK_CLIST_ADD_MODE(clist))
7019 gtk_clist_unselect_all (clist);
7020 clist->undo_anchor = old_focus_row;
7024 switch (gtk_clist_row_is_visible (clist, clist->focus_row))
7026 case GTK_VISIBILITY_NONE:
7027 if (old_focus_row != clist->focus_row &&
7028 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
7029 GTK_CLIST_ADD_MODE(clist)))
7030 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
7031 clist->focus_row, -1, NULL);
7032 switch (scroll_type)
7034 case GTK_SCROLL_STEP_BACKWARD:
7035 case GTK_SCROLL_PAGE_BACKWARD:
7036 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
7038 case GTK_SCROLL_STEP_FORWARD:
7039 case GTK_SCROLL_PAGE_FORWARD:
7040 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
7042 case GTK_SCROLL_JUMP:
7043 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
7049 case GTK_VISIBILITY_PARTIAL:
7050 switch (scroll_type)
7052 case GTK_SCROLL_STEP_BACKWARD:
7053 case GTK_SCROLL_PAGE_BACKWARD:
7054 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
7056 case GTK_SCROLL_STEP_FORWARD:
7057 case GTK_SCROLL_PAGE_FORWARD:
7058 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
7060 case GTK_SCROLL_JUMP:
7061 gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
7067 if (old_focus_row != clist->focus_row &&
7068 !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
7069 GTK_CLIST_ADD_MODE(clist)))
7070 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
7071 clist->focus_row, -1, NULL);
7076 move_focus_row (clist, scroll_type, position);
7078 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
7079 clist->clist_window_height)
7080 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
7081 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
7082 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
7088 move_horizontal (GtkCList *clist,
7093 if (!clist->hadjustment)
7096 value = CLAMP (clist->hadjustment->value + diff, 0.0,
7097 clist->hadjustment->upper - clist->hadjustment->page_size);
7098 gtk_adjustment_set_value(clist->hadjustment, value);
7102 move_vertical (GtkCList *clist,
7108 if (!clist->vadjustment)
7111 value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
7112 align * (clist->clist_window_height - clist->row_height) +
7113 (2 * align - 1) * CELL_SPACING);
7115 if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
7116 value = clist->vadjustment->upper - clist->vadjustment->page_size;
7118 gtk_adjustment_set_value(clist->vadjustment, value);
7122 horizontal_timeout (GtkCList *clist)
7125 GdkEventMotion event;
7126 GdkModifierType mask;
7128 GDK_THREADS_ENTER ();
7131 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
7138 gtk_clist_motion (GTK_WIDGET (clist), &event);
7140 GDK_THREADS_LEAVE ();
7146 vertical_timeout (GtkCList *clist)
7149 GdkEventMotion event;
7150 GdkModifierType mask;
7152 GDK_THREADS_ENTER ();
7155 gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
7162 gtk_clist_motion (GTK_WIDGET (clist), &event);
7164 GDK_THREADS_LEAVE ();
7170 remove_grab (GtkCList *clist)
7172 if (GTK_WIDGET_HAS_GRAB (clist))
7174 gtk_grab_remove (GTK_WIDGET (clist));
7175 if (gdk_pointer_is_grabbed ())
7176 gdk_pointer_ungrab (GDK_CURRENT_TIME);
7181 gtk_timeout_remove (clist->htimer);
7187 gtk_timeout_remove (clist->vtimer);
7192 /* PUBLIC SORTING FUNCTIONS
7194 * gtk_clist_set_compare_func
7195 * gtk_clist_set_auto_sort
7196 * gtk_clist_set_sort_type
7197 * gtk_clist_set_sort_column
7200 gtk_clist_sort (GtkCList *clist)
7202 g_return_if_fail (clist != NULL);
7203 g_return_if_fail (GTK_IS_CLIST (clist));
7205 GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
7209 gtk_clist_set_compare_func (GtkCList *clist,
7210 GtkCListCompareFunc cmp_func)
7212 g_return_if_fail (clist != NULL);
7213 g_return_if_fail (GTK_IS_CLIST (clist));
7215 clist->compare = (cmp_func) ? cmp_func : default_compare;
7219 gtk_clist_set_auto_sort (GtkCList *clist,
7222 g_return_if_fail (clist != NULL);
7223 g_return_if_fail (GTK_IS_CLIST (clist));
7225 if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
7226 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
7227 else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
7229 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
7230 gtk_clist_sort (clist);
7235 gtk_clist_set_sort_type (GtkCList *clist,
7236 GtkSortType sort_type)
7238 g_return_if_fail (clist != NULL);
7239 g_return_if_fail (GTK_IS_CLIST (clist));
7241 clist->sort_type = sort_type;
7245 gtk_clist_set_sort_column (GtkCList *clist,
7248 g_return_if_fail (clist != NULL);
7249 g_return_if_fail (GTK_IS_CLIST (clist));
7251 if (column < 0 || column >= clist->columns)
7254 clist->sort_column = column;
7257 /* PRIVATE SORTING FUNCTIONS
7261 * gtk_clist_mergesort
7264 default_compare (GtkCList *clist,
7271 GtkCListRow *row1 = (GtkCListRow *) ptr1;
7272 GtkCListRow *row2 = (GtkCListRow *) ptr2;
7274 switch (row1->cell[clist->sort_column].type)
7277 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
7279 case GTK_CELL_PIXTEXT:
7280 text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
7286 switch (row2->cell[clist->sort_column].type)
7289 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
7291 case GTK_CELL_PIXTEXT:
7292 text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
7299 return (text1 != NULL);
7304 return strcmp (text1, text2);
7308 real_sort_list (GtkCList *clist)
7314 g_return_if_fail (clist != NULL);
7315 g_return_if_fail (GTK_IS_CLIST (clist));
7317 if (clist->rows <= 1)
7320 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
7323 gtk_clist_freeze (clist);
7325 if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
7327 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7328 g_list_free (clist->undo_selection);
7329 g_list_free (clist->undo_unselection);
7330 clist->undo_selection = NULL;
7331 clist->undo_unselection = NULL;
7334 clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
7336 work = clist->selection;
7338 for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
7340 if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
7342 work->data = GINT_TO_POINTER (i);
7346 if (i == clist->rows - 1)
7347 clist->row_list_end = list;
7350 gtk_clist_thaw (clist);
7354 gtk_clist_merge (GtkCList *clist,
7355 GList *a, /* first list to merge */
7356 GList *b) /* second list to merge */
7358 GList z = { 0 }; /* auxiliary node */
7384 cmp = clist->compare (clist, GTK_CLIST_ROW (a), GTK_CLIST_ROW (b));
7385 if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
7386 (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
7408 gtk_clist_mergesort (GtkCList *clist,
7409 GList *list, /* the list to sort */
7410 gint num) /* the list's length */
7421 /* move "half" to the middle */
7423 for (i = 0; i < num / 2; i++)
7426 /* cut the list in two */
7427 half->prev->next = NULL;
7430 /* recursively sort both lists */
7431 return gtk_clist_merge (clist,
7432 gtk_clist_mergesort (clist, list, num / 2),
7433 gtk_clist_mergesort (clist, half, num - num / 2));
7437 /************************/
7440 drag_source_info_destroy (gpointer data)
7442 GtkCListCellInfo *info = data;
7448 drag_dest_info_destroy (gpointer data)
7450 GtkCListDestInfo *info = data;
7456 gtk_clist_drag_begin (GtkWidget *widget,
7457 GdkDragContext *context)
7460 GtkCListCellInfo *info;
7462 g_return_if_fail (widget != NULL);
7463 g_return_if_fail (GTK_IS_CLIST (widget));
7464 g_return_if_fail (context != NULL);
7466 clist = GTK_CLIST (widget);
7468 clist->drag_button = 0;
7469 remove_grab (clist);
7471 switch (clist->selection_mode)
7473 case GTK_SELECTION_EXTENDED:
7474 update_extended_selection (clist, clist->focus_row);
7475 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7477 case GTK_SELECTION_SINGLE:
7478 case GTK_SELECTION_MULTIPLE:
7480 case GTK_SELECTION_BROWSE:
7484 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7488 info = g_new (GtkCListCellInfo, 1);
7490 if (clist->click_cell.row < 0)
7491 clist->click_cell.row = 0;
7492 else if (clist->click_cell.row >= clist->rows)
7493 clist->click_cell.row = clist->rows - 1;
7494 info->row = clist->click_cell.row;
7495 info->column = clist->click_cell.column;
7497 g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
7498 drag_source_info_destroy);
7501 if (GTK_CLIST_USE_DRAG_ICONS (clist))
7502 gtk_drag_set_icon_default (context);
7506 gtk_clist_drag_end (GtkWidget *widget,
7507 GdkDragContext *context)
7511 g_return_if_fail (widget != NULL);
7512 g_return_if_fail (GTK_IS_CLIST (widget));
7513 g_return_if_fail (context != NULL);
7515 clist = GTK_CLIST (widget);
7517 clist->click_cell.row = -1;
7518 clist->click_cell.column = -1;
7522 gtk_clist_drag_leave (GtkWidget *widget,
7523 GdkDragContext *context,
7527 GtkCListDestInfo *dest_info;
7529 g_return_if_fail (widget != NULL);
7530 g_return_if_fail (GTK_IS_CLIST (widget));
7531 g_return_if_fail (context != NULL);
7533 clist = GTK_CLIST (widget);
7535 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7539 if (dest_info->cell.row >= 0 &&
7540 GTK_CLIST_REORDERABLE(clist) &&
7541 gtk_drag_get_source_widget (context) == widget)
7544 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7546 list = context->targets;
7549 if (atom == GPOINTER_TO_INT (list->data))
7551 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7553 g_list_nth (clist->row_list, dest_info->cell.row)->data,
7554 dest_info->cell.row, dest_info->insert_pos);
7560 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7565 gtk_clist_drag_motion (GtkWidget *widget,
7566 GdkDragContext *context,
7573 GtkCListDestInfo *dest_info;
7575 gint insert_pos = GTK_CLIST_DRAG_NONE;
7578 g_return_val_if_fail (widget != NULL, FALSE);
7579 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7581 clist = GTK_CLIST (widget);
7583 y -= (GTK_CONTAINER (widget)->border_width +
7584 widget->style->klass->ythickness + clist->column_title_area.height);
7585 row = ROW_FROM_YPIXEL (clist, y);
7587 if (row >= clist->rows)
7589 row = clist->rows - 1;
7590 y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
7595 x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
7596 column = COLUMN_FROM_XPIXEL (clist, x);
7600 y_delta = y - ROW_TOP_YPIXEL (clist, row);
7602 if (GTK_CLIST_DRAW_DRAG_RECT(clist))
7604 insert_pos = GTK_CLIST_DRAG_INTO;
7605 h = clist->row_height / 4;
7607 else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7609 insert_pos = GTK_CLIST_DRAG_BEFORE;
7610 h = clist->row_height / 2;
7613 if (GTK_CLIST_DRAW_DRAG_LINE(clist))
7616 insert_pos = GTK_CLIST_DRAG_BEFORE;
7617 else if (clist->row_height - y_delta < h)
7618 insert_pos = GTK_CLIST_DRAG_AFTER;
7622 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7626 dest_info = g_new (GtkCListDestInfo, 1);
7628 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
7629 dest_info->cell.row = -1;
7630 dest_info->cell.column = -1;
7632 g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
7633 drag_dest_info_destroy);
7636 if (GTK_CLIST_REORDERABLE (clist))
7639 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7641 list = context->targets;
7644 if (atom == GPOINTER_TO_INT (list->data))
7651 if (gtk_drag_get_source_widget (context) != widget ||
7652 insert_pos == GTK_CLIST_DRAG_NONE ||
7653 row == clist->click_cell.row ||
7654 (row == clist->click_cell.row - 1 &&
7655 insert_pos == GTK_CLIST_DRAG_AFTER) ||
7656 (row == clist->click_cell.row + 1 &&
7657 insert_pos == GTK_CLIST_DRAG_BEFORE))
7659 if (dest_info->cell.row < 0)
7661 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
7667 if (row != dest_info->cell.row ||
7668 (row == dest_info->cell.row &&
7669 dest_info->insert_pos != insert_pos))
7671 if (dest_info->cell.row >= 0)
7672 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7673 (clist, g_list_nth (clist->row_list,
7674 dest_info->cell.row)->data,
7675 dest_info->cell.row, dest_info->insert_pos);
7677 dest_info->insert_pos = insert_pos;
7678 dest_info->cell.row = row;
7679 dest_info->cell.column = column;
7681 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
7682 (clist, g_list_nth (clist->row_list,
7683 dest_info->cell.row)->data,
7684 dest_info->cell.row, dest_info->insert_pos);
7686 gdk_drag_status (context, context->suggested_action, time);
7692 dest_info->insert_pos = insert_pos;
7693 dest_info->cell.row = row;
7694 dest_info->cell.column = column;
7699 gtk_clist_drag_drop (GtkWidget *widget,
7700 GdkDragContext *context,
7705 g_return_val_if_fail (widget != NULL, FALSE);
7706 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
7707 g_return_val_if_fail (context != NULL, FALSE);
7709 if (GTK_CLIST_REORDERABLE (widget) &&
7710 gtk_drag_get_source_widget (context) == widget)
7713 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
7715 list = context->targets;
7718 if (atom == GPOINTER_TO_INT (list->data))
7727 gtk_clist_drag_data_received (GtkWidget *widget,
7728 GdkDragContext *context,
7731 GtkSelectionData *selection_data,
7737 g_return_if_fail (widget != NULL);
7738 g_return_if_fail (GTK_IS_CLIST (widget));
7739 g_return_if_fail (context != NULL);
7740 g_return_if_fail (selection_data != NULL);
7742 clist = GTK_CLIST (widget);
7744 if (GTK_CLIST_REORDERABLE (clist) &&
7745 gtk_drag_get_source_widget (context) == widget &&
7746 selection_data->target ==
7747 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
7748 selection_data->format == GTK_TYPE_POINTER &&
7749 selection_data->length == sizeof (GtkCListCellInfo))
7751 GtkCListCellInfo *source_info;
7752 GtkCListDestInfo *dest_info;
7754 source_info = (GtkCListCellInfo *)(selection_data->data);
7755 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
7757 if (dest_info && source_info)
7759 if (dest_info->insert_pos == GTK_CLIST_DRAG_AFTER)
7760 dest_info->cell.row++;
7761 if (source_info->row < dest_info->cell.row)
7762 dest_info->cell.row--;
7764 if (dest_info->cell.row != source_info->row)
7765 gtk_clist_row_move (GTK_CLIST (widget),
7767 dest_info->cell.row);
7768 g_dataset_remove_data (context, "gtk-clist-drag-dest");
7774 gtk_clist_drag_data_get (GtkWidget *widget,
7775 GdkDragContext *context,
7776 GtkSelectionData *selection_data,
7780 g_return_if_fail (widget != NULL);
7781 g_return_if_fail (GTK_IS_CLIST (widget));
7782 g_return_if_fail (context != NULL);
7783 g_return_if_fail (selection_data != NULL);
7785 if (selection_data->target ==
7786 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
7788 GtkCListCellInfo *info;
7790 info = g_dataset_get_data (context, "gtk-clist-drag-source");
7794 GtkCListCellInfo ret_info;
7796 ret_info.row = info->row;
7797 ret_info.column = info->column;
7799 gtk_selection_data_set (selection_data, selection_data->target,
7800 GTK_TYPE_POINTER, (guchar *) &ret_info,
7801 sizeof (GtkCListCellInfo));
7804 gtk_selection_data_set (selection_data, selection_data->target,
7805 GTK_TYPE_POINTER, NULL, 0);
7810 draw_drag_highlight (GtkCList *clist,
7811 GtkCListRow *dest_row,
7812 gint dest_row_number,
7813 GtkCListDragPos drag_pos)
7817 y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
7821 case GTK_CLIST_DRAG_NONE:
7823 case GTK_CLIST_DRAG_AFTER:
7824 y += clist->row_height + 1;
7825 case GTK_CLIST_DRAG_BEFORE:
7826 gdk_draw_line (clist->clist_window, clist->xor_gc,
7827 0, y, clist->clist_window_width, y);
7829 case GTK_CLIST_DRAG_INTO:
7830 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
7831 clist->clist_window_width - 1, clist->row_height);
7837 gtk_clist_set_reorderable (GtkCList *clist,
7838 gboolean reorderable)
7842 g_return_if_fail (clist != NULL);
7843 g_return_if_fail (GTK_IS_CLIST (clist));
7845 if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
7848 widget = GTK_WIDGET (clist);
7852 GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
7853 gtk_drag_dest_set (widget,
7854 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
7855 &clist_target_table, 1, GDK_ACTION_MOVE);
7859 GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
7860 gtk_drag_dest_unset (GTK_WIDGET (clist));
7865 gtk_clist_set_use_drag_icons (GtkCList *clist,
7868 g_return_if_fail (clist != NULL);
7869 g_return_if_fail (GTK_IS_CLIST (clist));
7872 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7874 GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
7878 gtk_clist_set_button_actions (GtkCList *clist,
7880 guint8 button_actions)
7882 g_return_if_fail (clist != NULL);
7883 g_return_if_fail (GTK_IS_CLIST (clist));
7885 if (button <= MAX_BUTTON)
7887 if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
7889 remove_grab (clist);
7890 clist->drag_button = 0;
7893 if (clist->anchor >= 0 &&
7894 clist->selection_mode == GTK_SELECTION_EXTENDED)
7895 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
7897 clist->button_actions[button] = button_actions;