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.
21 #include "../config.h"
24 /* the number rows memchunk expands at a time */
25 #define CLIST_OPTIMUM_SIZE 512
27 /* the width of the column resize windows */
30 /* minimum allowed width of a column */
31 #define COLUMN_MIN_WIDTH 5
33 /* this defigns the base grid spacing */
34 #define CELL_SPACING 1
36 /* added the horizontal space at the beginning and end of a row*/
37 #define COLUMN_INSET 3
39 /* scrollbar spacing class macro */
40 #define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
42 /* gives the top pixel of the given row in context of
43 * the clist's voffset */
44 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
45 (((row) + 1) * CELL_SPACING) + \
48 /* returns the row index from a y pixel location in the
49 * context of the clist's voffset */
50 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
51 ((clist)->row_height + CELL_SPACING))
53 /* gives the left pixel of the given column in context of
54 * the clist's hoffset */
55 #define COLUMN_LEFT_XPIXEL(clist, column) ((clist)->column[(column)].area.x + \
58 /* returns the column index from a x pixel location in the
59 * context of the clist's hoffset */
61 COLUMN_FROM_XPIXEL (GtkCList * clist,
66 for (i = 0; i < clist->columns; i++)
68 cx = clist->column[i].area.x + clist->hoffset;
70 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
71 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
79 /* returns the top pixel of the given row in the context of
81 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
83 /* returns the left pixel of the given column in the context of
85 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
87 /* returns the total height of the list */
88 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
89 (CELL_SPACING * ((clist)->rows + 1)))
91 /* returns the total width of the list */
92 #define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
93 (clist)->column[(clist)->columns - 1].area.width + \
94 COLUMN_INSET + CELL_SPACING)
113 typedef void (*GtkCListSignal1) (GtkObject * object,
116 GdkEventButton * arg3,
119 typedef void (*GtkCListSignal2) (GtkObject * object,
124 static void sync_selection (GtkCList * clist,
128 /* GtkCList Methods */
129 static void gtk_clist_class_init (GtkCListClass * klass);
130 static void gtk_clist_init (GtkCList * clist);
132 /* GtkObject Methods */
133 static void gtk_clist_destroy (GtkObject * object);
134 static void gtk_clist_finalize (GtkObject * object);
137 /* GtkWidget Methods */
138 static void gtk_clist_realize (GtkWidget * widget);
139 static void gtk_clist_unrealize (GtkWidget * widget);
140 static void gtk_clist_map (GtkWidget * widget);
141 static void gtk_clist_unmap (GtkWidget * widget);
142 static void gtk_clist_draw (GtkWidget * widget,
143 GdkRectangle * area);
144 static gint gtk_clist_expose (GtkWidget * widget,
145 GdkEventExpose * event);
146 static gint gtk_clist_button_press (GtkWidget * widget,
147 GdkEventButton * event);
148 static gint gtk_clist_button_release (GtkWidget * widget,
149 GdkEventButton * event);
150 static gint gtk_clist_motion (GtkWidget * widget,
151 GdkEventMotion * event);
153 static void gtk_clist_size_request (GtkWidget * widget,
154 GtkRequisition * requisition);
155 static void gtk_clist_size_allocate (GtkWidget * widget,
156 GtkAllocation * allocation);
157 static gint get_selection_info (GtkCList * clist,
163 /* GtkContainer Methods */
164 static void gtk_clist_foreach (GtkContainer * container,
165 GtkCallback callback,
166 gpointer callback_data);
169 static void draw_row (GtkCList * clist,
172 GtkCListRow * clist_row);
173 static void draw_rows (GtkCList * clist,
174 GdkRectangle * area);
176 /* Size Allocation */
177 static void size_allocate_title_buttons (GtkCList * clist);
178 static void size_allocate_columns (GtkCList * clist);
181 static void toggle_row (GtkCList * clist,
184 GdkEventButton * event);
185 static void select_row (GtkCList * clist,
188 GdkEventButton * event);
189 static void unselect_row (GtkCList * clist,
192 GdkEventButton * event);
194 static void real_select_row (GtkCList * clist,
197 GdkEventButton * event);
198 static void real_unselect_row (GtkCList * clist,
201 GdkEventButton * event);
204 static void draw_xor_line (GtkCList * clist);
205 static gint new_column_width (GtkCList * clist,
209 static void resize_column (GtkCList * clist,
214 static void column_button_create (GtkCList * clist,
216 static void column_button_clicked (GtkWidget * widget,
220 static void create_scrollbars (GtkCList * clist);
221 static void adjust_scrollbars (GtkCList * clist);
222 static void check_exposures (GtkCList * clist);
223 static void vadjustment_changed (GtkAdjustment * adjustment,
225 static void vadjustment_value_changed (GtkAdjustment * adjustment,
227 static void hadjustment_changed (GtkAdjustment * adjustment,
229 static void hadjustment_value_changed (GtkAdjustment * adjustment,
233 /* Memory Allocation/Distruction Routines */
234 static GtkCListColumn *columns_new (GtkCList * clist);
236 static void column_title_new (GtkCList * clist,
239 static void columns_delete (GtkCList * clist);
241 static GtkCListRow *row_new (GtkCList * clist);
243 static void row_delete (GtkCList * clist,
244 GtkCListRow * clist_row);
245 static void cell_empty (GtkCList * clist,
246 GtkCListRow * clist_row,
248 static void cell_set_text (GtkCList * clist,
249 GtkCListRow * clist_row,
252 static void cell_set_pixmap (GtkCList * clist,
253 GtkCListRow * clist_row,
257 static void cell_set_pixtext (GtkCList * clist,
258 GtkCListRow * clist_row,
266 static void gtk_clist_marshal_signal_1 (GtkObject * object,
270 static void gtk_clist_marshal_signal_2 (GtkObject * object,
275 /* Fill in data after widget is realized and has style */
277 static void add_style_data (GtkCList * clist);
279 static GtkContainerClass *parent_class = NULL;
280 static guint clist_signals[LAST_SIGNAL] = {0};
284 gtk_clist_get_type ()
286 static GtkType clist_type = 0;
290 GtkTypeInfo clist_info =
294 sizeof (GtkCListClass),
295 (GtkClassInitFunc) gtk_clist_class_init,
296 (GtkObjectInitFunc) gtk_clist_init,
297 (GtkArgSetFunc) NULL,
298 (GtkArgGetFunc) NULL,
301 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
308 gtk_clist_class_init (GtkCListClass * klass)
310 GtkObjectClass *object_class;
311 GtkWidgetClass *widget_class;
312 GtkContainerClass *container_class;
314 object_class = (GtkObjectClass *) klass;
315 widget_class = (GtkWidgetClass *) klass;
316 container_class = (GtkContainerClass *) klass;
318 parent_class = gtk_type_class (gtk_container_get_type ());
320 clist_signals[SELECT_ROW] =
321 gtk_signal_new ("select_row",
324 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
325 gtk_clist_marshal_signal_1,
326 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
327 clist_signals[UNSELECT_ROW] =
328 gtk_signal_new ("unselect_row",
331 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
332 gtk_clist_marshal_signal_1,
333 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
334 clist_signals[CLICK_COLUMN] =
335 gtk_signal_new ("click_column",
338 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
339 gtk_clist_marshal_signal_2,
340 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
342 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
344 object_class->destroy = gtk_clist_destroy;
345 object_class->finalize = gtk_clist_finalize;
347 widget_class->realize = gtk_clist_realize;
348 widget_class->unrealize = gtk_clist_unrealize;
349 widget_class->map = gtk_clist_map;
350 widget_class->unmap = gtk_clist_unmap;
351 widget_class->draw = gtk_clist_draw;
352 widget_class->button_press_event = gtk_clist_button_press;
353 widget_class->button_release_event = gtk_clist_button_release;
354 widget_class->motion_notify_event = gtk_clist_motion;
355 widget_class->expose_event = gtk_clist_expose;
356 widget_class->size_request = gtk_clist_size_request;
357 widget_class->size_allocate = gtk_clist_size_allocate;
359 /* container_class->add = NULL; use the default GtkContainerClass warning */
360 /* container_class->remove = NULL; use the default GtkContainerClass warning */
361 container_class->foreach = gtk_clist_foreach;
363 klass->select_row = real_select_row;
364 klass->unselect_row = real_unselect_row;
365 klass->click_column = NULL;
367 klass->draw_row = draw_row;
369 klass->scrollbar_spacing = 5;
373 gtk_clist_marshal_signal_1 (GtkObject * object,
378 GtkCListSignal1 rfunc;
380 rfunc = (GtkCListSignal1) func;
382 (*rfunc) (object, GTK_VALUE_INT (args[0]),
383 GTK_VALUE_INT (args[1]),
384 GTK_VALUE_POINTER (args[2]),
389 gtk_clist_marshal_signal_2 (GtkObject * object,
394 GtkCListSignal2 rfunc;
396 rfunc = (GtkCListSignal2) func;
398 (*rfunc) (object, GTK_VALUE_INT (args[0]),
403 gtk_clist_init (GtkCList * clist)
407 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
408 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
410 clist->row_mem_chunk = NULL;
411 clist->cell_mem_chunk = NULL;
414 clist->row_center_offset = 0;
415 clist->row_height = 0;
416 clist->row_list = NULL;
417 clist->row_list_end = NULL;
421 clist->title_window = NULL;
422 clist->column_title_area.x = 0;
423 clist->column_title_area.y = 0;
424 clist->column_title_area.width = 1;
425 clist->column_title_area.height = 1;
427 clist->clist_window = NULL;
428 clist->clist_window_width = 1;
429 clist->clist_window_height = 1;
434 clist->shadow_type = GTK_SHADOW_IN;
435 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
436 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
438 clist->cursor_drag = NULL;
439 clist->xor_gc = NULL;
444 clist->selection_mode = GTK_SELECTION_SINGLE;
445 clist->selection = NULL;
450 gtk_clist_construct (GtkCList * clist,
456 g_return_if_fail (clist != NULL);
457 g_return_if_fail (GTK_IS_CLIST (clist));
458 g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
460 GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
462 /* initalize memory chunks, if this has not been done by any
463 * possibly derived widget
465 if (!clist->row_mem_chunk)
466 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
467 sizeof (GtkCListRow),
468 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
471 if (!clist->cell_mem_chunk)
472 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
473 sizeof (GtkCell) * columns,
474 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
477 /* set number of columns, allocate memory */
478 clist->columns = columns;
479 clist->column = columns_new (clist);
481 /* there needs to be at least one column button
482 * because there is alot of code that will break if it
484 column_button_create (clist, 0);
486 /* create scrollbars */
487 create_scrollbars (clist);
491 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
492 for (i = 0; i < columns; i++)
493 gtk_clist_set_column_title (clist, i, titles[i]);
497 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
502 * GTKCLIST PUBLIC INTERFACE
503 * gtk_clist_new_with_titles
507 gtk_clist_new_with_titles (gint columns,
512 g_return_val_if_fail (titles != NULL, NULL);
514 widget = gtk_type_new (gtk_clist_get_type ());
516 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
522 gtk_clist_new (gint columns)
529 clist = gtk_type_new (gtk_clist_get_type ());
530 gtk_clist_construct (clist, columns, NULL);
531 return GTK_WIDGET (clist);
535 gtk_clist_set_border (GtkCList * clist,
536 GtkShadowType border)
538 g_return_if_fail (clist != NULL);
540 clist->shadow_type = border;
542 if (GTK_WIDGET_VISIBLE (clist))
543 gtk_widget_queue_resize (GTK_WIDGET (clist));
547 gtk_clist_set_selection_mode (GtkCList * clist,
548 GtkSelectionMode mode)
550 g_return_if_fail (clist != NULL);
552 clist->selection_mode = mode;
556 gtk_clist_freeze (GtkCList * clist)
558 g_return_if_fail (clist != NULL);
560 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
564 gtk_clist_thaw (GtkCList * clist)
566 g_return_if_fail (clist != NULL);
568 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
570 adjust_scrollbars (clist);
571 draw_rows (clist, NULL);
575 gtk_clist_column_titles_show (GtkCList * clist)
577 g_return_if_fail (clist != NULL);
579 if (!GTK_CLIST_SHOW_TITLES (clist))
581 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
582 if (clist->title_window)
583 gdk_window_show (clist->title_window);
584 gtk_widget_queue_resize (GTK_WIDGET (clist));
589 gtk_clist_column_titles_hide (GtkCList * clist)
591 g_return_if_fail (clist != NULL);
593 if (GTK_CLIST_SHOW_TITLES (clist))
595 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
596 if (clist->title_window)
597 gdk_window_hide (clist->title_window);
598 gtk_widget_queue_resize (GTK_WIDGET (clist));
603 gtk_clist_column_title_active (GtkCList * clist,
606 g_return_if_fail (clist != NULL);
608 if (column < 0 || column >= clist->columns)
611 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
612 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
614 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
615 if (GTK_WIDGET_VISIBLE (clist))
616 gtk_widget_queue_draw (clist->column[column].button);
621 gtk_clist_column_title_passive (GtkCList * clist,
624 g_return_if_fail (clist != NULL);
626 if (column < 0 || column >= clist->columns)
629 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
630 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
632 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
633 if (GTK_WIDGET_VISIBLE (clist))
634 gtk_widget_queue_draw (clist->column[column].button);
639 gtk_clist_column_titles_active (GtkCList * clist)
643 g_return_if_fail (clist != NULL);
645 for (i = 0; i < clist->columns; i++)
646 if (clist->column[i].button)
647 gtk_clist_column_title_active (clist, i);
651 gtk_clist_column_titles_passive (GtkCList * clist)
655 g_return_if_fail (clist != NULL);
657 for (i = 0; i < clist->columns; i++)
658 if (clist->column[i].button)
659 gtk_clist_column_title_passive (clist, i);
663 gtk_clist_set_column_title (GtkCList * clist,
668 GtkWidget *old_widget;
669 GtkWidget *alignment = NULL;
672 g_return_if_fail (clist != NULL);
674 if (column < 0 || column >= clist->columns)
677 /* if the column button doesn't currently exist,
678 * it has to be created first */
679 if (!clist->column[column].button)
681 column_button_create (clist, column);
685 column_title_new (clist, column, title);
687 /* remove and destroy the old widget */
688 old_widget = GTK_BUTTON (clist->column[column].button)->child;
690 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
692 /* create new alignment based no column justification */
693 switch (clist->column[column].justification)
695 case GTK_JUSTIFY_LEFT:
696 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
699 case GTK_JUSTIFY_RIGHT:
700 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
703 case GTK_JUSTIFY_CENTER:
704 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
707 case GTK_JUSTIFY_FILL:
708 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
712 label = gtk_label_new (clist->column[column].title);
713 gtk_container_add (GTK_CONTAINER (alignment), label);
714 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
715 gtk_widget_show (label);
716 gtk_widget_show (alignment);
718 /* if this button didn't previously exist, then the
719 * column button positions have to be re-computed */
720 if (GTK_WIDGET_VISIBLE (clist) && new_button)
721 size_allocate_title_buttons (clist);
725 gtk_clist_set_column_widget (GtkCList * clist,
730 GtkWidget *old_widget;
732 g_return_if_fail (clist != NULL);
734 if (column < 0 || column >= clist->columns)
737 /* if the column button doesn't currently exist,
738 * it has to be created first */
739 if (!clist->column[column].button)
741 column_button_create (clist, column);
745 column_title_new (clist, column, NULL);
747 /* remove and destroy the old widget */
748 old_widget = GTK_BUTTON (clist->column[column].button)->child;
750 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
752 /* add and show the widget */
755 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
756 gtk_widget_show (widget);
759 /* if this button didn't previously exist, then the
760 * column button positions have to be re-computed */
761 if (GTK_WIDGET_VISIBLE (clist) && new_button)
762 size_allocate_title_buttons (clist);
766 gtk_clist_set_column_justification (GtkCList * clist,
768 GtkJustification justification)
770 GtkWidget *alignment;
772 g_return_if_fail (clist != NULL);
774 if (column < 0 || column >= clist->columns)
777 clist->column[column].justification = justification;
779 /* change the alinment of the button title if it's not a
781 if (clist->column[column].title)
783 alignment = GTK_BUTTON (clist->column[column].button)->child;
785 switch (clist->column[column].justification)
787 case GTK_JUSTIFY_LEFT:
788 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
791 case GTK_JUSTIFY_RIGHT:
792 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
795 case GTK_JUSTIFY_CENTER:
796 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
799 case GTK_JUSTIFY_FILL:
800 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
808 if (!GTK_CLIST_FROZEN (clist))
809 draw_rows (clist, NULL);
813 gtk_clist_set_column_width (GtkCList * clist,
817 g_return_if_fail (clist != NULL);
819 if (column < 0 || column >= clist->columns)
822 clist->column[column].width = width;
823 clist->column[column].width_set = TRUE;
825 /* FIXME: this is quite expensive to do if the widget hasn't
826 * been size_allocated yet, and pointless. Should
829 size_allocate_columns (clist);
830 size_allocate_title_buttons (clist);
832 if (!GTK_CLIST_FROZEN (clist))
834 adjust_scrollbars (clist);
835 draw_rows (clist, NULL);
840 gtk_clist_set_row_height (GtkCList * clist,
845 g_return_if_fail (clist != NULL);
848 clist->row_height = height;
852 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
854 if (GTK_WIDGET_REALIZED (clist))
856 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
857 GTK_WIDGET (clist) ->style->font->descent + 1);
858 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
861 if (!GTK_CLIST_FROZEN (clist))
863 adjust_scrollbars (clist);
864 draw_rows (clist, NULL);
869 gtk_clist_moveto (GtkCList * clist,
877 g_return_if_fail (clist != NULL);
879 if (row < -1 || row >= clist->rows)
881 if (column < -1 || column >= clist->columns)
884 /* adjust vertical scrollbar */
887 x = ROW_TOP (clist, row) - (row_align * (clist->clist_window_height -
888 (clist->row_height + 2 * CELL_SPACING)));
891 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
892 else if (x > LIST_HEIGHT (clist) - clist->clist_window_height)
893 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
894 clist->clist_window_height;
896 GTK_RANGE (clist->vscrollbar)->adjustment->value = x;
898 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
902 /* adjust horizontal scrollbar */
905 y = COLUMN_LEFT (clist, column) - (col_align * (clist->clist_window_width -
906 clist->column[column].area.width +
907 2 * (CELL_SPACING + COLUMN_INSET)));
910 GTK_RANGE (clist->hscrollbar)->adjustment->value = 0.0;
911 else if (y > LIST_WIDTH (clist) - clist->clist_window_width)
912 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
913 clist->clist_window_width;
915 GTK_RANGE (clist->hscrollbar)->adjustment->value = y;
917 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
923 gtk_clist_get_cell_type (GtkCList * clist,
927 GtkCListRow *clist_row;
929 g_return_val_if_fail (clist != NULL, -1);
931 if (row < 0 || row >= clist->rows)
933 if (column < 0 || column >= clist->columns)
936 clist_row = (g_list_nth (clist->row_list, row))->data;
938 return clist_row->cell[column].type;
942 gtk_clist_set_text (GtkCList * clist,
947 GtkCListRow *clist_row;
949 g_return_if_fail (clist != NULL);
951 if (row < 0 || row >= clist->rows)
953 if (column < 0 || column >= clist->columns)
956 clist_row = (g_list_nth (clist->row_list, row))->data;
958 /* if text is null, then the cell is empty */
960 cell_set_text (clist, clist_row, column, text);
962 cell_empty (clist, clist_row, column);
964 /* redraw the list if it's not frozen */
965 if (!GTK_CLIST_FROZEN (clist))
967 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
968 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
969 (clist, NULL, row, clist_row);
974 gtk_clist_get_text (GtkCList * clist,
979 GtkCListRow *clist_row;
981 g_return_val_if_fail (clist != NULL, 0);
983 if (row < 0 || row >= clist->rows)
985 if (column < 0 || column >= clist->columns)
988 clist_row = (g_list_nth (clist->row_list, row))->data;
990 if (clist_row->cell[column].type != GTK_CELL_TEXT)
994 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
1000 gtk_clist_set_pixmap (GtkCList * clist,
1006 GtkCListRow *clist_row;
1008 g_return_if_fail (clist != NULL);
1010 if (row < 0 || row >= clist->rows)
1012 if (column < 0 || column >= clist->columns)
1015 clist_row = (g_list_nth (clist->row_list, row))->data;
1017 gdk_pixmap_ref (pixmap);
1019 if (mask) gdk_pixmap_ref (mask);
1021 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1023 /* redraw the list if it's not frozen */
1024 if (!GTK_CLIST_FROZEN (clist))
1026 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1027 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1028 (clist, NULL, row, clist_row);
1033 gtk_clist_get_pixmap (GtkCList * clist,
1036 GdkPixmap ** pixmap,
1039 GtkCListRow *clist_row;
1041 g_return_val_if_fail (clist != NULL, 0);
1043 if (row < 0 || row >= clist->rows)
1045 if (column < 0 || column >= clist->columns)
1048 clist_row = (g_list_nth (clist->row_list, row))->data;
1050 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1055 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1056 /* mask can be NULL */
1057 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1064 gtk_clist_set_pixtext (GtkCList * clist,
1072 GtkCListRow *clist_row;
1074 g_return_if_fail (clist != NULL);
1076 if (row < 0 || row >= clist->rows)
1078 if (column < 0 || column >= clist->columns)
1081 clist_row = (g_list_nth (clist->row_list, row))->data;
1083 gdk_pixmap_ref (pixmap);
1084 if (mask) gdk_pixmap_ref (mask);
1085 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1087 /* redraw the list if it's not frozen */
1088 if (!GTK_CLIST_FROZEN (clist))
1090 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1091 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1092 (clist, NULL, row, clist_row);
1097 gtk_clist_get_pixtext (GtkCList * clist,
1102 GdkPixmap ** pixmap,
1105 GtkCListRow *clist_row;
1107 g_return_val_if_fail (clist != NULL, 0);
1109 if (row < 0 || row >= clist->rows)
1111 if (column < 0 || column >= clist->columns)
1114 clist_row = (g_list_nth (clist->row_list, row))->data;
1116 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1120 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1122 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1124 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1126 /* mask can be NULL */
1127 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1133 gtk_clist_set_foreground (GtkCList * clist,
1137 GtkCListRow *clist_row;
1139 g_return_if_fail (clist != NULL);
1141 if (row < 0 || row >= clist->rows)
1144 clist_row = (g_list_nth (clist->row_list, row))->data;
1148 clist_row->foreground = *color;
1149 clist_row->fg_set = TRUE;
1152 clist_row->fg_set = FALSE;
1154 if (!GTK_CLIST_FROZEN (clist)
1155 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1156 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1157 (clist, NULL, row, clist_row);
1161 gtk_clist_set_background (GtkCList * clist,
1165 GtkCListRow *clist_row;
1167 g_return_if_fail (clist != NULL);
1169 if (row < 0 || row >= clist->rows)
1172 clist_row = (g_list_nth (clist->row_list, row))->data;
1176 clist_row->background = *color;
1177 clist_row->bg_set = TRUE;
1180 clist_row->bg_set = FALSE;
1182 if (!GTK_CLIST_FROZEN (clist)
1183 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1184 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1185 (clist, NULL, row, clist_row);
1189 gtk_clist_set_shift (GtkCList * clist,
1195 GtkCListRow *clist_row;
1197 g_return_if_fail (clist != NULL);
1199 if (row < 0 || row >= clist->rows)
1201 if (column < 0 || column >= clist->columns)
1204 clist_row = (g_list_nth (clist->row_list, row))->data;
1206 clist_row->cell[column].vertical = vertical;
1207 clist_row->cell[column].horizontal = horizontal;
1209 if (!GTK_CLIST_FROZEN (clist)
1210 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1211 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1212 (clist, NULL, row, clist_row);
1216 gtk_clist_append (GtkCList * clist,
1220 GtkCListRow *clist_row;
1222 g_return_val_if_fail (clist != NULL, -1);
1224 clist_row = row_new (clist);
1227 /* set the text in the row's columns */
1229 for (i = 0; i < clist->columns; i++)
1231 cell_set_text (clist, clist_row, i, text[i]);
1233 /* keeps track of the end of the list so the list
1234 * doesn't have to be traversed every time a item is added */
1235 if (!clist->row_list)
1237 clist->row_list = g_list_append (clist->row_list, clist_row);
1238 clist->row_list_end = clist->row_list;
1240 /* check the selection mode to see if we should select
1241 * the first row automaticly */
1242 switch (clist->selection_mode)
1244 case GTK_SELECTION_BROWSE:
1245 gtk_clist_select_row (clist, 0, -1);
1253 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1255 /* redraw the list if it's not frozen */
1256 if (!GTK_CLIST_FROZEN (clist))
1258 adjust_scrollbars (clist);
1260 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1261 draw_rows (clist, NULL);
1264 /* return index of the row */
1265 return clist->rows - 1;
1269 gtk_clist_insert (GtkCList * clist,
1274 GtkCListRow *clist_row;
1276 g_return_if_fail (clist != NULL);
1277 g_return_if_fail (text != NULL);
1279 /* return if out of bounds */
1280 if (row < 0 || row > clist->rows)
1283 if (clist->rows == 0)
1284 gtk_clist_append (clist, text);
1287 /* create the row */
1288 clist_row = row_new (clist);
1290 /* set the text in the row's columns */
1292 for (i = 0; i < clist->columns; i++)
1294 cell_set_text (clist, clist_row, i, text[i]);
1296 /* reset the row end pointer if we're inserting at the
1297 * end of the list */
1298 if (row == clist->rows)
1299 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1301 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1305 /* syncronize the selection list */
1306 sync_selection (clist, row, SYNC_INSERT);
1309 /* redraw the list if it isn't frozen */
1310 if (!GTK_CLIST_FROZEN (clist))
1312 adjust_scrollbars (clist);
1314 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1315 draw_rows (clist, NULL);
1320 gtk_clist_remove (GtkCList * clist,
1323 gint was_visible, was_selected;
1325 GtkCListRow *clist_row;
1327 g_return_if_fail (clist != NULL);
1329 /* return if out of bounds */
1330 if (row < 0 || row > (clist->rows - 1))
1333 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1336 /* get the row we're going to delete */
1337 list = g_list_nth (clist->row_list, row);
1338 clist_row = list->data;
1340 /* if we're removing a selected row, we have to make sure
1341 * it's properly unselected, and then sync up the clist->selected
1342 * list to reflect the deincrimented indexies of rows after the
1344 if (clist_row->state == GTK_STATE_SELECTED)
1348 switch (clist->selection_mode)
1350 case GTK_SELECTION_SINGLE:
1351 case GTK_SELECTION_BROWSE:
1352 case GTK_SELECTION_MULTIPLE:
1353 gtk_clist_unselect_row (clist, row, -1);
1361 /* reset the row end pointer if we're removing at the
1362 * end of the list */
1363 if (row == clist->rows - 1)
1364 clist->row_list_end = list->prev;
1366 clist->row_list = g_list_remove (clist->row_list, clist_row);
1368 sync_selection (clist, row, SYNC_REMOVE);
1370 /* preform any selections required by the selection mode */
1373 switch (clist->selection_mode)
1375 case GTK_SELECTION_BROWSE:
1376 if (row == clist->rows)
1377 gtk_clist_select_row (clist, row - 1, -1);
1379 gtk_clist_select_row (clist, row, -1);
1388 row_delete (clist, clist_row);
1390 /* redraw the row if it isn't frozen */
1391 if (!GTK_CLIST_FROZEN (clist))
1393 adjust_scrollbars (clist);
1396 draw_rows (clist, NULL);
1401 sync_selection (GtkCList * clist,
1407 list = clist->selection;
1410 if ((gint) list->data >= row)
1414 list->data = ((gchar*) list->data) + 1;
1418 list->data = ((gchar*) list->data) - 1;
1430 gtk_clist_clear (GtkCList * clist)
1434 g_return_if_fail (clist != NULL);
1436 /* remove all the rows */
1437 for (list = clist->row_list; list; list = list->next)
1439 GtkCListRow *clist_row;
1441 clist_row = list->data;
1442 row_delete (clist, clist_row);
1444 g_list_free (clist->row_list);
1446 /* free up the selection list */
1447 g_list_free (clist->selection);
1449 clist->row_list = NULL;
1450 clist->row_list_end = NULL;
1451 clist->selection = NULL;
1455 /* zero-out the scrollbars */
1456 if (clist->vscrollbar)
1458 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1459 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1461 if (!GTK_CLIST_FROZEN (clist))
1463 adjust_scrollbars (clist);
1464 draw_rows (clist, NULL);
1470 gtk_clist_set_row_data (GtkCList * clist,
1474 gtk_clist_set_row_data_full (clist, row, data, NULL);
1478 gtk_clist_set_row_data_full (GtkCList * clist,
1481 GtkDestroyNotify destroy)
1483 GtkCListRow *clist_row;
1485 g_return_if_fail (clist != NULL);
1487 if (row < 0 || row > (clist->rows - 1))
1490 clist_row = (g_list_nth (clist->row_list, row))->data;
1491 clist_row->data = data;
1492 clist_row->destroy = destroy;
1494 /* re-send the selected signal if data is changed/added
1495 * so the application can respond to the new data --
1496 * this could be questionable behavior */
1497 if (clist_row->state == GTK_STATE_SELECTED)
1498 gtk_clist_select_row (clist, row, -1);
1502 gtk_clist_get_row_data (GtkCList * clist,
1505 GtkCListRow *clist_row;
1507 g_return_val_if_fail (clist != NULL, NULL);
1509 if (row < 0 || row > (clist->rows - 1))
1512 clist_row = (g_list_nth (clist->row_list, row))->data;
1513 return clist_row->data;
1517 gtk_clist_find_row_from_data (GtkCList * clist,
1523 g_return_val_if_fail (clist != NULL, -1);
1524 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1526 if (clist->rows < 1)
1527 return -1; /* is this an optimization or just worthless? */
1530 list = clist->row_list;
1533 GtkCListRow *clist_row;
1535 clist_row = list->data;
1536 if (clist_row->data == data)
1549 gtk_clist_select_row (GtkCList * clist,
1553 g_return_if_fail (clist != NULL);
1555 if (row < 0 || row >= clist->rows)
1558 if (column < -1 || column >= clist->columns)
1561 select_row (clist, row, column, NULL);
1565 gtk_clist_unselect_row (GtkCList * clist,
1569 g_return_if_fail (clist != NULL);
1571 if (row < 0 || row >= clist->rows)
1574 if (column < -1 || column >= clist->columns)
1577 unselect_row (clist, row, column, NULL);
1581 gtk_clist_row_is_visible (GtkCList * clist,
1586 g_return_val_if_fail (clist != NULL, 0);
1588 if (row < 0 || row >= clist->rows)
1589 return GTK_VISIBILITY_NONE;
1591 if (clist->row_height == 0)
1592 return GTK_VISIBILITY_NONE;
1594 if (row < ROW_FROM_YPIXEL (clist, 0))
1595 return GTK_VISIBILITY_NONE;
1597 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
1598 return GTK_VISIBILITY_NONE;
1600 top = ROW_TOP_YPIXEL (clist, row);
1603 || ((top + clist->row_height) >= clist->clist_window_height))
1604 return GTK_VISIBILITY_PARTIAL;
1606 return GTK_VISIBILITY_FULL;
1610 gtk_clist_get_vadjustment (GtkCList * clist)
1612 g_return_val_if_fail (clist != NULL, NULL);
1613 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1615 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
1619 gtk_clist_get_hadjustment (GtkCList * clist)
1621 g_return_val_if_fail (clist != NULL, NULL);
1622 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1624 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
1628 gtk_clist_set_policy (GtkCList * clist,
1629 GtkPolicyType vscrollbar_policy,
1630 GtkPolicyType hscrollbar_policy)
1632 g_return_if_fail (clist != NULL);
1633 g_return_if_fail (GTK_IS_CLIST (clist));
1635 if (clist->vscrollbar_policy != vscrollbar_policy)
1637 clist->vscrollbar_policy = vscrollbar_policy;
1639 if (GTK_WIDGET (clist)->parent)
1640 gtk_widget_queue_resize (GTK_WIDGET (clist));
1643 if (clist->hscrollbar_policy != hscrollbar_policy)
1645 clist->hscrollbar_policy = hscrollbar_policy;
1647 if (GTK_WIDGET (clist)->parent)
1648 gtk_widget_queue_resize (GTK_WIDGET (clist));
1655 * gtk_clist_finalize
1658 gtk_clist_destroy (GtkObject * object)
1663 g_return_if_fail (object != NULL);
1664 g_return_if_fail (GTK_IS_CLIST (object));
1666 clist = GTK_CLIST (object);
1668 /* freeze the list */
1669 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1671 /* get rid of all the rows */
1672 gtk_clist_clear (clist);
1674 /* Since we don't have a _remove method, unparent the children
1675 * instead of destroying them so the focus will be unset properly.
1676 * (For other containers, the _remove method takes care of the
1677 * unparent) The destroy will happen when the refcount drops
1681 /* destroy the scrollbars */
1682 if (clist->vscrollbar)
1684 gtk_widget_unparent (clist->vscrollbar);
1685 clist->vscrollbar = NULL;
1687 if (clist->hscrollbar)
1689 gtk_widget_unparent (clist->hscrollbar);
1690 clist->hscrollbar = NULL;
1693 /* destroy the column buttons */
1694 for (i = 0; i < clist->columns; i++)
1695 if (clist->column[i].button)
1697 gtk_widget_unparent (clist->column[i].button);
1698 clist->column[i].button = NULL;
1701 if (GTK_OBJECT_CLASS (parent_class)->destroy)
1702 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1706 gtk_clist_finalize (GtkObject * object)
1710 g_return_if_fail (object != NULL);
1711 g_return_if_fail (GTK_IS_CLIST (object));
1713 clist = GTK_CLIST (object);
1715 columns_delete (clist);
1717 g_mem_chunk_destroy (clist->cell_mem_chunk);
1718 g_mem_chunk_destroy (clist->row_mem_chunk);
1720 if (GTK_OBJECT_CLASS (parent_class)->finalize)
1721 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
1727 * gtk_clist_unrealize
1732 * gtk_clist_button_press
1733 * gtk_clist_button_release
1734 * gtk_clist_button_motion
1735 * gtk_clist_size_request
1736 * gtk_clist_size_allocate
1739 gtk_clist_realize (GtkWidget * widget)
1743 GdkWindowAttr attributes;
1744 gint attributes_mask;
1748 g_return_if_fail (widget != NULL);
1749 g_return_if_fail (GTK_IS_CLIST (widget));
1751 clist = GTK_CLIST (widget);
1753 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1755 add_style_data (clist);
1757 border_width = GTK_CONTAINER (widget)->border_width;
1759 attributes.window_type = GDK_WINDOW_CHILD;
1760 attributes.x = widget->allocation.x + border_width;
1761 attributes.y = widget->allocation.y + border_width;
1762 attributes.width = widget->allocation.width - border_width * 2;
1763 attributes.height = widget->allocation.height - border_width * 2;
1764 attributes.wclass = GDK_INPUT_OUTPUT;
1765 attributes.visual = gtk_widget_get_visual (widget);
1766 attributes.colormap = gtk_widget_get_colormap (widget);
1767 attributes.event_mask = gtk_widget_get_events (widget);
1768 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1769 GDK_BUTTON_PRESS_MASK |
1770 GDK_BUTTON_RELEASE_MASK |
1771 GDK_KEY_PRESS_MASK);
1772 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1776 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1777 gdk_window_set_user_data (widget->window, clist);
1779 widget->style = gtk_style_attach (widget->style, widget->window);
1781 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1783 /* column-title window */
1785 attributes.x = clist->column_title_area.x;
1786 attributes.y = clist->column_title_area.y;
1787 attributes.width = clist->column_title_area.width;
1788 attributes.height = clist->column_title_area.height;
1790 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1791 gdk_window_set_user_data (clist->title_window, clist);
1793 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
1794 gdk_window_show (clist->title_window);
1796 /* set things up so column buttons are drawn in title window */
1797 for (i = 0; i < clist->columns; i++)
1798 if (clist->column[i].button)
1799 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
1802 attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
1803 attributes.y = clist->internal_allocation.y + widget->style->klass->ythickness +
1804 clist->column_title_area.height;
1805 attributes.width = clist->clist_window_width;
1806 attributes.height = clist->clist_window_height;
1808 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1809 gdk_window_set_user_data (clist->clist_window, clist);
1811 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
1812 gdk_window_show (clist->clist_window);
1813 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
1814 &clist->clist_window_height);
1816 /* create resize windows */
1817 attributes.wclass = GDK_INPUT_ONLY;
1818 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
1819 GDK_BUTTON_RELEASE_MASK |
1820 GDK_POINTER_MOTION_MASK |
1821 GDK_POINTER_MOTION_HINT_MASK);
1822 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1823 attributes_mask = GDK_WA_CURSOR;
1825 for (i = 0; i < clist->columns; i++)
1827 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
1828 gdk_window_set_user_data (clist->column[i].window, clist);
1831 /* This is slightly less efficient than creating them with the
1832 * right size to begin with, but easier
1834 size_allocate_title_buttons (clist);
1837 clist->fg_gc = gdk_gc_new (widget->window);
1838 clist->bg_gc = gdk_gc_new (widget->window);
1840 /* We'll use this gc to do scrolling as well */
1841 gdk_gc_set_exposures (clist->fg_gc, TRUE);
1843 values.foreground = widget->style->white;
1844 values.function = GDK_XOR;
1845 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1846 clist->xor_gc = gdk_gc_new_with_values (widget->window,
1854 gtk_clist_unrealize (GtkWidget * widget)
1859 g_return_if_fail (widget != NULL);
1860 g_return_if_fail (GTK_IS_CLIST (widget));
1862 clist = GTK_CLIST (widget);
1864 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1866 gdk_cursor_destroy (clist->cursor_drag);
1867 gdk_gc_destroy (clist->xor_gc);
1868 gdk_gc_destroy (clist->fg_gc);
1869 gdk_gc_destroy (clist->bg_gc);
1871 for (i = 0; i < clist->columns; i++)
1872 if (clist->column[i].window)
1874 gdk_window_set_user_data (clist->column[i].window, NULL);
1875 gdk_window_destroy (clist->column[i].window);
1876 clist->column[i].window = NULL;
1879 gdk_window_set_user_data (clist->clist_window, NULL);
1880 gdk_window_destroy (clist->clist_window);
1881 clist->clist_window = NULL;
1883 gdk_window_set_user_data (clist->title_window, NULL);
1884 gdk_window_destroy (clist->title_window);
1885 clist->title_window = NULL;
1887 clist->cursor_drag = NULL;
1888 clist->xor_gc = NULL;
1889 clist->fg_gc = NULL;
1890 clist->bg_gc = NULL;
1892 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1893 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1897 gtk_clist_map (GtkWidget * widget)
1902 g_return_if_fail (widget != NULL);
1903 g_return_if_fail (GTK_IS_CLIST (widget));
1905 clist = GTK_CLIST (widget);
1907 if (!GTK_WIDGET_MAPPED (widget))
1909 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1911 gdk_window_show (widget->window);
1912 gdk_window_show (clist->title_window);
1913 gdk_window_show (clist->clist_window);
1915 /* map column buttons */
1916 for (i = 0; i < clist->columns; i++)
1917 if (clist->column[i].button &&
1918 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
1919 !GTK_WIDGET_MAPPED (clist->column[i].button))
1920 gtk_widget_map (clist->column[i].button);
1922 /* map resize windows AFTER column buttons (above) */
1923 for (i = 0; i < clist->columns; i++)
1924 if (clist->column[i].window && clist->column[i].button)
1925 gdk_window_show (clist->column[i].window);
1927 /* map vscrollbars */
1928 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
1929 !GTK_WIDGET_MAPPED (clist->vscrollbar))
1930 gtk_widget_map (clist->vscrollbar);
1932 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
1933 !GTK_WIDGET_MAPPED (clist->hscrollbar))
1934 gtk_widget_map (clist->hscrollbar);
1936 /* unfreeze the list */
1937 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
1942 gtk_clist_unmap (GtkWidget * widget)
1947 g_return_if_fail (widget != NULL);
1948 g_return_if_fail (GTK_IS_CLIST (widget));
1950 clist = GTK_CLIST (widget);
1952 if (GTK_WIDGET_MAPPED (widget))
1954 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1956 for (i = 0; i < clist->columns; i++)
1957 if (clist->column[i].window)
1958 gdk_window_hide (clist->column[i].window);
1960 gdk_window_hide (clist->clist_window);
1961 gdk_window_hide (clist->title_window);
1962 gdk_window_hide (widget->window);
1964 /* unmap scrollbars */
1965 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
1966 gtk_widget_unmap (clist->vscrollbar);
1968 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
1969 gtk_widget_unmap (clist->hscrollbar);
1971 /* unmap column buttons */
1972 for (i = 0; i < clist->columns; i++)
1973 if (clist->column[i].button &&
1974 GTK_WIDGET_MAPPED (clist->column[i].button))
1975 gtk_widget_unmap (clist->column[i].button);
1977 /* freeze the list */
1978 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1983 gtk_clist_draw (GtkWidget * widget,
1984 GdkRectangle * area)
1989 g_return_if_fail (widget != NULL);
1990 g_return_if_fail (GTK_IS_CLIST (widget));
1991 g_return_if_fail (area != NULL);
1993 if (GTK_WIDGET_DRAWABLE (widget))
1995 clist = GTK_CLIST (widget);
1996 border_width = GTK_CONTAINER (widget)->border_width;
1998 gdk_window_clear_area (widget->window,
1999 area->x - border_width,
2000 area->y - border_width,
2001 area->width, area->height);
2003 /* draw list shadow/border */
2004 gtk_draw_shadow (widget->style, widget->window,
2005 GTK_STATE_NORMAL, clist->shadow_type,
2007 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2008 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2009 clist->column_title_area.height);
2011 gdk_window_clear_area (clist->clist_window,
2014 draw_rows (clist, NULL);
2019 gtk_clist_expose (GtkWidget * widget,
2020 GdkEventExpose * event)
2024 g_return_val_if_fail (widget != NULL, FALSE);
2025 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2026 g_return_val_if_fail (event != NULL, FALSE);
2028 if (GTK_WIDGET_DRAWABLE (widget))
2030 clist = GTK_CLIST (widget);
2033 if (event->window == widget->window)
2034 gtk_draw_shadow (widget->style, widget->window,
2035 GTK_STATE_NORMAL, clist->shadow_type,
2037 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2038 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2039 clist->column_title_area.height);
2041 /* exposure events on the list */
2042 if (event->window == clist->clist_window)
2043 draw_rows (clist, &event->area);
2050 gtk_clist_button_press (GtkWidget * widget,
2051 GdkEventButton * event)
2055 gint x, y, row, column;
2057 g_return_val_if_fail (widget != NULL, FALSE);
2058 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2059 g_return_val_if_fail (event != NULL, FALSE);
2061 clist = GTK_CLIST (widget);
2063 /* selections on the list */
2064 if (event->window == clist->clist_window)
2069 if (get_selection_info (clist, x, y, &row, &column))
2070 toggle_row (clist, row, column, event);
2075 /* press on resize windows */
2076 for (i = 0; i < clist->columns; i++)
2077 if (clist->column[i].window && event->window == clist->column[i].window)
2079 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
2080 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2082 gdk_pointer_grab (clist->column[i].window, FALSE,
2083 GDK_POINTER_MOTION_HINT_MASK |
2084 GDK_BUTTON1_MOTION_MASK |
2085 GDK_BUTTON_RELEASE_MASK,
2086 NULL, NULL, event->time);
2088 draw_xor_line (clist);
2096 gtk_clist_button_release (GtkWidget * widget,
2097 GdkEventButton * event)
2099 gint i, x, width, visible;
2102 g_return_val_if_fail (widget != NULL, FALSE);
2103 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2104 g_return_val_if_fail (event != NULL, FALSE);
2106 clist = GTK_CLIST (widget);
2108 /* release on resize windows */
2109 if (GTK_CLIST_IN_DRAG (clist))
2110 for (i = 0; i < clist->columns; i++)
2111 if (clist->column[i].window && event->window == clist->column[i].window)
2113 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
2114 gtk_widget_get_pointer (widget, &x, NULL);
2115 width = new_column_width (clist, i, &x, &visible);
2116 gdk_pointer_ungrab (event->time);
2119 draw_xor_line (clist);
2121 resize_column (clist, i, width);
2129 gtk_clist_motion (GtkWidget * widget,
2130 GdkEventMotion * event)
2135 g_return_val_if_fail (widget != NULL, FALSE);
2136 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2138 clist = GTK_CLIST (widget);
2140 if (GTK_CLIST_IN_DRAG (clist))
2141 for (i = 0; i < clist->columns; i++)
2142 if (clist->column[i].window && event->window == clist->column[i].window)
2144 if (event->is_hint || event->window != widget->window)
2145 gtk_widget_get_pointer (widget, &x, NULL);
2149 new_column_width (clist, i, &x, &visible);
2150 /* Welcome to my hack! I'm going to use a value of x_drage = -99999 to
2151 * indicate the the xor line is already no visible */
2152 if (!visible && clist->x_drag != -99999)
2154 draw_xor_line (clist);
2155 clist->x_drag = -99999;
2158 if (x != clist->x_drag && visible)
2160 if (clist->x_drag != -99999)
2161 draw_xor_line (clist);
2164 draw_xor_line (clist);
2172 gtk_clist_size_request (GtkWidget * widget,
2173 GtkRequisition * requisition)
2178 g_return_if_fail (widget != NULL);
2179 g_return_if_fail (GTK_IS_CLIST (widget));
2180 g_return_if_fail (requisition != NULL);
2182 clist = GTK_CLIST (widget);
2184 add_style_data (clist);
2186 requisition->width = 0;
2187 requisition->height = 0;
2189 /* compute the size of the column title (title) area */
2190 clist->column_title_area.height = 0;
2191 if (GTK_CLIST_SHOW_TITLES (clist))
2192 for (i = 0; i < clist->columns; i++)
2193 if (clist->column[i].button)
2195 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
2196 clist->column_title_area.height = MAX (clist->column_title_area.height,
2197 clist->column[i].button->requisition.height);
2199 requisition->height += clist->column_title_area.height;
2201 /* add the vscrollbar space */
2202 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2203 GTK_WIDGET_VISIBLE (clist->vscrollbar))
2205 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
2207 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
2208 requisition->height = MAX (requisition->height,
2209 clist->vscrollbar->requisition.height);
2212 /* add the hscrollbar space */
2213 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2214 GTK_WIDGET_VISIBLE (clist->hscrollbar))
2216 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
2218 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
2219 requisition->width = MAX (clist->hscrollbar->requisition.width,
2220 requisition->width -
2221 clist->vscrollbar->requisition.width);
2225 requisition->width += widget->style->klass->xthickness * 2 +
2226 GTK_CONTAINER (widget)->border_width * 2;
2227 requisition->height += widget->style->klass->ythickness * 2 +
2228 GTK_CONTAINER (widget)->border_width * 2;
2232 gtk_clist_size_allocate (GtkWidget * widget,
2233 GtkAllocation * allocation)
2236 GtkAllocation clist_allocation;
2237 GtkAllocation child_allocation;
2238 gint i, vscrollbar_vis, hscrollbar_vis;
2240 g_return_if_fail (widget != NULL);
2241 g_return_if_fail (GTK_IS_CLIST (widget));
2242 g_return_if_fail (allocation != NULL);
2244 clist = GTK_CLIST (widget);
2245 widget->allocation = *allocation;
2247 if (GTK_WIDGET_REALIZED (widget))
2249 gdk_window_move_resize (widget->window,
2250 allocation->x + GTK_CONTAINER (widget)->border_width,
2251 allocation->y + GTK_CONTAINER (widget)->border_width,
2252 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
2253 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
2256 /* use internal allocation structure for all the math
2257 * because it's easier than always subtracting the container
2259 clist->internal_allocation.x = 0;
2260 clist->internal_allocation.y = 0;
2261 clist->internal_allocation.width = MAX (1, allocation->width -
2262 GTK_CONTAINER (widget)->border_width * 2);
2263 clist->internal_allocation.height = MAX (1, allocation->height -
2264 GTK_CONTAINER (widget)->border_width * 2);
2266 /* allocate clist window assuming no scrollbars */
2267 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2268 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2269 clist->column_title_area.height;
2270 clist_allocation.width = MAX (1, clist->internal_allocation.width -
2271 (2 * widget->style->klass->xthickness));
2272 clist_allocation.height = MAX (1, clist->internal_allocation.height -
2273 (2 * widget->style->klass->ythickness) -
2274 clist->column_title_area.height);
2277 * here's where we decide to show/not show the scrollbars
2282 for (i = 0; i <= 1; i++)
2284 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
2285 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2291 if (!vscrollbar_vis)
2294 clist_allocation.width = MAX (1, clist_allocation.width -
2295 (clist->vscrollbar->requisition.width +
2296 SCROLLBAR_SPACING (clist)));
2300 if (LIST_WIDTH (clist) <= clist_allocation.width &&
2301 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2307 if (!hscrollbar_vis)
2310 clist_allocation.height = MAX (1, clist_allocation.height -
2311 (clist->hscrollbar->requisition.height +
2312 SCROLLBAR_SPACING (clist)));
2317 clist->clist_window_width = clist_allocation.width;
2318 clist->clist_window_height = clist_allocation.height;
2320 if (GTK_WIDGET_REALIZED (widget))
2322 gdk_window_move_resize (clist->clist_window,
2325 clist_allocation.width,
2326 clist_allocation.height);
2329 /* position the window which holds the column title buttons */
2330 clist->column_title_area.x = widget->style->klass->xthickness;
2331 clist->column_title_area.y = widget->style->klass->ythickness;
2332 clist->column_title_area.width = clist_allocation.width;
2334 if (GTK_WIDGET_REALIZED (widget))
2336 gdk_window_move_resize (clist->title_window,
2337 clist->column_title_area.x,
2338 clist->column_title_area.y,
2339 clist->column_title_area.width,
2340 clist->column_title_area.height);
2343 /* column button allocation */
2344 size_allocate_columns (clist);
2346 if (GTK_WIDGET_REALIZED (widget))
2347 size_allocate_title_buttons (clist);
2349 adjust_scrollbars (clist);
2351 /* allocate the vscrollbar */
2354 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2355 gtk_widget_show (clist->vscrollbar);
2357 child_allocation.x = clist->internal_allocation.x +
2358 clist->internal_allocation.width -
2359 clist->vscrollbar->requisition.width;
2360 child_allocation.y = clist->internal_allocation.y;
2361 child_allocation.width = clist->vscrollbar->requisition.width;
2362 child_allocation.height = MAX (1, clist->internal_allocation.height -
2363 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
2365 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
2369 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2370 gtk_widget_hide (clist->vscrollbar);
2375 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2376 gtk_widget_show (clist->hscrollbar);
2378 child_allocation.x = clist->internal_allocation.x;
2379 child_allocation.y = clist->internal_allocation.y +
2380 clist->internal_allocation.height -
2381 clist->hscrollbar->requisition.height;
2382 child_allocation.width = MAX (1, clist->internal_allocation.width -
2383 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
2384 child_allocation.height = clist->hscrollbar->requisition.height;
2386 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
2390 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2391 gtk_widget_hide (clist->hscrollbar);
2394 /* set the vscrollbar adjustments */
2395 adjust_scrollbars (clist);
2403 gtk_clist_foreach (GtkContainer * container,
2404 GtkCallback callback,
2405 gpointer callback_data)
2410 g_return_if_fail (container != NULL);
2411 g_return_if_fail (GTK_IS_CLIST (container));
2412 g_return_if_fail (callback != NULL);
2414 clist = GTK_CLIST (container);
2416 /* callback for the column buttons */
2417 for (i = 0; i < clist->columns; i++)
2418 if (clist->column[i].button)
2419 (*callback) (clist->column[i].button, callback_data);
2421 /* callbacks for the scrollbars */
2422 if (clist->vscrollbar)
2423 (*callback) (clist->vscrollbar, callback_data);
2424 if (clist->hscrollbar)
2425 (*callback) (clist->hscrollbar, callback_data);
2434 draw_row (GtkCList * clist,
2435 GdkRectangle * area,
2437 GtkCListRow * clist_row)
2440 GdkGC *fg_gc, *bg_gc;
2441 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
2443 gint i, offset = 0, width, height, pixmap_width = 0;
2444 gint xsrc, ysrc, xdest, ydest;
2446 g_return_if_fail (clist != NULL);
2448 /* bail now if we arn't drawable yet */
2449 if (!GTK_WIDGET_DRAWABLE (clist))
2452 if (row < 0 || row >= clist->rows)
2455 widget = GTK_WIDGET (clist);
2457 /* if the function is passed the pointer to the row instead of null,
2458 * it avoids this expensive lookup */
2460 clist_row = (g_list_nth (clist->row_list, row))->data;
2462 /* rectangle of the entire row */
2463 row_rectangle.x = 0;
2464 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
2465 row_rectangle.width = clist->clist_window_width;
2466 row_rectangle.height = clist->row_height;
2468 /* rectangle of the cell spacing above the row */
2469 cell_rectangle.x = 0;
2470 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
2471 cell_rectangle.width = row_rectangle.width;
2472 cell_rectangle.height = CELL_SPACING;
2474 /* rectangle used to clip drawing operations, it's y and height
2475 * positions only need to be set once, so we set them once here.
2476 * the x and width are set withing the drawing loop below once per
2478 clip_rectangle.y = row_rectangle.y;
2479 clip_rectangle.height = row_rectangle.height;
2481 /* select GC for background rectangle */
2482 if (clist_row->state == GTK_STATE_SELECTED)
2484 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
2485 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
2489 if (clist_row->fg_set)
2491 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
2492 fg_gc = clist->fg_gc;
2495 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
2497 if (clist_row->bg_set)
2499 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
2500 bg_gc = clist->bg_gc;
2503 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
2506 /* draw the cell borders and background */
2509 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2510 gdk_draw_rectangle (clist->clist_window,
2511 widget->style->base_gc[GTK_STATE_NORMAL],
2513 intersect_rectangle.x,
2514 intersect_rectangle.y,
2515 intersect_rectangle.width,
2516 intersect_rectangle.height);
2518 /* the last row has to clear it's bottom cell spacing too */
2519 if (clist_row == clist->row_list_end->data)
2521 cell_rectangle.y += clist->row_height + CELL_SPACING;
2523 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2524 gdk_draw_rectangle (clist->clist_window,
2525 widget->style->base_gc[GTK_STATE_NORMAL],
2527 intersect_rectangle.x,
2528 intersect_rectangle.y,
2529 intersect_rectangle.width,
2530 intersect_rectangle.height);
2533 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
2536 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
2537 gdk_draw_rectangle (clist->clist_window,
2540 intersect_rectangle.x,
2541 intersect_rectangle.y,
2542 intersect_rectangle.width,
2543 intersect_rectangle.height);
2545 gdk_window_clear_area (clist->clist_window,
2546 intersect_rectangle.x,
2547 intersect_rectangle.y,
2548 intersect_rectangle.width,
2549 intersect_rectangle.height);
2553 gdk_draw_rectangle (clist->clist_window,
2554 widget->style->base_gc[GTK_STATE_NORMAL],
2558 cell_rectangle.width,
2559 cell_rectangle.height);
2561 /* the last row has to clear it's bottom cell spacing too */
2562 if (clist_row == clist->row_list_end->data)
2564 cell_rectangle.y += clist->row_height + CELL_SPACING;
2566 gdk_draw_rectangle (clist->clist_window,
2567 widget->style->base_gc[GTK_STATE_NORMAL],
2571 cell_rectangle.width,
2572 cell_rectangle.height);
2575 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
2576 gdk_draw_rectangle (clist->clist_window,
2581 row_rectangle.width,
2582 row_rectangle.height);
2584 gdk_window_clear_area (clist->clist_window,
2587 row_rectangle.width,
2588 row_rectangle.height);
2591 /* iterate and draw all the columns (row cells) and draw their contents */
2592 for (i = 0; i < clist->columns; i++)
2594 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
2595 clip_rectangle.width = clist->column[i].area.width;
2597 /* calculate clipping region clipping region */
2600 rect = &clip_rectangle;
2604 if (!gdk_rectangle_intersect (area, &clip_rectangle, &intersect_rectangle))
2606 rect = &intersect_rectangle;
2609 /* calculate real width for column justification */
2610 switch (clist_row->cell[i].type)
2612 case GTK_CELL_EMPTY:
2617 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2618 GTK_CELL_TEXT (clist_row->cell[i])->text);
2621 case GTK_CELL_PIXMAP:
2622 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
2623 pixmap_width = width;
2626 case GTK_CELL_PIXTEXT:
2627 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
2628 pixmap_width = width;
2629 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2630 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2631 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2634 case GTK_CELL_WIDGET:
2644 switch (clist->column[i].justification)
2646 case GTK_JUSTIFY_LEFT:
2647 offset = clip_rectangle.x;
2650 case GTK_JUSTIFY_RIGHT:
2651 offset = (clip_rectangle.x + clip_rectangle.width) - width;
2654 case GTK_JUSTIFY_CENTER:
2655 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2658 case GTK_JUSTIFY_FILL:
2659 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2667 /* Draw Text or Pixmap */
2668 switch (clist_row->cell[i].type)
2670 case GTK_CELL_EMPTY:
2675 gdk_gc_set_clip_rectangle (fg_gc, rect);
2677 gdk_draw_string (clist->clist_window,
2678 widget->style->font,
2680 offset + clist_row->cell[i].horizontal,
2681 row_rectangle.y + clist->row_center_offset +
2682 clist_row->cell[i].vertical,
2683 GTK_CELL_TEXT (clist_row->cell[i])->text);
2685 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2688 case GTK_CELL_PIXMAP:
2691 xdest = offset + clist_row->cell[i].horizontal;
2692 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2693 clist_row->cell[i].vertical;
2695 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2697 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
2698 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2700 gdk_draw_pixmap (clist->clist_window,
2702 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2706 pixmap_width, height);
2708 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2710 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2711 gdk_gc_set_clip_mask (fg_gc, NULL);
2715 case GTK_CELL_PIXTEXT:
2716 /* draw the pixmap */
2719 xdest = offset + clist_row->cell[i].horizontal;
2720 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2721 clist_row->cell[i].vertical;
2723 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2725 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
2726 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2729 gdk_draw_pixmap (clist->clist_window,
2731 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2735 pixmap_width, height);
2737 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2739 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2741 /* draw the string */
2742 gdk_gc_set_clip_rectangle (fg_gc, rect);
2744 gdk_draw_string (clist->clist_window,
2745 widget->style->font,
2747 offset + clist_row->cell[i].horizontal,
2748 row_rectangle.y + clist->row_center_offset +
2749 clist_row->cell[i].vertical,
2750 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2752 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2756 case GTK_CELL_WIDGET:
2769 draw_rows (GtkCList * clist,
2770 GdkRectangle * area)
2773 GtkCListRow *clist_row;
2774 int i, first_row, last_row;
2776 g_return_if_fail (clist != NULL);
2777 g_return_if_fail (GTK_IS_CLIST (clist));
2779 if (clist->row_height == 0 ||
2780 !GTK_WIDGET_DRAWABLE (clist))
2785 first_row = ROW_FROM_YPIXEL (clist, area->y);
2786 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
2790 first_row = ROW_FROM_YPIXEL (clist, 0);
2791 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
2794 /* this is a small special case which exposes the bottom cell line
2795 * on the last row -- it might go away if I change the wall the cell spacings
2797 if (clist->rows == first_row)
2800 list = g_list_nth (clist->row_list, first_row);
2804 clist_row = list->data;
2810 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
2811 (clist, area, i, clist_row);
2816 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
2821 * size_allocate_title_buttons
2822 * size_allocate_columns
2825 size_allocate_title_buttons (GtkCList * clist)
2827 gint i, last_button = 0;
2828 GtkAllocation button_allocation;
2830 if (!GTK_WIDGET_REALIZED (clist))
2833 button_allocation.x = clist->hoffset;
2834 button_allocation.y = 0;
2835 button_allocation.width = 0;
2836 button_allocation.height = clist->column_title_area.height;
2838 for (i = 0; i < clist->columns; i++)
2840 button_allocation.width += clist->column[i].area.width;
2842 if (i == clist->columns - 1)
2843 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
2845 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
2847 if (i == (clist->columns - 1) || clist->column[i + 1].button)
2849 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
2850 button_allocation.x += button_allocation.width;
2851 button_allocation.width = 0;
2853 gdk_window_show (clist->column[last_button].window);
2854 gdk_window_move_resize (clist->column[last_button].window,
2855 button_allocation.x - (DRAG_WIDTH / 2),
2856 0, DRAG_WIDTH, clist->column_title_area.height);
2858 last_button = i + 1;
2862 gdk_window_hide (clist->column[i].window);
2868 size_allocate_columns (GtkCList * clist)
2870 gint i, xoffset = 0;
2872 for (i = 0; i < clist->columns; i++)
2874 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
2876 if (i == clist->columns - 1)
2880 if (clist->column[i].width_set)
2882 width = clist->column[i].width;
2886 if (clist->column[i].title)
2887 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2888 clist->column[i].title);
2893 clist->column[i].area.width = MAX (width,
2894 clist->clist_window_width -
2895 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
2900 clist->column[i].area.width = clist->column[i].width;
2903 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
2912 * get_selection_info
2915 toggle_row (GtkCList * clist,
2918 GdkEventButton * event)
2922 GtkCListRow *clist_row, *selected_row;
2925 list = clist->row_list;
2926 selected_row = NULL;
2928 switch (clist->selection_mode)
2930 case GTK_SELECTION_SINGLE:
2933 clist_row = list->data;
2937 selected_row = clist_row;
2938 else if (clist_row->state == GTK_STATE_SELECTED)
2939 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2945 if (selected_row && selected_row->state == GTK_STATE_SELECTED)
2946 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2947 row, column, event);
2949 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2950 row, column, event);
2954 case GTK_SELECTION_BROWSE:
2957 clist_row = list->data;
2960 if (i != row && clist_row->state == GTK_STATE_SELECTED)
2961 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2966 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2967 row, column, event);
2971 case GTK_SELECTION_MULTIPLE:
2972 clist_row = (g_list_nth (clist->row_list, row))->data;
2974 if (clist_row->state == GTK_STATE_SELECTED)
2975 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2976 row, column, event);
2978 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2979 row, column, event);
2983 case GTK_SELECTION_EXTENDED:
2992 select_row (GtkCList * clist,
2995 GdkEventButton * event)
2999 GtkCListRow *clist_row;
3001 switch (clist->selection_mode)
3003 case GTK_SELECTION_SINGLE:
3004 case GTK_SELECTION_BROWSE:
3006 list = clist->row_list;
3009 clist_row = list->data;
3012 if (row != i && clist_row->state == GTK_STATE_SELECTED)
3013 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3019 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3020 row, column, event);
3023 case GTK_SELECTION_MULTIPLE:
3024 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3025 row, column, event);
3029 case GTK_SELECTION_EXTENDED:
3038 unselect_row (GtkCList * clist,
3041 GdkEventButton * event)
3043 switch (clist->selection_mode)
3045 case GTK_SELECTION_SINGLE:
3046 case GTK_SELECTION_BROWSE:
3047 case GTK_SELECTION_MULTIPLE:
3048 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3049 row, column, event);
3052 case GTK_SELECTION_EXTENDED:
3061 real_select_row (GtkCList * clist,
3064 GdkEventButton * event)
3066 GtkCListRow *clist_row;
3068 g_return_if_fail (clist != NULL);
3070 if (row < 0 || row > (clist->rows - 1))
3073 clist_row = (g_list_nth (clist->row_list, row))->data;
3075 if (clist_row->state == GTK_STATE_NORMAL)
3077 clist_row->state = GTK_STATE_SELECTED;
3078 clist->selection = g_list_append (clist->selection, (gpointer) row);
3080 if (!GTK_CLIST_FROZEN (clist)
3081 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3082 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
3083 (clist, NULL, row, clist_row);
3088 real_unselect_row (GtkCList * clist,
3091 GdkEventButton * event)
3093 GtkCListRow *clist_row;
3095 g_return_if_fail (clist != NULL);
3097 if (row < 0 || row > (clist->rows - 1))
3100 clist_row = (g_list_nth (clist->row_list, row))->data;
3102 if (clist_row->state == GTK_STATE_SELECTED)
3104 clist_row->state = GTK_STATE_NORMAL;
3105 clist->selection = g_list_remove (clist->selection, (gpointer) row);
3107 if (!GTK_CLIST_FROZEN (clist)
3108 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3109 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
3110 (clist, NULL, row, clist_row);
3115 get_selection_info (GtkCList * clist,
3123 g_return_val_if_fail (clist != NULL, 0);
3125 /* bounds checking, return false if the user clicked
3126 * on a blank area */
3127 trow = ROW_FROM_YPIXEL (clist, y);
3128 if (trow >= clist->rows)
3134 tcol = COLUMN_FROM_XPIXEL (clist, x);
3135 if (tcol >= clist->columns)
3145 gtk_clist_get_selection_info (GtkCList *clist,
3151 g_return_val_if_fail (clist != NULL, 0);
3152 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3153 return get_selection_info (clist, x, y, row, column);
3163 draw_xor_line (GtkCList * clist)
3167 g_return_if_fail (clist != NULL);
3169 widget = GTK_WIDGET (clist);
3171 gdk_draw_line (widget->window, clist->xor_gc,
3173 widget->style->klass->ythickness,
3175 clist->column_title_area.height + clist->clist_window_height + 1);
3178 /* this function returns the new width of the column being resized given
3179 * the column and x position of the cursor; the x cursor position is passed
3180 * in as a pointer and automagicly corrected if it's beyond min/max limits */
3182 new_column_width (GtkCList * clist,
3191 /* first translate the x position from widget->window
3192 * to clist->clist_window */
3193 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3195 /* rx is x from the list beginning */
3196 rx = cx - clist->hoffset;
3198 /* you can't shrink a column to less than its minimum width */
3199 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
3201 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
3202 GTK_WIDGET (clist)->style->klass->xthickness;
3203 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3204 rx = cx - clist->hoffset;
3207 if (cx > clist->clist_window_width)
3212 /* calculate new column width making sure it doesn't end up
3213 * less than the minimum width */
3214 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
3215 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
3216 if (width < COLUMN_MIN_WIDTH)
3217 width = COLUMN_MIN_WIDTH;
3222 /* this will do more later */
3224 resize_column (GtkCList * clist,
3228 gtk_clist_set_column_width (clist, column, width);
3233 column_button_create (GtkCList * clist,
3238 button = clist->column[column].button = gtk_button_new ();
3239 gtk_widget_set_parent (button, GTK_WIDGET (clist));
3240 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
3241 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
3243 gtk_signal_connect (GTK_OBJECT (button),
3245 (GtkSignalFunc) column_button_clicked,
3248 gtk_widget_show (button);
3252 column_button_clicked (GtkWidget * widget,
3258 g_return_if_fail (widget != NULL);
3259 g_return_if_fail (GTK_IS_CLIST (data));
3261 clist = GTK_CLIST (data);
3263 /* find the column who's button was pressed */
3264 for (i = 0; i < clist->columns; i++)
3265 if (clist->column[i].button == widget)
3268 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
3277 * vadjustment_changed
3278 * hadjustment_changed
3279 * vadjustment_value_changed
3280 * hadjustment_value_changed
3283 create_scrollbars (GtkCList * clist)
3285 GtkAdjustment *adjustment;
3287 clist->vscrollbar = gtk_vscrollbar_new (NULL);
3288 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
3290 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3291 (GtkSignalFunc) vadjustment_changed,
3294 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3295 (GtkSignalFunc) vadjustment_value_changed,
3298 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
3299 gtk_widget_show (clist->vscrollbar);
3301 clist->hscrollbar = gtk_hscrollbar_new (NULL);
3302 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
3304 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3305 (GtkSignalFunc) hadjustment_changed,
3308 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3309 (GtkSignalFunc) hadjustment_value_changed,
3312 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
3313 gtk_widget_show (clist->hscrollbar);
3317 adjust_scrollbars (GtkCList * clist)
3319 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
3320 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
3321 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
3322 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
3323 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
3325 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
3327 GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
3328 clist->clist_window_height);
3329 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
3333 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
3334 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
3335 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
3336 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
3337 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
3339 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
3341 GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
3342 clist->clist_window_width);
3343 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
3347 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
3348 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3350 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3352 gtk_widget_hide (clist->vscrollbar);
3353 gtk_widget_queue_resize (GTK_WIDGET (clist));
3358 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3360 gtk_widget_show (clist->vscrollbar);
3361 gtk_widget_queue_resize (GTK_WIDGET (clist));
3365 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
3366 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3368 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3370 gtk_widget_hide (clist->hscrollbar);
3371 gtk_widget_queue_resize (GTK_WIDGET (clist));
3376 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3378 gtk_widget_show (clist->hscrollbar);
3379 gtk_widget_queue_resize (GTK_WIDGET (clist));
3383 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
3384 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
3388 vadjustment_changed (GtkAdjustment * adjustment,
3393 g_return_if_fail (adjustment != NULL);
3394 g_return_if_fail (data != NULL);
3396 clist = GTK_CLIST (data);
3400 hadjustment_changed (GtkAdjustment * adjustment,
3405 g_return_if_fail (adjustment != NULL);
3406 g_return_if_fail (data != NULL);
3408 clist = GTK_CLIST (data);
3412 check_exposures (GtkCList *clist)
3416 if (!GTK_WIDGET_REALIZED (clist))
3419 /* Make sure graphics expose events are processed before scrolling
3421 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
3423 gtk_widget_event (GTK_WIDGET (clist), event);
3424 if (event->expose.count == 0)
3426 gdk_event_free (event);
3429 gdk_event_free (event);
3434 vadjustment_value_changed (GtkAdjustment * adjustment,
3441 g_return_if_fail (adjustment != NULL);
3442 g_return_if_fail (data != NULL);
3443 g_return_if_fail (GTK_IS_CLIST (data));
3445 clist = GTK_CLIST (data);
3447 if (!GTK_WIDGET_DRAWABLE (clist))
3450 value = adjustment->value;
3452 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
3454 if (value > -clist->voffset)
3457 diff = value + clist->voffset;
3459 /* we have to re-draw the whole screen here... */
3460 if (diff >= clist->clist_window_height)
3462 clist->voffset = -value;
3463 draw_rows (clist, NULL);
3467 if ((diff != 0) && (diff != clist->clist_window_height))
3468 gdk_window_copy_area (clist->clist_window,
3471 clist->clist_window,
3474 clist->clist_window_width,
3475 clist->clist_window_height - diff);
3478 area.y = clist->clist_window_height - diff;
3479 area.width = clist->clist_window_width;
3485 diff = -clist->voffset - value;
3487 /* we have to re-draw the whole screen here... */
3488 if (diff >= clist->clist_window_height)
3490 clist->voffset = -value;
3491 draw_rows (clist, NULL);
3495 if ((diff != 0) && (diff != clist->clist_window_height))
3496 gdk_window_copy_area (clist->clist_window,
3499 clist->clist_window,
3502 clist->clist_window_width,
3503 clist->clist_window_height - diff);
3507 area.width = clist->clist_window_width;
3512 clist->voffset = -value;
3513 if ((diff != 0) && (diff != clist->clist_window_height))
3514 check_exposures (clist);
3517 draw_rows (clist, &area);
3521 hadjustment_value_changed (GtkAdjustment * adjustment,
3526 gint i, diff, value;
3528 g_return_if_fail (adjustment != NULL);
3529 g_return_if_fail (data != NULL);
3530 g_return_if_fail (GTK_IS_CLIST (data));
3532 clist = GTK_CLIST (data);
3534 if (!GTK_WIDGET_DRAWABLE (clist))
3537 value = adjustment->value;
3539 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
3541 /* move the column buttons and resize windows */
3542 for (i = 0; i < clist->columns; i++)
3544 if (clist->column[i].button)
3546 clist->column[i].button->allocation.x -= value + clist->hoffset;
3548 if (clist->column[i].button->window)
3550 gdk_window_move (clist->column[i].button->window,
3551 clist->column[i].button->allocation.x,
3552 clist->column[i].button->allocation.y);
3554 if (clist->column[i].window)
3555 gdk_window_move (clist->column[i].window,
3556 clist->column[i].button->allocation.x +
3557 clist->column[i].button->allocation.width -
3558 (DRAG_WIDTH / 2), 0);
3563 if (value > -clist->hoffset)
3566 diff = value + clist->hoffset;
3568 /* we have to re-draw the whole screen here... */
3569 if (diff >= clist->clist_window_width)
3571 clist->hoffset = -value;
3572 draw_rows (clist, NULL);
3576 if ((diff != 0) && (diff != clist->clist_window_width))
3577 gdk_window_copy_area (clist->clist_window,
3580 clist->clist_window,
3583 clist->clist_window_width - diff,
3584 clist->clist_window_height);
3586 area.x = clist->clist_window_width - diff;
3589 area.height = clist->clist_window_height;
3594 diff = -clist->hoffset - value;
3596 /* we have to re-draw the whole screen here... */
3597 if (diff >= clist->clist_window_width)
3599 clist->hoffset = -value;
3600 draw_rows (clist, NULL);
3604 if ((diff != 0) && (diff != clist->clist_window_width))
3605 gdk_window_copy_area (clist->clist_window,
3608 clist->clist_window,
3611 clist->clist_window_width - diff,
3612 clist->clist_window_height);
3617 area.height = clist->clist_window_height;
3620 clist->hoffset = -value;
3621 if ((diff != 0) && (diff != clist->clist_window_width))
3622 check_exposures (clist);
3625 draw_rows (clist, &area);
3629 * Memory Allocation/Distruction Routines for GtkCList stuctures
3641 static GtkCListColumn *
3642 columns_new (GtkCList * clist)
3645 GtkCListColumn *column;
3647 column = g_new (GtkCListColumn, clist->columns);
3649 for (i = 0; i < clist->columns; i++)
3651 column[i].area.x = 0;
3652 column[i].area.y = 0;
3653 column[i].area.width = 0;
3654 column[i].area.height = 0;
3655 column[i].title = NULL;
3656 column[i].button = NULL;
3657 column[i].window = NULL;
3658 column[i].width = 0;
3659 column[i].width_set = FALSE;
3660 column[i].justification = GTK_JUSTIFY_LEFT;
3667 column_title_new (GtkCList * clist,
3671 if (clist->column[column].title)
3672 g_free (clist->column[column].title);
3674 clist->column[column].title = g_strdup (title);
3678 columns_delete (GtkCList * clist)
3682 for (i = 0; i < clist->columns; i++)
3683 if (clist->column[i].title)
3684 g_free (clist->column[i].title);
3686 g_free (clist->column);
3689 static GtkCListRow *
3690 row_new (GtkCList * clist)
3693 GtkCListRow *clist_row;
3695 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
3696 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3698 for (i = 0; i < clist->columns; i++)
3700 clist_row->cell[i].type = GTK_CELL_EMPTY;
3701 clist_row->cell[i].vertical = 0;
3702 clist_row->cell[i].horizontal = 0;
3705 clist_row->fg_set = FALSE;
3706 clist_row->bg_set = FALSE;
3707 clist_row->state = GTK_STATE_NORMAL;
3708 clist_row->data = NULL;
3709 clist_row->destroy = NULL;
3715 row_delete (GtkCList * clist,
3716 GtkCListRow * clist_row)
3720 for (i = 0; i < clist->columns; i++)
3721 cell_empty (clist, clist_row, i);
3723 if (clist_row->destroy)
3724 clist_row->destroy (clist_row->data);
3726 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
3727 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
3731 cell_empty (GtkCList * clist,
3732 GtkCListRow * clist_row,
3735 switch (clist_row->cell[column].type)
3737 case GTK_CELL_EMPTY:
3741 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3744 case GTK_CELL_PIXMAP:
3745 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3746 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3747 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3750 case GTK_CELL_PIXTEXT:
3751 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3752 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3753 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3754 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3757 case GTK_CELL_WIDGET:
3765 clist_row->cell[column].type = GTK_CELL_EMPTY;
3769 cell_set_text (GtkCList * clist,
3770 GtkCListRow * clist_row,
3774 cell_empty (clist, clist_row, column);
3778 clist_row->cell[column].type = GTK_CELL_TEXT;
3779 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3784 cell_set_pixmap (GtkCList * clist,
3785 GtkCListRow * clist_row,
3790 cell_empty (clist, clist_row, column);
3794 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3795 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3796 /* We set the mask even if it is NULL */
3797 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3802 cell_set_pixtext (GtkCList * clist,
3803 GtkCListRow * clist_row,
3810 cell_empty (clist, clist_row, column);
3814 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3815 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3816 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3817 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3818 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3822 /* Fill in data after widget has correct style */
3825 add_style_data (GtkCList * clist)
3829 widget = GTK_WIDGET(clist);
3831 /* text properties */
3832 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
3834 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
3835 clist->row_center_offset = widget->style->font->ascent + 1.5;
3840 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
3841 GTK_WIDGET (clist) ->style->font->descent + 1);
3842 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;