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 Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "../config.h"
23 /* the width of the column resize windows */
26 /* minimum allowed width of a column */
27 #define COLUMN_MIN_WIDTH 5
29 /* this defigns the base grid spacing */
30 #define CELL_SPACING 1
32 /* added the horizontal space at the beginning and end of a row*/
33 #define COLUMN_INSET 3
35 /* scrollbar spacing class macro */
36 #define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
38 /* gives the top pixel of the given row in context of
39 * the clist's voffset */
40 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
41 (((row) + 1) * CELL_SPACING) + \
44 /* returns the row index from a y pixel location in the
45 * context of the clist's voffset */
46 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
47 ((clist)->row_height + CELL_SPACING))
49 /* gives the left pixel of the given column in context of
50 * the clist's hoffset */
51 #define COLUMN_LEFT_YPIXEL(clist, column) ((clist)->column[(column)].area.x + \
54 /* returns the column index from a x pixel location in the
55 * context of the clist's hoffset */
57 COLUMN_FROM_XPIXEL (GtkCList * clist,
62 for (i = 0; i < clist->columns; i++)
64 cx = clist->column[i].area.x + clist->hoffset;
66 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
67 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
75 /* returns the top pixel of the given row in the context of
77 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
79 /* returns the left pixel of the given column in the context of
81 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
83 /* returns the total height of the list */
84 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
85 (CELL_SPACING * ((clist)->rows + 1)))
87 /* returns the total width of the list */
88 #define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
89 (clist)->column[(clist)->columns - 1].area.width + \
90 COLUMN_INSET + CELL_SPACING)
102 typedef void (*GtkCListSignal1) (GtkObject * object,
105 GdkEventButton * arg3,
108 typedef void (*GtkCListSignal2) (GtkObject * object,
113 /* GtkCList Methods */
114 static void gtk_clist_class_init (GtkCListClass * klass);
115 static void gtk_clist_init (GtkCList * clist);
117 static gint gtk_clist_row_isvisable (GtkCList * clist,
120 static void gtk_clist_draw_row (GtkCList * clist,
123 GtkCListRow * clist_row);
125 static void gtk_clist_draw_rows (GtkCList * clist,
126 GdkRectangle * area);
128 static gint gtk_clist_get_selection_info (GtkCList * clist,
134 static void gtk_clist_real_select_row (GtkCList * clist,
137 GdkEventButton * event);
138 static void gtk_clist_real_unselect_row (GtkCList * clist,
141 GdkEventButton * event);
143 static void gtk_clist_size_allocate_title_buttons (GtkCList * clist);
144 static void gtk_clist_size_allocate_columns (GtkCList * clist);
147 /* GtkObject Methods */
148 static void gtk_clist_destroy (GtkObject * object);
151 /* GtkWidget Methods */
152 static void gtk_clist_realize (GtkWidget * widget);
153 static void gtk_clist_unrealize (GtkWidget * widget);
154 static void gtk_clist_map (GtkWidget * widget);
155 static void gtk_clist_unmap (GtkWidget * widget);
156 static void gtk_clist_draw (GtkWidget * widget,
157 GdkRectangle * area);
158 static gint gtk_clist_expose (GtkWidget * widget,
159 GdkEventExpose * event);
160 static gint gtk_clist_button_press (GtkWidget * widget,
161 GdkEventButton * event);
163 static void gtk_clist_size_request (GtkWidget * widget,
164 GtkRequisition * requisition);
165 static void gtk_clist_size_allocate (GtkWidget * widget,
166 GtkAllocation * allocation);
169 /* GtkContainer Methods */
170 static void gtk_clist_foreach (GtkContainer * container,
171 GtkCallback callback,
172 gpointer callback_data);
176 static void gtk_clist_column_button_realize (GtkWidget * widget,
178 static void gtk_clist_column_button_clicked (GtkWidget * widget,
183 static void gtk_clist_adjust_scrollbars (GtkCList * clist);
184 static void gtk_clist_vadjustment_changed (GtkAdjustment * adjustment,
186 static void gtk_clist_vadjustment_value_changed (GtkAdjustment * adjustment,
188 static void gtk_clist_hadjustment_changed (GtkAdjustment * adjustment,
190 static void gtk_clist_hadjustment_value_changed (GtkAdjustment * adjustment,
194 /* Memory Allocation/Distruction Routines */
195 static GtkCListColumn *gtk_clist_columns_new (GtkCList * clist);
197 static void gtk_clist_column_title_new (GtkCList * clist,
200 static void gtk_clist_columns_delete (GtkCList * clist);
202 static GtkCListRow *gtk_clist_row_new (GtkCList * clist);
204 static void gtk_clist_row_delete (GtkCList * clist,
205 GtkCListRow * clist_row);
206 static void gtk_clist_cell_empty (GtkCList * clist,
207 GtkCListRow * clist_row,
209 static void gtk_clist_cell_set_text (GtkCList * clist,
210 GtkCListRow * clist_row,
213 static void gtk_clist_cell_set_pixmap (GtkCList * clist,
214 GtkCListRow * clist_row,
218 static void gtk_clist_cell_set_pixtext (GtkCList * clist,
219 GtkCListRow * clist_row,
227 static void gtk_clist_marshal_signal_1 (GtkObject * object,
231 static void gtk_clist_marshal_signal_2 (GtkObject * object,
237 static GtkContainerClass *parent_class = NULL;
238 static gint clist_signals[LAST_SIGNAL] = {0};
242 gtk_clist_get_type ()
244 static guint clist_type = 0;
248 GtkTypeInfo clist_info =
252 sizeof (GtkCListClass),
253 (GtkClassInitFunc) gtk_clist_class_init,
254 (GtkObjectInitFunc) gtk_clist_init,
258 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
265 gtk_clist_class_init (GtkCListClass * klass)
267 GtkObjectClass *object_class;
268 GtkWidgetClass *widget_class;
269 GtkContainerClass *container_class;
271 object_class = (GtkObjectClass *) klass;
272 widget_class = (GtkWidgetClass *) klass;
273 container_class = (GtkContainerClass *) klass;
275 parent_class = gtk_type_class (gtk_container_get_type ());
277 clist_signals[SELECT_ROW] =
278 gtk_signal_new ("select_row",
281 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
282 gtk_clist_marshal_signal_1,
283 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
284 clist_signals[UNSELECT_ROW] =
285 gtk_signal_new ("unselect_row",
288 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
289 gtk_clist_marshal_signal_1,
290 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
291 clist_signals[CLICK_COLUMN] =
292 gtk_signal_new ("click_column",
295 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
296 gtk_clist_marshal_signal_2,
297 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
299 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
301 object_class->destroy = gtk_clist_destroy;
303 widget_class->realize = gtk_clist_realize;
304 widget_class->unrealize = gtk_clist_unrealize;
305 widget_class->map = gtk_clist_map;
306 widget_class->unmap = gtk_clist_unmap;
307 widget_class->draw = gtk_clist_draw;
308 widget_class->button_press_event = gtk_clist_button_press;
309 widget_class->expose_event = gtk_clist_expose;
310 widget_class->size_request = gtk_clist_size_request;
311 widget_class->size_allocate = gtk_clist_size_allocate;
313 container_class->add = NULL;
314 container_class->remove = NULL;
315 container_class->foreach = gtk_clist_foreach;
317 klass->select_row = gtk_clist_real_select_row;
318 klass->unselect_row = gtk_clist_real_unselect_row;
319 klass->click_column = NULL;
321 klass->scrollbar_spacing = 5;
325 gtk_clist_marshal_signal_1 (GtkObject * object,
330 GtkCListSignal1 rfunc;
332 rfunc = (GtkCListSignal1) func;
334 (*rfunc) (object, GTK_VALUE_INT (args[0]),
335 GTK_VALUE_INT (args[1]),
336 GTK_VALUE_POINTER (args[2]),
341 gtk_clist_marshal_signal_2 (GtkObject * object,
346 GtkCListSignal2 rfunc;
348 rfunc = (GtkCListSignal2) func;
350 (*rfunc) (object, GTK_VALUE_INT (args[0]),
355 gtk_clist_init (GtkCList * clist)
359 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
360 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
363 clist->row_center_offset = 0;
364 clist->row_height = 0;
365 clist->row_list = NULL;
366 clist->row_list_end = NULL;
370 clist->column_title_area.x = 0;
371 clist->column_title_area.y = 0;
372 clist->column_title_area.width = 0;
373 clist->column_title_area.height = 0;
375 clist->clist_window = NULL;
376 clist->clist_window_width = 0;
377 clist->clist_window_height = 0;
382 clist->shadow_type = GTK_SHADOW_IN;
383 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
384 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
386 clist->cursor_drag = NULL;
387 clist->xor_gc = NULL;
392 clist->selection_mode = GTK_SELECTION_SINGLE;
393 clist->selection = NULL;
397 gtk_clist_new (int columns,
402 GtkAdjustment *adjustment;
405 if (columns < 1 || titles == NULL)
408 clist = gtk_type_new (gtk_clist_get_type ());
410 /* initalize memory chunks */
411 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
412 sizeof (GtkCListRow),
413 1024, G_ALLOC_AND_FREE);
414 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
415 sizeof (GtkCell) * columns,
416 1024, G_ALLOC_AND_FREE);
418 /* set number of columns, allocate memory */
419 clist->columns = columns;
420 clist->column = gtk_clist_columns_new (clist);
422 /* create column button and connect signals */
423 for (i = 0; i < columns; i++)
425 clist->column[i].button = gtk_button_new ();
426 gtk_widget_set_parent (clist->column[i].button, GTK_WIDGET (clist));
428 gtk_signal_connect_after (GTK_OBJECT (clist->column[i].button),
430 (GtkSignalFunc) gtk_clist_column_button_realize,
433 gtk_signal_connect (GTK_OBJECT (clist->column[i].button),
435 (GtkSignalFunc) gtk_clist_column_button_clicked,
438 /* set column title */
439 gtk_clist_set_column_title (clist, i, titles[i]);
441 clist->column[i].width =
442 gdk_string_width (GTK_WIDGET (clist)->style->font, clist->column[i].title);
444 gtk_widget_show (clist->column[i].button);
448 /* create and connect scrollbars */
449 clist->vscrollbar = gtk_vscrollbar_new (NULL);
450 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
452 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
453 (GtkSignalFunc) gtk_clist_vadjustment_changed,
456 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
457 (GtkSignalFunc) gtk_clist_vadjustment_value_changed,
460 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
461 gtk_widget_show (clist->vscrollbar);
463 clist->hscrollbar = gtk_hscrollbar_new (NULL);
464 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
466 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
467 (GtkSignalFunc) gtk_clist_hadjustment_changed,
470 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
471 (GtkSignalFunc) gtk_clist_hadjustment_value_changed,
474 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
475 gtk_widget_show (clist->hscrollbar);
477 return GTK_WIDGET (clist);
481 gtk_clist_set_border (GtkCList * clist,
482 GtkShadowType border)
484 g_return_if_fail (clist != NULL);
486 clist->shadow_type = border;
488 if (GTK_WIDGET_VISIBLE (clist))
489 gtk_widget_queue_resize (GTK_WIDGET (clist));
493 gtk_clist_set_selection_mode (GtkCList * clist,
494 GtkSelectionMode mode)
496 g_return_if_fail (clist != NULL);
498 clist->selection_mode = mode;
502 gtk_clist_freeze (GtkCList * clist)
504 g_return_if_fail (clist != NULL);
506 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
510 gtk_clist_thaw (GtkCList * clist)
512 g_return_if_fail (clist != NULL);
514 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
516 gtk_clist_adjust_scrollbars (clist);
517 gtk_clist_draw_rows (clist, NULL);
522 gtk_clist_set_column_title (GtkCList * clist,
526 GtkWidget *old_widget;
527 GtkWidget *alignment = NULL;
530 g_return_if_fail (clist != NULL);
532 if (column < 0 || column >= clist->columns)
535 gtk_clist_column_title_new (clist, column, title);
537 /* remove and destroy the old widget */
538 old_widget = GTK_BUTTON (clist->column[column].button)->child;
541 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
542 gtk_widget_destroy (old_widget);
545 switch (clist->column[column].justification)
547 case GTK_JUSTIFY_LEFT:
548 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
551 case GTK_JUSTIFY_RIGHT:
552 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
555 case GTK_JUSTIFY_CENTER:
556 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
559 case GTK_JUSTIFY_FILL:
560 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
566 label = gtk_label_new (clist->column[column].title);
567 gtk_container_add (GTK_CONTAINER (alignment), label);
568 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
569 gtk_widget_show (label);
570 gtk_widget_show (alignment);
575 gtk_clist_set_column_widget (GtkCList * clist,
579 GtkWidget *old_widget;
581 g_return_if_fail (clist != NULL);
583 if (column < 0 || column >= clist->columns)
586 gtk_clist_column_title_new (clist, column, NULL);
588 /* remove and destroy the old widget */
589 old_widget = GTK_BUTTON (clist->column[column].button)->child;
592 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
593 gtk_widget_destroy (old_widget);
596 /* add and show the widget */
599 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
600 gtk_widget_show (widget);
605 gtk_clist_set_column_justification (GtkCList * clist,
607 GtkJustification justification)
609 GtkWidget *alignment;
611 g_return_if_fail (clist != NULL);
613 if (column < 0 || column >= clist->columns)
616 clist->column[column].justification = justification;
618 /* change the alinment of the button title if it's not a
620 if (clist->column[column].title)
622 alignment = GTK_BUTTON (clist->column[column].button)->child;
624 switch (clist->column[column].justification)
626 case GTK_JUSTIFY_LEFT:
627 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
630 case GTK_JUSTIFY_RIGHT:
631 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
634 case GTK_JUSTIFY_CENTER:
635 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
638 case GTK_JUSTIFY_FILL:
639 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
647 if (!GTK_CLIST_FROZEN (clist))
648 gtk_clist_draw_rows (clist, NULL);
652 gtk_clist_set_column_width (GtkCList * clist,
656 g_return_if_fail (clist != NULL);
658 if (column < 0 || column >= clist->columns)
661 clist->column[column].width = width;
663 gtk_clist_size_allocate_title_buttons (clist);
665 if (!GTK_CLIST_FROZEN (clist))
667 gtk_clist_adjust_scrollbars (clist);
668 gtk_clist_draw_rows (clist, NULL);
673 gtk_clist_set_row_height (GtkCList * clist,
678 g_return_if_fail (clist != NULL);
681 clist->row_height = height;
685 GTK_CLIST_SET_FLAGS (clist, CLIST_ROW_HEIGHT_SET);
687 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
688 GTK_WIDGET (clist) ->style->font->descent + 1);
689 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
691 if (!GTK_CLIST_FROZEN (clist))
693 gtk_clist_adjust_scrollbars (clist);
694 gtk_clist_draw_rows (clist, NULL);
699 gtk_clist_moveto (GtkCList * clist,
707 g_return_if_fail (clist != NULL);
709 if (row < -1 || row >= clist->rows)
711 if (column < -1 || column >= clist->columns)
714 /* adjust vertical scrollbar */
717 x = ROW_TOP (clist, row) - (row_align * (clist->clist_window_height -
718 (clist->row_height + 2 * CELL_SPACING)));
721 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
722 else if (x > LIST_HEIGHT (clist) - clist->clist_window_height)
723 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
724 clist->clist_window_height;
726 GTK_RANGE (clist->vscrollbar)->adjustment->value = x;
728 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
732 /* adjust horizontal scrollbar */
735 y = COLUMN_LEFT (clist, column) - (col_align * (clist->clist_window_width -
736 clist->column[column].area.width +
737 2 * (CELL_SPACING + COLUMN_INSET)));
740 GTK_RANGE (clist->hscrollbar)->adjustment->value = 0.0;
741 else if (y > LIST_WIDTH (clist) - clist->clist_window_width)
742 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
743 clist->clist_window_width;
745 GTK_RANGE (clist->hscrollbar)->adjustment->value = y;
747 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
753 gtk_clist_set_text (GtkCList * clist,
758 GtkCListRow *clist_row;
760 g_return_if_fail (clist != NULL);
762 if (row < 0 || row >= clist->rows)
764 if (column < 0 || column >= clist->columns)
767 clist_row = (g_list_nth (clist->row_list, row))->data;
769 /* if text is null, then the cell is empty */
771 gtk_clist_cell_set_text (clist, clist_row, column, text);
773 gtk_clist_cell_empty (clist, clist_row, column);
775 /* redraw the list if it's not frozen */
776 if (!GTK_CLIST_FROZEN (clist))
778 if (gtk_clist_row_isvisable (clist, row))
779 gtk_clist_draw_row (clist, NULL, row, clist_row);
784 gtk_clist_set_pixmap (GtkCList * clist,
790 GtkCListRow *clist_row;
792 g_return_if_fail (clist != NULL);
794 if (row < 0 || row >= clist->rows)
796 if (column < 0 || column >= clist->columns)
799 clist_row = (g_list_nth (clist->row_list, row))->data;
801 gdk_pixmap_ref (pixmap);
802 gdk_pixmap_ref (mask);
803 gtk_clist_cell_set_pixmap (clist, clist_row, column, pixmap, mask);
805 /* redraw the list if it's not frozen */
806 if (!GTK_CLIST_FROZEN (clist))
808 if (gtk_clist_row_isvisable (clist, row))
809 gtk_clist_draw_row (clist, NULL, row, clist_row);
814 gtk_clist_set_pixtext (GtkCList * clist,
822 GtkCListRow *clist_row;
824 g_return_if_fail (clist != NULL);
826 if (row < 0 || row >= clist->rows)
828 if (column < 0 || column >= clist->columns)
831 clist_row = (g_list_nth (clist->row_list, row))->data;
833 gdk_pixmap_ref (pixmap);
834 gdk_pixmap_ref (mask);
835 gtk_clist_cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
837 /* redraw the list if it's not frozen */
838 if (!GTK_CLIST_FROZEN (clist))
840 if (gtk_clist_row_isvisable (clist, row))
841 gtk_clist_draw_row (clist, NULL, row, clist_row);
846 gtk_clist_set_foreground (GtkCList * clist,
850 GtkCListRow *clist_row;
852 g_return_if_fail (clist != NULL);
853 g_return_if_fail (color != NULL);
855 if (row < 0 || row >= clist->rows)
858 clist_row = (g_list_nth (clist->row_list, row))->data;
859 clist_row->foreground = *color;
861 if (!GTK_CLIST_FROZEN (clist))
862 if (gtk_clist_row_isvisable (clist, row))
863 gtk_clist_draw_row (clist, NULL, row, clist_row);
866 void gtk_clist_set_background (GtkCList * clist,
870 GtkCListRow *clist_row;
872 g_return_if_fail (clist != NULL);
873 g_return_if_fail (color != NULL);
875 if (row < 0 || row >= clist->rows)
878 clist_row = (g_list_nth (clist->row_list, row))->data;
879 clist_row->background = *color;
881 if (!GTK_CLIST_FROZEN (clist))
882 if (gtk_clist_row_isvisable (clist, row))
883 gtk_clist_draw_row (clist, NULL, row, clist_row);
887 gtk_clist_set_shift (GtkCList * clist,
893 GtkCListRow *clist_row;
895 g_return_if_fail (clist != NULL);
897 if (row < 0 || row >= clist->rows)
899 if (column < 0 || column >= clist->columns)
902 clist_row = (g_list_nth (clist->row_list, row))->data;
904 clist_row->cell[column].verticle = verticle;
905 clist_row->cell[column].horizontal = horizontal;
907 if (!GTK_CLIST_FROZEN (clist))
908 if (gtk_clist_row_isvisable (clist, row))
909 gtk_clist_draw_row (clist, NULL, row, clist_row);
913 gtk_clist_append (GtkCList * clist,
917 GtkCListRow *clist_row;
919 g_return_val_if_fail (clist != NULL, -1);
921 clist_row = gtk_clist_row_new (clist);
924 /* keeps track of the end of the list so the list
925 * doesn't have to be traversed every time a item is added */
926 if (!clist->row_list)
928 clist->row_list = g_list_append (clist->row_list, clist_row);
929 clist->row_list_end = clist->row_list;
931 /* check the selection mode to see if we should select
932 * the first row automaticly */
933 switch (clist->selection_mode)
935 case GTK_SELECTION_BROWSE:
936 gtk_clist_select_row (clist, 0, -1);
944 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
946 /* set the text in the row's columns */
948 for (i = 0; i < clist->columns; i++)
950 gtk_clist_cell_set_text (clist, clist_row, i, text[i]);
952 /* redraw the list if it's not frozen */
953 if (!GTK_CLIST_FROZEN (clist))
955 gtk_clist_adjust_scrollbars (clist);
957 if (gtk_clist_row_isvisable (clist, clist->rows - 1))
958 gtk_clist_draw_rows (clist, NULL);
961 /* return index of the row */
962 return clist->rows - 1;
966 gtk_clist_insert (GtkCList * clist,
971 GtkCListRow *clist_row;
973 g_return_if_fail (clist != NULL);
974 g_return_if_fail (text != NULL);
976 /* return if out of bounds */
977 if (row < 0 || row > (clist->rows - 1))
981 clist_row = gtk_clist_row_new (clist);
983 /* reset the row end pointer if we're inserting at the
985 if (row == clist->rows)
986 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
988 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
992 /* set the text in the row's columns */
994 for (i = 0; i < clist->columns; i++)
996 gtk_clist_cell_set_text (clist, clist_row, i, text[i]);
998 /* redraw the list if it isn't frozen */
999 if (!GTK_CLIST_FROZEN (clist))
1001 gtk_clist_adjust_scrollbars (clist);
1003 if (gtk_clist_row_isvisable (clist, row))
1004 gtk_clist_draw_rows (clist, NULL);
1009 gtk_clist_remove (GtkCList * clist,
1014 GtkCListRow *clist_row;
1016 g_return_if_fail (clist != NULL);
1018 /* return if out of bounds */
1019 if (row < 0 || row > (clist->rows - 1))
1022 was_visible = gtk_clist_row_isvisable (clist, row);
1024 /* get the row we're going to delete */
1025 list = g_list_nth (clist->row_list, row);
1026 clist_row = list->data;
1028 /* reset the row end pointer if we're removing at the
1029 * end of the list */
1030 if (row == clist->rows - 1)
1031 clist->row_list_end = list->prev;
1033 clist->row_list = g_list_remove (clist->row_list, clist_row);
1036 /* redraw the row if it isn't frozen */
1037 if (!GTK_CLIST_FROZEN (clist))
1039 gtk_clist_adjust_scrollbars (clist);
1042 gtk_clist_draw_rows (clist, NULL);
1045 if (clist_row->state == GTK_STATE_SELECTED)
1047 switch (clist->selection_mode)
1049 case GTK_SELECTION_BROWSE:
1050 if (row >= clist->rows)
1052 gtk_clist_select_row (clist, row, -1);
1059 /* remove from selection list */
1060 clist->selection = g_list_remove (clist->selection, clist_row);
1063 gtk_clist_row_delete (clist, clist_row);
1067 gtk_clist_clear (GtkCList * clist)
1070 GtkCListRow *clist_row;
1072 g_return_if_fail (clist != NULL);
1074 /* remove all the rows */
1075 list = clist->row_list;
1078 clist_row = list->data;
1081 gtk_clist_row_delete (clist, clist_row);
1083 g_list_free (clist->row_list);
1085 /* free up the selection list */
1086 g_list_free (clist->selection);
1088 clist->row_list = NULL;
1089 clist->row_list_end = NULL;
1090 clist->selection = NULL;
1094 /* zero-out the scrollbars */
1095 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1096 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1098 if (!GTK_CLIST_FROZEN (clist))
1100 gtk_clist_adjust_scrollbars (clist);
1101 gtk_clist_draw_rows (clist, NULL);
1106 gtk_clist_set_row_data (GtkCList * clist,
1110 GtkCListRow *clist_row;
1112 g_return_if_fail (clist != NULL);
1114 if (row < 0 || row > (clist->rows - 1))
1117 clist_row = (g_list_nth (clist->row_list, row))->data;
1118 clist_row->data = data;
1121 * re-send the selected signal if data is changed/added
1122 * so the application can respond to the new data --
1123 * this could be questionable behavior
1125 if (clist_row->state == GTK_STATE_SELECTED)
1126 gtk_clist_select_row (clist, 0, 0);
1130 gtk_clist_get_row_data (GtkCList * clist,
1133 GtkCListRow *clist_row;
1135 g_return_val_if_fail (clist != NULL, NULL);
1137 if (row < 0 || row > (clist->rows - 1))
1140 clist_row = (g_list_nth (clist->row_list, row))->data;
1141 return clist_row->data;
1145 gtk_clist_select_row (GtkCList * clist,
1149 g_return_if_fail (clist != NULL);
1151 if (row < 0 || row >= clist->rows)
1154 if (column < -1 || column >= clist->columns)
1157 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], row, column, NULL);
1161 gtk_clist_unselect_row (GtkCList * clist,
1165 g_return_if_fail (clist != NULL);
1167 if (row < 0 || row >= clist->rows)
1170 if (column < -1 || column >= clist->columns)
1173 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], row, column, NULL);
1177 gtk_clist_row_isvisable (GtkCList * clist,
1180 g_return_val_if_fail (clist != NULL, 0);
1182 if (row < 0 || row >= clist->rows)
1185 if (clist->row_height == 0)
1188 if (row < ROW_FROM_YPIXEL (clist, 0))
1191 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
1198 gtk_clist_get_vadjustment (GtkCList * clist)
1200 g_return_val_if_fail (clist != NULL, NULL);
1201 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1203 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
1207 gtk_clist_get_hadjustment (GtkCList * clist)
1209 g_return_val_if_fail (clist != NULL, NULL);
1210 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1212 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
1216 gtk_clist_set_policy (GtkCList * clist,
1217 GtkPolicyType vscrollbar_policy,
1218 GtkPolicyType hscrollbar_policy)
1220 g_return_if_fail (clist != NULL);
1221 g_return_if_fail (GTK_IS_CLIST (clist));
1223 if (clist->vscrollbar_policy != vscrollbar_policy)
1225 clist->vscrollbar_policy = vscrollbar_policy;
1227 if (GTK_WIDGET (clist)->parent)
1228 gtk_widget_queue_resize (GTK_WIDGET (clist));
1231 if (clist->hscrollbar_policy != hscrollbar_policy)
1233 clist->hscrollbar_policy = hscrollbar_policy;
1235 if (GTK_WIDGET (clist)->parent)
1236 gtk_widget_queue_resize (GTK_WIDGET (clist));
1241 gtk_clist_destroy (GtkObject * object)
1246 g_return_if_fail (object != NULL);
1247 g_return_if_fail (GTK_IS_CLIST (object));
1249 clist = GTK_CLIST (object);
1251 /* freeze the list */
1252 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1254 /* get rid of all the rows */
1255 gtk_clist_clear (clist);
1257 /* destroy the scrollbars */
1258 gtk_widget_destroy (clist->vscrollbar);
1259 gtk_widget_destroy (clist->hscrollbar);
1261 /* get rid of all the column buttons */
1262 for (i = 0; i < clist->columns; i++)
1263 gtk_widget_destroy (clist->column[i].button);
1265 gtk_clist_columns_delete (clist);
1267 /* get rid of the memory chunks */
1268 g_mem_chunk_destroy (clist->cell_mem_chunk);
1269 g_mem_chunk_destroy (clist->row_mem_chunk);
1271 if (GTK_OBJECT_CLASS (parent_class)->destroy)
1272 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1276 gtk_clist_realize (GtkWidget * widget)
1279 GdkWindowAttr attributes;
1280 gint attributes_mask;
1283 g_return_if_fail (widget != NULL);
1284 g_return_if_fail (GTK_IS_CLIST (widget));
1286 clist = GTK_CLIST (widget);
1288 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1290 attributes.window_type = GDK_WINDOW_CHILD;
1291 attributes.x = widget->allocation.x;
1292 attributes.y = widget->allocation.y;
1293 attributes.width = widget->allocation.width;
1294 attributes.height = widget->allocation.height;
1295 attributes.wclass = GDK_INPUT_OUTPUT;
1296 attributes.visual = gtk_widget_get_visual (widget);
1297 attributes.colormap = gtk_widget_get_colormap (widget);
1298 attributes.event_mask = gtk_widget_get_events (widget);
1299 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1300 GDK_BUTTON_PRESS_MASK |
1301 GDK_BUTTON_RELEASE_MASK |
1302 GDK_KEY_PRESS_MASK);
1303 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1307 widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
1308 gdk_window_set_user_data (widget->window, clist);
1310 widget->style = gtk_style_attach (widget->style, widget->window);
1312 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1314 /* column-title window */
1315 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1316 gdk_window_set_user_data (clist->title_window, clist);
1318 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
1319 gdk_window_show (clist->title_window);
1322 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1323 gdk_window_set_user_data (clist->clist_window, clist);
1325 gdk_window_set_background (clist->clist_window, &widget->style->white);
1326 gdk_window_show (clist->clist_window);
1327 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
1328 &clist->clist_window_height);
1330 /* cursor's and GC's */
1331 clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1333 clist->fg_gc = gdk_gc_new (widget->window);
1334 clist->bg_gc = gdk_gc_new (widget->window);
1336 values.foreground = widget->style->white;
1337 values.function = GDK_XOR;
1338 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1339 clist->xor_gc = gdk_gc_new_with_values (widget->window,
1345 /* text properties */
1346 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
1348 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
1349 clist->row_center_offset = widget->style->font->ascent + 1.5;
1354 gtk_clist_unrealize (GtkWidget * widget)
1358 g_return_if_fail (widget != NULL);
1359 g_return_if_fail (GTK_IS_CLIST (widget));
1361 clist = GTK_CLIST (widget);
1362 GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
1363 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1365 gdk_cursor_destroy (clist->cursor_drag);
1366 gdk_gc_destroy (clist->xor_gc);
1367 gdk_gc_destroy (clist->fg_gc);
1368 gdk_gc_destroy (clist->bg_gc);
1370 gtk_style_detach (widget->style);
1372 gdk_window_destroy (clist->clist_window);
1373 gdk_window_destroy (clist->title_window);
1374 gdk_window_set_user_data (widget->window, NULL);
1375 gdk_window_destroy (widget->window);
1377 widget->window = NULL;
1378 clist->clist_window = NULL;
1379 clist->title_window = NULL;
1380 clist->cursor_drag = NULL;
1381 clist->xor_gc = NULL;
1382 clist->fg_gc = NULL;
1383 clist->bg_gc = NULL;
1387 gtk_clist_map (GtkWidget * widget)
1392 g_return_if_fail (widget != NULL);
1393 g_return_if_fail (GTK_IS_CLIST (widget));
1395 clist = GTK_CLIST (widget);
1397 if (!GTK_WIDGET_MAPPED (widget))
1399 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1401 gdk_window_show (widget->window);
1402 gdk_window_show (clist->title_window);
1403 gdk_window_show (clist->clist_window);
1405 /* map column buttons*/
1406 for (i = 0; i < clist->columns; i++)
1407 if (GTK_WIDGET_VISIBLE (clist->column[i].button) &&
1408 !GTK_WIDGET_MAPPED (clist->column[i].button))
1409 gtk_widget_map (clist->column[i].button);
1411 /* map vscrollbars */
1412 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
1413 !GTK_WIDGET_MAPPED (clist->vscrollbar))
1414 gtk_widget_map (clist->vscrollbar);
1416 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
1417 !GTK_WIDGET_MAPPED (clist->hscrollbar))
1418 gtk_widget_map (clist->hscrollbar);
1420 /* unfreeze the list */
1421 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
1426 gtk_clist_unmap (GtkWidget * widget)
1431 g_return_if_fail (widget != NULL);
1432 g_return_if_fail (GTK_IS_CLIST (widget));
1434 clist = GTK_CLIST (widget);
1436 if (GTK_WIDGET_MAPPED (widget))
1438 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1440 gdk_window_hide (clist->clist_window);
1441 gdk_window_hide (clist->title_window);
1442 gdk_window_hide (widget->window);
1444 /* unmap scrollbars */
1445 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
1446 gtk_widget_unmap (clist->vscrollbar);
1448 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
1449 gtk_widget_unmap (clist->hscrollbar);
1451 /* unmap column buttons */
1452 for (i = 0; i < clist->columns; i++)
1453 if (GTK_WIDGET_MAPPED (clist->column[i].button))
1454 gtk_widget_unmap (clist->column[i].button);
1456 /* freeze the list */
1457 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1462 gtk_clist_draw_row (GtkCList * clist,
1463 GdkRectangle * area,
1465 GtkCListRow * clist_row)
1468 GdkGC *fg_gc, *bg_gc;
1469 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
1471 gint i, offset = 0, width, height, pixmap_width = 0;
1472 gint xsrc, ysrc, xdest, ydest;
1474 g_return_if_fail (clist != NULL);
1476 /* bail now if we arn't drawable yet */
1477 if (!GTK_WIDGET_DRAWABLE (clist))
1480 if (row < 0 || row >= clist->rows)
1483 widget = GTK_WIDGET (clist);
1485 /* if the function is passed the pointer to the row instead of null,
1486 * it avoids this expensive lookup */
1488 clist_row = (g_list_nth (clist->row_list, row))->data;
1490 /* rectangle of the entire row */
1491 row_rectangle.x = 0;
1492 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1493 row_rectangle.width = clist->clist_window_width;
1494 row_rectangle.height = clist->row_height;
1496 /* rectangle of the cell spacing above the row */
1497 cell_rectangle.x = 0;
1498 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1499 cell_rectangle.width = row_rectangle.width;
1500 cell_rectangle.height = CELL_SPACING;
1502 /* rectangle used to clip drawing operations, it's y and height
1503 * positions only need to be set once, so we set them once here.
1504 * the x and width are set withing the drawing loop below once per
1506 clip_rectangle.y = row_rectangle.y;
1507 clip_rectangle.height = row_rectangle.height;
1509 /* select GC for background rectangle */
1510 if (clist_row->state == GTK_STATE_SELECTED)
1512 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
1513 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
1517 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1518 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1520 fg_gc = clist->fg_gc;
1521 bg_gc = clist->bg_gc;
1527 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1528 gdk_window_clear_area (clist->clist_window,
1529 intersect_rectangle.x,
1530 intersect_rectangle.y,
1531 intersect_rectangle.width,
1532 intersect_rectangle.height);
1534 /* the last row has to clear it's bottom cell spacing too */
1535 if (clist_row == clist->row_list_end->data)
1537 cell_rectangle.y += clist->row_height + CELL_SPACING;
1539 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1540 gdk_window_clear_area (clist->clist_window,
1541 intersect_rectangle.x,
1542 intersect_rectangle.y,
1543 intersect_rectangle.width,
1544 intersect_rectangle.height);
1547 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
1550 gdk_draw_rectangle (clist->clist_window,
1553 intersect_rectangle.x,
1554 intersect_rectangle.y,
1555 intersect_rectangle.width,
1556 intersect_rectangle.height);
1560 gdk_window_clear_area (clist->clist_window,
1563 cell_rectangle.width,
1564 cell_rectangle.height);
1566 cell_rectangle.y += clist->row_height + CELL_SPACING;
1567 gdk_window_clear_area (clist->clist_window,
1570 cell_rectangle.width,
1571 cell_rectangle.height);
1573 gdk_draw_rectangle (clist->clist_window,
1578 row_rectangle.width,
1579 row_rectangle.height);
1583 /* iterate and draw all the columns (row cells) and draw their contents */
1584 for (i = 0; i < clist->columns; i++)
1586 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1587 clip_rectangle.width = clist->column[i].area.width;
1589 /* calculate clipping region clipping region */
1592 rect = &clip_rectangle;
1596 if (!gdk_rectangle_intersect (area, &clip_rectangle, &intersect_rectangle))
1598 rect = &intersect_rectangle;
1601 /* calculate real width for column justification */
1602 switch (clist_row->cell[i].type)
1604 case GTK_CELL_EMPTY:
1609 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1610 GTK_CELL_TEXT (clist_row->cell[i])->text);
1613 case GTK_CELL_PIXMAP:
1614 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
1615 pixmap_width = width;
1618 case GTK_CELL_PIXTEXT:
1619 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
1620 pixmap_width = width;
1621 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1622 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1623 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1626 case GTK_CELL_WIDGET:
1636 switch (clist->column[i].justification)
1638 case GTK_JUSTIFY_LEFT:
1639 offset = clip_rectangle.x;
1642 case GTK_JUSTIFY_RIGHT:
1643 offset = (clip_rectangle.x + clip_rectangle.width) - width;
1646 case GTK_JUSTIFY_CENTER:
1647 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1650 case GTK_JUSTIFY_FILL:
1651 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1659 /* Draw Text or Pixmap */
1660 switch (clist_row->cell[i].type)
1662 case GTK_CELL_EMPTY:
1667 gdk_gc_set_clip_rectangle (fg_gc, rect);
1669 gdk_draw_string (clist->clist_window,
1670 widget->style->font,
1672 offset + clist_row->cell[i].horizontal,
1673 row_rectangle.y + clist->row_center_offset +
1674 clist_row->cell[i].verticle,
1675 GTK_CELL_TEXT (clist_row->cell[i])->text);
1677 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1680 case GTK_CELL_PIXMAP:
1683 xdest = offset + clist_row->cell[i].horizontal;
1684 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1685 clist_row->cell[i].verticle;
1687 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
1688 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1690 gdk_draw_pixmap (clist->clist_window,
1692 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1696 pixmap_width, height);
1698 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1699 gdk_gc_set_clip_mask (fg_gc, NULL);
1702 case GTK_CELL_PIXTEXT:
1703 /* draw the pixmap */
1706 xdest = offset + clist_row->cell[i].horizontal;
1707 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1708 clist_row->cell[i].verticle;
1710 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
1711 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1713 gdk_draw_pixmap (clist->clist_window,
1715 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1719 pixmap_width, height);
1721 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1723 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1725 /* draw the string */
1726 gdk_gc_set_clip_rectangle (fg_gc, rect);
1728 gdk_draw_string (clist->clist_window,
1729 widget->style->font,
1731 offset + clist_row->cell[i].horizontal,
1732 row_rectangle.y + clist->row_center_offset +
1733 clist_row->cell[i].verticle,
1734 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1736 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1740 case GTK_CELL_WIDGET:
1753 gtk_clist_draw_rows (GtkCList * clist,
1754 GdkRectangle * area)
1757 GtkCListRow *clist_row;
1758 int i, first_row, last_row;
1760 g_return_if_fail (clist != NULL);
1761 g_return_if_fail (GTK_IS_CLIST (clist));
1763 if (clist->row_height == 0)
1768 first_row = ROW_FROM_YPIXEL (clist, area->y);
1769 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
1773 first_row = ROW_FROM_YPIXEL (clist, 0);
1774 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
1777 list = g_list_nth (clist->row_list, first_row);
1781 clist_row = list->data;
1787 gtk_clist_draw_row (clist, area, i, clist_row);
1792 gdk_window_clear_area (clist->clist_window,
1793 0, ROW_TOP_YPIXEL (clist, i) - CELL_SPACING,
1798 gtk_clist_get_selection_info (GtkCList * clist,
1806 g_return_val_if_fail (clist != NULL, 0);
1808 /* bounds checking, return false if the user clicked
1809 * on a blank area */
1810 trow = ROW_FROM_YPIXEL (clist, y);
1811 if (trow >= clist->rows)
1817 tcol = COLUMN_FROM_XPIXEL (clist, x);
1818 if (tcol >= clist->columns)
1828 gtk_clist_real_select_row (GtkCList * clist,
1831 GdkEventButton * event)
1835 GtkCListRow *clist_row;
1837 g_return_if_fail (clist != NULL);
1839 if (row < 0 || row >= clist->rows)
1842 switch (clist->selection_mode)
1844 case GTK_SELECTION_SINGLE:
1846 list = clist->row_list;
1849 clist_row = list->data;
1854 if (clist_row->state == GTK_STATE_SELECTED)
1856 clist_row->state = GTK_STATE_NORMAL;
1857 gtk_clist_unselect_row (clist, i, column);
1861 clist_row->state = GTK_STATE_SELECTED;
1862 clist->selection = g_list_append (clist->selection, clist_row);
1865 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1866 gtk_clist_draw_row (clist, NULL, row, clist_row);
1868 else if (clist_row->state == GTK_STATE_SELECTED)
1870 gtk_clist_unselect_row (clist, i, column);
1877 case GTK_SELECTION_BROWSE:
1879 list = clist->row_list;
1882 clist_row = list->data;
1887 if (clist_row->state != GTK_STATE_SELECTED)
1889 clist_row->state = GTK_STATE_SELECTED;
1890 clist->selection = g_list_append (clist->selection, clist_row);
1892 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1893 gtk_clist_draw_row (clist, NULL, row, clist_row);
1896 else if (clist_row->state == GTK_STATE_SELECTED)
1898 gtk_clist_unselect_row (clist, i, column);
1905 case GTK_SELECTION_MULTIPLE:
1907 list = clist->row_list;
1910 clist_row = list->data;
1915 if (clist_row->state == GTK_STATE_SELECTED)
1917 clist_row->state = GTK_STATE_NORMAL;
1918 gtk_clist_unselect_row (clist, i, column);
1922 clist->selection = g_list_append (clist->selection, clist_row);
1923 clist_row->state = GTK_STATE_SELECTED;
1926 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1927 gtk_clist_draw_row (clist, NULL, row, clist_row);
1934 case GTK_SELECTION_EXTENDED:
1943 gtk_clist_real_unselect_row (GtkCList * clist,
1946 GdkEventButton * event)
1948 GtkCListRow *clist_row;
1950 g_return_if_fail (clist != NULL);
1952 if (row < 0 || row > (clist->rows - 1))
1955 clist_row = (g_list_nth (clist->row_list, row))->data;
1956 clist_row->state = GTK_STATE_NORMAL;
1957 clist->selection = g_list_remove (clist->selection, clist_row);
1959 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1960 gtk_clist_draw_row (clist, NULL, row, clist_row);
1964 gtk_clist_draw (GtkWidget * widget,
1965 GdkRectangle * area)
1969 g_return_if_fail (widget != NULL);
1970 g_return_if_fail (GTK_IS_CLIST (widget));
1971 g_return_if_fail (area != NULL);
1973 if (GTK_WIDGET_DRAWABLE (widget))
1975 clist = GTK_CLIST (widget);
1977 gdk_window_clear_area (widget->window,
1979 area->width, area->height);
1981 /* draw list shadow/border */
1982 gtk_draw_shadow (widget->style, widget->window,
1983 GTK_STATE_NORMAL, clist->shadow_type,
1985 clist->clist_window_width + (2 * widget->style->klass->xthickness),
1986 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
1987 clist->column_title_area.height);
1989 gdk_window_clear_area (clist->clist_window,
1992 gtk_clist_draw_rows (clist, NULL);
1997 gtk_clist_expose (GtkWidget * widget,
1998 GdkEventExpose * event)
2002 g_return_val_if_fail (widget != NULL, FALSE);
2003 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2004 g_return_val_if_fail (event != NULL, FALSE);
2006 if (GTK_WIDGET_DRAWABLE (widget))
2008 clist = GTK_CLIST (widget);
2011 if (event->window == widget->window)
2012 gtk_draw_shadow (widget->style, widget->window,
2013 GTK_STATE_NORMAL, clist->shadow_type,
2015 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2016 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2017 clist->column_title_area.height);
2019 /* exposure events on the list */
2020 if (event->window == clist->clist_window)
2021 gtk_clist_draw_rows (clist, &event->area);
2028 gtk_clist_button_press (GtkWidget * widget,
2029 GdkEventButton * event)
2032 gint x, y, row, column;
2034 g_return_val_if_fail (widget != NULL, FALSE);
2035 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2036 g_return_val_if_fail (event != NULL, FALSE);
2038 clist = GTK_CLIST (widget);
2040 /* selections on the list */
2041 if (event->window == clist->clist_window)
2046 if (gtk_clist_get_selection_info (clist, x, y, &row, &column))
2047 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2048 row, column, event);
2055 gtk_clist_size_request (GtkWidget * widget,
2056 GtkRequisition * requisition)
2061 g_return_if_fail (widget != NULL);
2062 g_return_if_fail (GTK_IS_CLIST (widget));
2063 g_return_if_fail (requisition != NULL);
2065 clist = GTK_CLIST (widget);
2067 requisition->width = 0;
2068 requisition->height = 0;
2070 /* compute the size of the column title (title) area */
2071 clist->column_title_area.height = 0;
2072 for (i = 0; i < clist->columns; i++)
2074 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
2075 clist->column_title_area.height = MAX (clist->column_title_area.height,
2076 clist->column[i].button->requisition.height);
2078 requisition->height += clist->column_title_area.height;
2080 /* add the vscrollbar space */
2081 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2082 GTK_WIDGET_VISIBLE (clist->vscrollbar))
2084 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
2086 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
2087 requisition->height = MAX (requisition->height,
2088 clist->vscrollbar->requisition.height);
2091 /* add the hscrollbar space */
2092 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2093 GTK_WIDGET_VISIBLE (clist->hscrollbar))
2095 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
2097 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
2098 requisition->width = MAX (clist->hscrollbar->requisition.width,
2099 requisition->width -
2100 clist->vscrollbar->requisition.width);
2104 requisition->width += widget->style->klass->xthickness * 2 +
2105 GTK_CONTAINER (widget)->border_width * 2;
2106 requisition->height += widget->style->klass->ythickness * 2 +
2107 GTK_CONTAINER (widget)->border_width * 2;
2111 gtk_clist_size_allocate (GtkWidget * widget,
2112 GtkAllocation * allocation)
2115 GtkAllocation clist_allocation;
2116 GtkAllocation child_allocation;
2117 gint i, vscrollbar_vis, hscrollbar_vis;
2119 g_return_if_fail (widget != NULL);
2120 g_return_if_fail (GTK_IS_CLIST (widget));
2121 g_return_if_fail (allocation != NULL);
2123 clist = GTK_CLIST (widget);
2124 widget->allocation = *allocation;
2126 if (GTK_WIDGET_REALIZED (widget))
2128 gdk_window_move_resize (widget->window,
2129 allocation->x + GTK_CONTAINER (widget)->border_width,
2130 allocation->y + GTK_CONTAINER (widget)->border_width,
2131 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
2132 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
2134 /* use internal allocation structure for all the math
2135 * because it's easier than always subtracting the container
2137 clist->internal_allocation.x = 0;
2138 clist->internal_allocation.y = 0;
2139 clist->internal_allocation.width = allocation->width -
2140 GTK_CONTAINER (widget)->border_width * 2;
2141 clist->internal_allocation.height = allocation->height -
2142 GTK_CONTAINER (widget)->border_width * 2;
2144 /* allocate clist window assuming no scrollbars */
2145 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2146 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2147 clist->column_title_area.height;
2148 clist_allocation.width = clist->internal_allocation.width -
2149 (2 * widget->style->klass->xthickness);
2150 clist_allocation.height = clist->internal_allocation.height -
2151 (2 * widget->style->klass->xthickness) -
2152 clist->column_title_area.height;
2155 * here's where we decide to show/not show the scrollbars
2160 for (i = 0; i <= 1; i++)
2162 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
2163 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2169 if (!vscrollbar_vis)
2172 clist_allocation.width -= clist->vscrollbar->requisition.width +
2173 SCROLLBAR_SPACING (clist);
2177 if (LIST_WIDTH (clist) <= clist_allocation.width &&
2178 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2184 if (!hscrollbar_vis)
2187 clist_allocation.height -= clist->hscrollbar->requisition.height +
2188 SCROLLBAR_SPACING (clist);
2193 clist->clist_window_width = clist_allocation.width;
2194 clist->clist_window_height = clist_allocation.height;
2196 gdk_window_move_resize (clist->clist_window,
2199 clist_allocation.width,
2200 clist_allocation.height);
2202 /* position the window which holds the column title buttons */
2203 clist->column_title_area.x = widget->style->klass->xthickness;
2204 clist->column_title_area.y = widget->style->klass->ythickness;
2205 clist->column_title_area.width = clist_allocation.width;
2207 gdk_window_move_resize (clist->title_window,
2208 clist->column_title_area.x,
2209 clist->column_title_area.y,
2210 clist->column_title_area.width,
2211 clist->column_title_area.height);
2213 /* column button allocation */
2214 gtk_clist_size_allocate_title_buttons (clist);
2215 gtk_clist_size_allocate_columns (clist);
2217 /* allocate the vscrollbar */
2220 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2221 gtk_widget_show (clist->vscrollbar);
2223 child_allocation.x = clist->internal_allocation.x +
2224 clist->internal_allocation.width -
2225 clist->vscrollbar->requisition.width;
2226 child_allocation.y = clist->internal_allocation.y;
2227 child_allocation.width = clist->vscrollbar->requisition.width;
2228 child_allocation.height = clist->internal_allocation.height -
2229 SCROLLBAR_SPACING (clist) -
2230 (hscrollbar_vis ? clist->hscrollbar->requisition.height : 0);
2232 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
2236 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2237 gtk_widget_hide (clist->vscrollbar);
2242 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2243 gtk_widget_show (clist->hscrollbar);
2245 child_allocation.x = clist->internal_allocation.x;
2246 child_allocation.y = clist->internal_allocation.y +
2247 clist->internal_allocation.height -
2248 clist->hscrollbar->requisition.height;
2249 child_allocation.width = clist->internal_allocation.width -
2250 SCROLLBAR_SPACING (clist) -
2251 (vscrollbar_vis ? clist->vscrollbar->requisition.width : 0);
2252 child_allocation.height = clist->hscrollbar->requisition.height;
2254 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
2258 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2259 gtk_widget_hide (clist->hscrollbar);
2264 * set the vscrollbar adjustments
2266 gtk_clist_adjust_scrollbars (clist);
2270 gtk_clist_size_allocate_title_buttons (GtkCList * clist)
2273 GtkAllocation button_allocation;
2275 button_allocation.x = clist->hoffset;
2276 button_allocation.y = 0;
2277 button_allocation.height = clist->column_title_area.height;
2279 for (i = 0; i < clist->columns; i++)
2281 button_allocation.width = clist->column[i].width;
2283 if (i == clist->columns - 1)
2285 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
2287 if (button_allocation.width < (clist->column_title_area.width - button_allocation.x))
2288 button_allocation.width = clist->column_title_area.width - button_allocation.x;
2292 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
2295 gtk_widget_size_allocate (clist->column[i].button, &button_allocation);
2296 button_allocation.x += button_allocation.width;
2301 gtk_clist_size_allocate_columns (GtkCList * clist)
2307 for (i = 0; i < clist->columns; i++)
2309 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
2311 if (i == clist->columns - 1)
2313 clist->column[i].area.width = MAX (clist->column[i].width,
2314 clist->column_title_area.width -
2315 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
2319 clist->column[i].area.width = clist->column[i].width;
2322 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
2327 gtk_clist_foreach (GtkContainer * container,
2328 GtkCallback callback,
2329 gpointer callback_data)
2334 g_return_if_fail (container != NULL);
2335 g_return_if_fail (GTK_IS_CLIST (container));
2336 g_return_if_fail (callback != NULL);
2338 clist = GTK_CLIST (container);
2340 /* callback for the column buttons */
2341 for (i = 0; i < clist->columns; i++)
2342 (*callback) (clist->column[i].button, callback_data);
2344 /* callbacks for the scrollbars */
2345 (*callback) (clist->vscrollbar, callback_data);
2346 (*callback) (clist->hscrollbar, callback_data);
2351 gtk_clist_column_button_realize (GtkWidget * widget,
2356 g_return_if_fail (widget != NULL);
2357 g_return_if_fail (GTK_IS_CLIST (data));
2359 clist = GTK_CLIST (data);
2361 if (widget->window && clist->title_window)
2362 gdk_window_reparent (widget->window, clist->title_window,
2363 widget->allocation.x, 0);
2367 gtk_clist_column_button_clicked (GtkWidget * widget,
2373 g_return_if_fail (widget != NULL);
2374 g_return_if_fail (GTK_IS_CLIST (data));
2376 clist = GTK_CLIST (data);
2378 /* find the column who's button was pressed */
2379 for (i = 0; i < clist->columns; i++)
2380 if (clist->column[i].button == widget)
2383 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
2390 * gtk_clist_adjust_scrollbars
2391 * gtk_clist_vadjustment_changed
2392 * gtk_clist_hadjustment_changed
2393 * gtk_clist_vadjustment_value_changed
2394 * gtk_clist_hadjustment_value_changed
2397 gtk_clist_adjust_scrollbars (GtkCList * clist)
2399 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
2400 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
2401 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
2402 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
2403 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
2405 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
2407 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
2408 clist->clist_window_height;
2409 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
2413 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
2414 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
2415 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
2416 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
2417 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
2419 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
2421 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
2422 clist->clist_window_width;
2423 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
2427 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
2428 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2430 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2432 gtk_widget_hide (clist->vscrollbar);
2433 gtk_widget_queue_resize (GTK_WIDGET (clist));
2438 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2440 gtk_widget_show (clist->vscrollbar);
2441 gtk_widget_queue_resize (GTK_WIDGET (clist));
2445 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
2446 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2448 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2450 gtk_widget_hide (clist->hscrollbar);
2451 gtk_widget_queue_resize (GTK_WIDGET (clist));
2456 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2458 gtk_widget_show (clist->hscrollbar);
2459 gtk_widget_queue_resize (GTK_WIDGET (clist));
2463 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
2464 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
2468 gtk_clist_vadjustment_changed (GtkAdjustment * adjustment,
2473 g_return_if_fail (adjustment != NULL);
2474 g_return_if_fail (data != NULL);
2476 clist = GTK_CLIST (data);
2480 gtk_clist_hadjustment_changed (GtkAdjustment * adjustment,
2485 g_return_if_fail (adjustment != NULL);
2486 g_return_if_fail (data != NULL);
2488 clist = GTK_CLIST (data);
2492 gtk_clist_vadjustment_value_changed (GtkAdjustment * adjustment,
2499 g_return_if_fail (adjustment != NULL);
2500 g_return_if_fail (data != NULL);
2501 g_return_if_fail (GTK_IS_CLIST (data));
2503 clist = GTK_CLIST (data);
2505 value = adjustment->value;
2507 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
2509 if (value > -clist->voffset)
2512 diff = value + clist->voffset;
2514 /* we have to re-draw the whole screen here... */
2515 if (diff >= clist->clist_window_height)
2517 clist->voffset = -value;
2518 gtk_clist_draw_rows (clist, NULL);
2522 gdk_window_copy_area (clist->clist_window,
2523 GTK_WIDGET (clist)->style->white_gc,
2525 clist->clist_window,
2528 clist->clist_window_width,
2529 clist->clist_window_height - diff);
2532 area.y = clist->clist_window_height - diff;
2533 area.width = clist->clist_window_width;
2539 diff = -clist->voffset - value;
2541 /* we have to re-draw the whole screen here... */
2542 if (diff >= clist->clist_window_height)
2544 clist->voffset = -value;
2545 gtk_clist_draw_rows (clist, NULL);
2549 gdk_window_copy_area (clist->clist_window,
2550 GTK_WIDGET (clist)->style->white_gc,
2552 clist->clist_window,
2555 clist->clist_window_width,
2556 clist->clist_window_height - diff);
2560 area.width = clist->clist_window_width;
2565 clist->voffset = -value;
2568 gtk_clist_draw_rows (clist, &area);
2572 gtk_clist_hadjustment_value_changed (GtkAdjustment * adjustment,
2577 gint i, diff, value;
2579 g_return_if_fail (adjustment != NULL);
2580 g_return_if_fail (data != NULL);
2581 g_return_if_fail (GTK_IS_CLIST (data));
2583 clist = GTK_CLIST (data);
2585 value = adjustment->value;
2587 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
2589 for (i = 0; i < clist->columns; i++)
2591 clist->column[i].button->allocation.x -= value + clist->hoffset;
2593 if (clist->column[i].button->window)
2594 gdk_window_move (clist->column[i].button->window,
2595 clist->column[i].button->allocation.x,
2596 clist->column[i].button->allocation.y);
2599 if (value > -clist->hoffset)
2602 diff = value + clist->hoffset;
2604 /* we have to re-draw the whole screen here... */
2605 if (diff >= clist->clist_window_width)
2607 clist->hoffset = -value;
2608 gtk_clist_draw_rows (clist, NULL);
2612 gdk_window_copy_area (clist->clist_window,
2613 GTK_WIDGET (clist)->style->white_gc,
2615 clist->clist_window,
2618 clist->clist_window_width - diff,
2619 clist->clist_window_height);
2621 area.x = clist->clist_window_width - diff;
2624 area.height = clist->clist_window_height;
2629 diff = -clist->hoffset - value;
2631 /* we have to re-draw the whole screen here... */
2632 if (diff >= clist->clist_window_width)
2634 clist->hoffset = -value;
2635 gtk_clist_draw_rows (clist, NULL);
2639 gdk_window_copy_area (clist->clist_window,
2640 GTK_WIDGET (clist)->style->white_gc,
2642 clist->clist_window,
2645 clist->clist_window_width - diff,
2646 clist->clist_window_height);
2651 area.height = clist->clist_window_height;
2654 clist->hoffset = -value;
2657 gtk_clist_draw_rows (clist, &area);
2661 * Memory Allocation/Distruction Routines for GtkCList stuctures
2664 * gtk_clist_columns_new
2665 * gtk_clist_column_title_new
2666 * gtk_clist_columns_delete
2668 * gtk_clist_row_delete
2669 * gtk_clist_cell_empty
2670 * gtk_clist_cell_set_text
2671 * gtk_clist_cell_set_pixmap
2673 static GtkCListColumn *
2674 gtk_clist_columns_new (GtkCList * clist)
2677 GtkCListColumn *column;
2679 column = g_new (GtkCListColumn, clist->columns);
2681 for (i = 0; i < clist->columns; i++)
2683 column[i].area.x = 0;
2684 column[i].area.y = 0;
2685 column[i].area.width = 0;
2686 column[i].area.height = 0;
2687 column[i].title = NULL;
2688 column[i].button = NULL;
2689 column[i].width = 0;
2690 column[i].justification = GTK_JUSTIFY_LEFT;
2697 gtk_clist_column_title_new (GtkCList * clist,
2701 if (clist->column[column].title)
2702 g_free (clist->column[column].title);
2704 clist->column[column].title = g_strdup (title);
2708 gtk_clist_columns_delete (GtkCList * clist)
2712 for (i = 0; i < clist->columns; i++)
2713 if (clist->column[i].title)
2714 g_free (clist->column[i].title);
2716 g_free (clist->column);
2719 static GtkCListRow *
2720 gtk_clist_row_new (GtkCList * clist)
2723 GtkCListRow *clist_row;
2725 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
2726 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
2728 for (i = 0; i < clist->columns; i++)
2730 clist_row->cell[i].type = GTK_CELL_EMPTY;
2731 clist_row->cell[i].verticle = 0;
2732 clist_row->cell[i].horizontal = 0;
2735 clist_row->foreground = GTK_WIDGET (clist)->style->fg[GTK_STATE_NORMAL];
2736 clist_row->background = GTK_WIDGET (clist)->style->bg[GTK_STATE_PRELIGHT];
2737 clist_row->state = GTK_STATE_NORMAL;
2738 clist_row->data = NULL;
2744 gtk_clist_row_delete (GtkCList * clist,
2745 GtkCListRow * clist_row)
2749 for (i = 0; i < clist->columns; i++)
2750 gtk_clist_cell_empty (clist, clist_row, i);
2752 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
2753 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
2758 gtk_clist_cell_empty (GtkCList * clist,
2759 GtkCListRow * clist_row,
2762 switch (clist_row->cell[column].type)
2764 case GTK_CELL_EMPTY:
2768 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2771 case GTK_CELL_PIXMAP:
2772 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2773 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2776 case GTK_CELL_PIXTEXT:
2777 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2778 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2779 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2782 case GTK_CELL_WIDGET:
2790 clist_row->cell[column].type = GTK_CELL_EMPTY;
2794 gtk_clist_cell_set_text (GtkCList * clist,
2795 GtkCListRow * clist_row,
2799 gtk_clist_cell_empty (clist, clist_row, column);
2803 clist_row->cell[column].type = GTK_CELL_TEXT;
2804 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2809 gtk_clist_cell_set_pixmap (GtkCList * clist,
2810 GtkCListRow * clist_row,
2815 gtk_clist_cell_empty (clist, clist_row, column);
2819 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2820 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2821 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2826 gtk_clist_cell_set_pixtext (GtkCList * clist,
2827 GtkCListRow * clist_row,
2834 gtk_clist_cell_empty (clist, clist_row, column);
2836 if (text && pixmap && mask)
2838 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2839 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2840 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2841 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2842 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;