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,
255 (GtkArgSetFunc) NULL,
256 (GtkArgGetFunc) NULL,
259 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
266 gtk_clist_class_init (GtkCListClass * klass)
268 GtkObjectClass *object_class;
269 GtkWidgetClass *widget_class;
270 GtkContainerClass *container_class;
272 object_class = (GtkObjectClass *) klass;
273 widget_class = (GtkWidgetClass *) klass;
274 container_class = (GtkContainerClass *) klass;
276 parent_class = gtk_type_class (gtk_container_get_type ());
278 clist_signals[SELECT_ROW] =
279 gtk_signal_new ("select_row",
282 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
283 gtk_clist_marshal_signal_1,
284 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
285 clist_signals[UNSELECT_ROW] =
286 gtk_signal_new ("unselect_row",
289 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
290 gtk_clist_marshal_signal_1,
291 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
292 clist_signals[CLICK_COLUMN] =
293 gtk_signal_new ("click_column",
296 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
297 gtk_clist_marshal_signal_2,
298 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
300 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
302 object_class->destroy = gtk_clist_destroy;
304 widget_class->realize = gtk_clist_realize;
305 widget_class->unrealize = gtk_clist_unrealize;
306 widget_class->map = gtk_clist_map;
307 widget_class->unmap = gtk_clist_unmap;
308 widget_class->draw = gtk_clist_draw;
309 widget_class->button_press_event = gtk_clist_button_press;
310 widget_class->expose_event = gtk_clist_expose;
311 widget_class->size_request = gtk_clist_size_request;
312 widget_class->size_allocate = gtk_clist_size_allocate;
314 container_class->add = NULL;
315 container_class->remove = NULL;
316 container_class->foreach = gtk_clist_foreach;
318 klass->select_row = gtk_clist_real_select_row;
319 klass->unselect_row = gtk_clist_real_unselect_row;
320 klass->click_column = NULL;
322 klass->scrollbar_spacing = 5;
326 gtk_clist_marshal_signal_1 (GtkObject * object,
331 GtkCListSignal1 rfunc;
333 rfunc = (GtkCListSignal1) func;
335 (*rfunc) (object, GTK_VALUE_INT (args[0]),
336 GTK_VALUE_INT (args[1]),
337 GTK_VALUE_POINTER (args[2]),
342 gtk_clist_marshal_signal_2 (GtkObject * object,
347 GtkCListSignal2 rfunc;
349 rfunc = (GtkCListSignal2) func;
351 (*rfunc) (object, GTK_VALUE_INT (args[0]),
356 gtk_clist_init (GtkCList * clist)
360 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
361 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
364 clist->row_center_offset = 0;
365 clist->row_height = 0;
366 clist->row_list = NULL;
367 clist->row_list_end = NULL;
371 clist->column_title_area.x = 0;
372 clist->column_title_area.y = 0;
373 clist->column_title_area.width = 0;
374 clist->column_title_area.height = 0;
376 clist->clist_window = NULL;
377 clist->clist_window_width = 0;
378 clist->clist_window_height = 0;
383 clist->shadow_type = GTK_SHADOW_IN;
384 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
385 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
387 clist->cursor_drag = NULL;
388 clist->xor_gc = NULL;
393 clist->selection_mode = GTK_SELECTION_SINGLE;
394 clist->selection = NULL;
398 gtk_clist_new (int columns,
403 GtkAdjustment *adjustment;
406 if (columns < 1 || titles == NULL)
409 clist = gtk_type_new (gtk_clist_get_type ());
411 /* initalize memory chunks */
412 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
413 sizeof (GtkCListRow),
414 sizeof (GtkCListRow) * 1024,
416 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
417 sizeof (GtkCell) * columns,
418 sizeof (GtkCell) * columns * 1024,
421 /* set number of columns, allocate memory */
422 clist->columns = columns;
423 clist->column = gtk_clist_columns_new (clist);
425 /* create column button and connect signals */
426 for (i = 0; i < columns; i++)
428 clist->column[i].button = gtk_button_new ();
429 gtk_widget_set_parent (clist->column[i].button, GTK_WIDGET (clist));
431 gtk_signal_connect_after (GTK_OBJECT (clist->column[i].button),
433 (GtkSignalFunc) gtk_clist_column_button_realize,
436 gtk_signal_connect (GTK_OBJECT (clist->column[i].button),
438 (GtkSignalFunc) gtk_clist_column_button_clicked,
441 /* set column title */
442 gtk_clist_set_column_title (clist, i, titles[i]);
444 clist->column[i].width =
445 gdk_string_width (GTK_WIDGET (clist)->style->font, clist->column[i].title);
447 gtk_widget_show (clist->column[i].button);
451 /* create and connect scrollbars */
452 clist->vscrollbar = gtk_vscrollbar_new (NULL);
453 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
455 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
456 (GtkSignalFunc) gtk_clist_vadjustment_changed,
459 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
460 (GtkSignalFunc) gtk_clist_vadjustment_value_changed,
463 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
464 gtk_widget_show (clist->vscrollbar);
466 clist->hscrollbar = gtk_hscrollbar_new (NULL);
467 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
469 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
470 (GtkSignalFunc) gtk_clist_hadjustment_changed,
473 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
474 (GtkSignalFunc) gtk_clist_hadjustment_value_changed,
477 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
478 gtk_widget_show (clist->hscrollbar);
480 return GTK_WIDGET (clist);
484 gtk_clist_set_border (GtkCList * clist,
485 GtkShadowType border)
487 g_return_if_fail (clist != NULL);
489 clist->shadow_type = border;
491 if (GTK_WIDGET_VISIBLE (clist))
492 gtk_widget_queue_resize (GTK_WIDGET (clist));
496 gtk_clist_set_selection_mode (GtkCList * clist,
497 GtkSelectionMode mode)
499 g_return_if_fail (clist != NULL);
501 clist->selection_mode = mode;
505 gtk_clist_freeze (GtkCList * clist)
507 g_return_if_fail (clist != NULL);
509 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
513 gtk_clist_thaw (GtkCList * clist)
515 g_return_if_fail (clist != NULL);
517 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
519 gtk_clist_adjust_scrollbars (clist);
520 gtk_clist_draw_rows (clist, NULL);
525 gtk_clist_set_column_title (GtkCList * clist,
529 GtkWidget *old_widget;
530 GtkWidget *alignment = NULL;
533 g_return_if_fail (clist != NULL);
535 if (column < 0 || column >= clist->columns)
538 gtk_clist_column_title_new (clist, column, title);
540 /* remove and destroy the old widget */
541 old_widget = GTK_BUTTON (clist->column[column].button)->child;
544 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
545 gtk_widget_destroy (old_widget);
548 switch (clist->column[column].justification)
550 case GTK_JUSTIFY_LEFT:
551 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
554 case GTK_JUSTIFY_RIGHT:
555 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
558 case GTK_JUSTIFY_CENTER:
559 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
562 case GTK_JUSTIFY_FILL:
563 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
569 label = gtk_label_new (clist->column[column].title);
570 gtk_container_add (GTK_CONTAINER (alignment), label);
571 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
572 gtk_widget_show (label);
573 gtk_widget_show (alignment);
578 gtk_clist_set_column_widget (GtkCList * clist,
582 GtkWidget *old_widget;
584 g_return_if_fail (clist != NULL);
586 if (column < 0 || column >= clist->columns)
589 gtk_clist_column_title_new (clist, column, NULL);
591 /* remove and destroy the old widget */
592 old_widget = GTK_BUTTON (clist->column[column].button)->child;
595 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
596 gtk_widget_destroy (old_widget);
599 /* add and show the widget */
602 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
603 gtk_widget_show (widget);
608 gtk_clist_set_column_justification (GtkCList * clist,
610 GtkJustification justification)
612 GtkWidget *alignment;
614 g_return_if_fail (clist != NULL);
616 if (column < 0 || column >= clist->columns)
619 clist->column[column].justification = justification;
621 /* change the alinment of the button title if it's not a
623 if (clist->column[column].title)
625 alignment = GTK_BUTTON (clist->column[column].button)->child;
627 switch (clist->column[column].justification)
629 case GTK_JUSTIFY_LEFT:
630 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
633 case GTK_JUSTIFY_RIGHT:
634 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
637 case GTK_JUSTIFY_CENTER:
638 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
641 case GTK_JUSTIFY_FILL:
642 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
650 if (!GTK_CLIST_FROZEN (clist))
651 gtk_clist_draw_rows (clist, NULL);
655 gtk_clist_set_column_width (GtkCList * clist,
659 g_return_if_fail (clist != NULL);
661 if (column < 0 || column >= clist->columns)
664 clist->column[column].width = width;
666 gtk_clist_size_allocate_title_buttons (clist);
668 if (!GTK_CLIST_FROZEN (clist))
670 gtk_clist_adjust_scrollbars (clist);
671 gtk_clist_draw_rows (clist, NULL);
676 gtk_clist_set_row_height (GtkCList * clist,
681 g_return_if_fail (clist != NULL);
684 clist->row_height = height;
688 GTK_CLIST_SET_FLAGS (clist, CLIST_ROW_HEIGHT_SET);
690 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
691 GTK_WIDGET (clist) ->style->font->descent + 1);
692 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
694 if (!GTK_CLIST_FROZEN (clist))
696 gtk_clist_adjust_scrollbars (clist);
697 gtk_clist_draw_rows (clist, NULL);
702 gtk_clist_moveto (GtkCList * clist,
710 g_return_if_fail (clist != NULL);
712 if (row < -1 || row >= clist->rows)
714 if (column < -1 || column >= clist->columns)
717 /* adjust vertical scrollbar */
720 x = ROW_TOP (clist, row) - (row_align * (clist->clist_window_height -
721 (clist->row_height + 2 * CELL_SPACING)));
724 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
725 else if (x > LIST_HEIGHT (clist) - clist->clist_window_height)
726 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
727 clist->clist_window_height;
729 GTK_RANGE (clist->vscrollbar)->adjustment->value = x;
731 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
735 /* adjust horizontal scrollbar */
738 y = COLUMN_LEFT (clist, column) - (col_align * (clist->clist_window_width -
739 clist->column[column].area.width +
740 2 * (CELL_SPACING + COLUMN_INSET)));
743 GTK_RANGE (clist->hscrollbar)->adjustment->value = 0.0;
744 else if (y > LIST_WIDTH (clist) - clist->clist_window_width)
745 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
746 clist->clist_window_width;
748 GTK_RANGE (clist->hscrollbar)->adjustment->value = y;
750 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
756 gtk_clist_set_text (GtkCList * clist,
761 GtkCListRow *clist_row;
763 g_return_if_fail (clist != NULL);
765 if (row < 0 || row >= clist->rows)
767 if (column < 0 || column >= clist->columns)
770 clist_row = (g_list_nth (clist->row_list, row))->data;
772 /* if text is null, then the cell is empty */
774 gtk_clist_cell_set_text (clist, clist_row, column, text);
776 gtk_clist_cell_empty (clist, clist_row, column);
778 /* redraw the list if it's not frozen */
779 if (!GTK_CLIST_FROZEN (clist))
781 if (gtk_clist_row_isvisable (clist, row))
782 gtk_clist_draw_row (clist, NULL, row, clist_row);
787 gtk_clist_set_pixmap (GtkCList * clist,
793 GtkCListRow *clist_row;
795 g_return_if_fail (clist != NULL);
797 if (row < 0 || row >= clist->rows)
799 if (column < 0 || column >= clist->columns)
802 clist_row = (g_list_nth (clist->row_list, row))->data;
804 gdk_pixmap_ref (pixmap);
805 gdk_pixmap_ref (mask);
806 gtk_clist_cell_set_pixmap (clist, clist_row, column, pixmap, mask);
808 /* redraw the list if it's not frozen */
809 if (!GTK_CLIST_FROZEN (clist))
811 if (gtk_clist_row_isvisable (clist, row))
812 gtk_clist_draw_row (clist, NULL, row, clist_row);
817 gtk_clist_set_pixtext (GtkCList * clist,
825 GtkCListRow *clist_row;
827 g_return_if_fail (clist != NULL);
829 if (row < 0 || row >= clist->rows)
831 if (column < 0 || column >= clist->columns)
834 clist_row = (g_list_nth (clist->row_list, row))->data;
836 gdk_pixmap_ref (pixmap);
837 gdk_pixmap_ref (mask);
838 gtk_clist_cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
840 /* redraw the list if it's not frozen */
841 if (!GTK_CLIST_FROZEN (clist))
843 if (gtk_clist_row_isvisable (clist, row))
844 gtk_clist_draw_row (clist, NULL, row, clist_row);
849 gtk_clist_set_foreground (GtkCList * clist,
853 GtkCListRow *clist_row;
855 g_return_if_fail (clist != NULL);
856 g_return_if_fail (color != NULL);
858 if (row < 0 || row >= clist->rows)
861 clist_row = (g_list_nth (clist->row_list, row))->data;
862 clist_row->foreground = *color;
864 if (!GTK_CLIST_FROZEN (clist))
865 if (gtk_clist_row_isvisable (clist, row))
866 gtk_clist_draw_row (clist, NULL, row, clist_row);
869 void gtk_clist_set_background (GtkCList * clist,
873 GtkCListRow *clist_row;
875 g_return_if_fail (clist != NULL);
876 g_return_if_fail (color != NULL);
878 if (row < 0 || row >= clist->rows)
881 clist_row = (g_list_nth (clist->row_list, row))->data;
882 clist_row->background = *color;
884 if (!GTK_CLIST_FROZEN (clist))
885 if (gtk_clist_row_isvisable (clist, row))
886 gtk_clist_draw_row (clist, NULL, row, clist_row);
890 gtk_clist_set_shift (GtkCList * clist,
896 GtkCListRow *clist_row;
898 g_return_if_fail (clist != NULL);
900 if (row < 0 || row >= clist->rows)
902 if (column < 0 || column >= clist->columns)
905 clist_row = (g_list_nth (clist->row_list, row))->data;
907 clist_row->cell[column].verticle = verticle;
908 clist_row->cell[column].horizontal = horizontal;
910 if (!GTK_CLIST_FROZEN (clist))
911 if (gtk_clist_row_isvisable (clist, row))
912 gtk_clist_draw_row (clist, NULL, row, clist_row);
916 gtk_clist_append (GtkCList * clist,
920 GtkCListRow *clist_row;
922 g_return_val_if_fail (clist != NULL, -1);
924 clist_row = gtk_clist_row_new (clist);
927 /* keeps track of the end of the list so the list
928 * doesn't have to be traversed every time a item is added */
929 if (!clist->row_list)
931 clist->row_list = g_list_append (clist->row_list, clist_row);
932 clist->row_list_end = clist->row_list;
934 /* check the selection mode to see if we should select
935 * the first row automaticly */
936 switch (clist->selection_mode)
938 case GTK_SELECTION_BROWSE:
939 gtk_clist_select_row (clist, 0, -1);
947 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
949 /* set the text in the row's columns */
951 for (i = 0; i < clist->columns; i++)
953 gtk_clist_cell_set_text (clist, clist_row, i, text[i]);
955 /* redraw the list if it's not frozen */
956 if (!GTK_CLIST_FROZEN (clist))
958 gtk_clist_adjust_scrollbars (clist);
960 if (gtk_clist_row_isvisable (clist, clist->rows - 1))
961 gtk_clist_draw_rows (clist, NULL);
964 /* return index of the row */
965 return clist->rows - 1;
969 gtk_clist_insert (GtkCList * clist,
974 GtkCListRow *clist_row;
976 g_return_if_fail (clist != NULL);
977 g_return_if_fail (text != NULL);
979 /* return if out of bounds */
980 if (row < 0 || row > (clist->rows - 1))
984 clist_row = gtk_clist_row_new (clist);
986 /* reset the row end pointer if we're inserting at the
988 if (row == clist->rows)
989 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
991 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
995 /* set the text in the row's columns */
997 for (i = 0; i < clist->columns; i++)
999 gtk_clist_cell_set_text (clist, clist_row, i, text[i]);
1001 /* redraw the list if it isn't frozen */
1002 if (!GTK_CLIST_FROZEN (clist))
1004 gtk_clist_adjust_scrollbars (clist);
1006 if (gtk_clist_row_isvisable (clist, row))
1007 gtk_clist_draw_rows (clist, NULL);
1012 gtk_clist_remove (GtkCList * clist,
1017 GtkCListRow *clist_row;
1019 g_return_if_fail (clist != NULL);
1021 /* return if out of bounds */
1022 if (row < 0 || row > (clist->rows - 1))
1025 was_visible = gtk_clist_row_isvisable (clist, row);
1027 /* get the row we're going to delete */
1028 list = g_list_nth (clist->row_list, row);
1029 clist_row = list->data;
1031 /* reset the row end pointer if we're removing at the
1032 * end of the list */
1033 if (row == clist->rows - 1)
1034 clist->row_list_end = list->prev;
1036 clist->row_list = g_list_remove (clist->row_list, clist_row);
1039 /* redraw the row if it isn't frozen */
1040 if (!GTK_CLIST_FROZEN (clist))
1042 gtk_clist_adjust_scrollbars (clist);
1045 gtk_clist_draw_rows (clist, NULL);
1048 if (clist_row->state == GTK_STATE_SELECTED)
1050 switch (clist->selection_mode)
1052 case GTK_SELECTION_BROWSE:
1053 if (row >= clist->rows)
1055 gtk_clist_select_row (clist, row, -1);
1062 /* remove from selection list */
1063 clist->selection = g_list_remove (clist->selection, clist_row);
1066 gtk_clist_row_delete (clist, clist_row);
1070 gtk_clist_clear (GtkCList * clist)
1073 GtkCListRow *clist_row;
1075 g_return_if_fail (clist != NULL);
1077 /* remove all the rows */
1078 list = clist->row_list;
1081 clist_row = list->data;
1084 gtk_clist_row_delete (clist, clist_row);
1086 g_list_free (clist->row_list);
1088 /* free up the selection list */
1089 g_list_free (clist->selection);
1091 clist->row_list = NULL;
1092 clist->row_list_end = NULL;
1093 clist->selection = NULL;
1097 /* zero-out the scrollbars */
1098 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1099 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1101 if (!GTK_CLIST_FROZEN (clist))
1103 gtk_clist_adjust_scrollbars (clist);
1104 gtk_clist_draw_rows (clist, NULL);
1109 gtk_clist_set_row_data (GtkCList * clist,
1113 GtkCListRow *clist_row;
1115 g_return_if_fail (clist != NULL);
1117 if (row < 0 || row > (clist->rows - 1))
1120 clist_row = (g_list_nth (clist->row_list, row))->data;
1121 clist_row->data = data;
1124 * re-send the selected signal if data is changed/added
1125 * so the application can respond to the new data --
1126 * this could be questionable behavior
1128 if (clist_row->state == GTK_STATE_SELECTED)
1129 gtk_clist_select_row (clist, 0, 0);
1133 gtk_clist_get_row_data (GtkCList * clist,
1136 GtkCListRow *clist_row;
1138 g_return_val_if_fail (clist != NULL, NULL);
1140 if (row < 0 || row > (clist->rows - 1))
1143 clist_row = (g_list_nth (clist->row_list, row))->data;
1144 return clist_row->data;
1148 gtk_clist_select_row (GtkCList * clist,
1152 g_return_if_fail (clist != NULL);
1154 if (row < 0 || row >= clist->rows)
1157 if (column < -1 || column >= clist->columns)
1160 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], row, column, NULL);
1164 gtk_clist_unselect_row (GtkCList * clist,
1168 g_return_if_fail (clist != NULL);
1170 if (row < 0 || row >= clist->rows)
1173 if (column < -1 || column >= clist->columns)
1176 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], row, column, NULL);
1180 gtk_clist_row_isvisable (GtkCList * clist,
1183 g_return_val_if_fail (clist != NULL, 0);
1185 if (row < 0 || row >= clist->rows)
1188 if (clist->row_height == 0)
1191 if (row < ROW_FROM_YPIXEL (clist, 0))
1194 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
1201 gtk_clist_get_vadjustment (GtkCList * clist)
1203 g_return_val_if_fail (clist != NULL, NULL);
1204 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1206 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
1210 gtk_clist_get_hadjustment (GtkCList * clist)
1212 g_return_val_if_fail (clist != NULL, NULL);
1213 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1215 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
1219 gtk_clist_set_policy (GtkCList * clist,
1220 GtkPolicyType vscrollbar_policy,
1221 GtkPolicyType hscrollbar_policy)
1223 g_return_if_fail (clist != NULL);
1224 g_return_if_fail (GTK_IS_CLIST (clist));
1226 if (clist->vscrollbar_policy != vscrollbar_policy)
1228 clist->vscrollbar_policy = vscrollbar_policy;
1230 if (GTK_WIDGET (clist)->parent)
1231 gtk_widget_queue_resize (GTK_WIDGET (clist));
1234 if (clist->hscrollbar_policy != hscrollbar_policy)
1236 clist->hscrollbar_policy = hscrollbar_policy;
1238 if (GTK_WIDGET (clist)->parent)
1239 gtk_widget_queue_resize (GTK_WIDGET (clist));
1244 gtk_clist_destroy (GtkObject * object)
1249 g_return_if_fail (object != NULL);
1250 g_return_if_fail (GTK_IS_CLIST (object));
1252 clist = GTK_CLIST (object);
1254 /* freeze the list */
1255 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1257 /* get rid of all the rows */
1258 gtk_clist_clear (clist);
1260 /* destroy the scrollbars */
1261 gtk_widget_destroy (clist->vscrollbar);
1262 gtk_widget_destroy (clist->hscrollbar);
1264 /* get rid of all the column buttons */
1265 for (i = 0; i < clist->columns; i++)
1266 gtk_widget_destroy (clist->column[i].button);
1268 gtk_clist_columns_delete (clist);
1270 /* get rid of the memory chunks */
1271 g_mem_chunk_destroy (clist->cell_mem_chunk);
1272 g_mem_chunk_destroy (clist->row_mem_chunk);
1274 if (GTK_OBJECT_CLASS (parent_class)->destroy)
1275 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1279 gtk_clist_realize (GtkWidget * widget)
1282 GdkWindowAttr attributes;
1283 gint attributes_mask;
1286 g_return_if_fail (widget != NULL);
1287 g_return_if_fail (GTK_IS_CLIST (widget));
1289 clist = GTK_CLIST (widget);
1291 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1293 attributes.window_type = GDK_WINDOW_CHILD;
1294 attributes.x = widget->allocation.x;
1295 attributes.y = widget->allocation.y;
1296 attributes.width = widget->allocation.width;
1297 attributes.height = widget->allocation.height;
1298 attributes.wclass = GDK_INPUT_OUTPUT;
1299 attributes.visual = gtk_widget_get_visual (widget);
1300 attributes.colormap = gtk_widget_get_colormap (widget);
1301 attributes.event_mask = gtk_widget_get_events (widget);
1302 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1303 GDK_BUTTON_PRESS_MASK |
1304 GDK_BUTTON_RELEASE_MASK |
1305 GDK_KEY_PRESS_MASK);
1306 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1310 widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
1311 gdk_window_set_user_data (widget->window, clist);
1313 widget->style = gtk_style_attach (widget->style, widget->window);
1315 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1317 /* column-title window */
1318 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1319 gdk_window_set_user_data (clist->title_window, clist);
1321 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
1322 gdk_window_show (clist->title_window);
1325 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1326 gdk_window_set_user_data (clist->clist_window, clist);
1328 gdk_window_set_background (clist->clist_window, &widget->style->white);
1329 gdk_window_show (clist->clist_window);
1330 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
1331 &clist->clist_window_height);
1333 /* cursor's and GC's */
1334 clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1336 clist->fg_gc = gdk_gc_new (widget->window);
1337 clist->bg_gc = gdk_gc_new (widget->window);
1339 values.foreground = widget->style->white;
1340 values.function = GDK_XOR;
1341 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1342 clist->xor_gc = gdk_gc_new_with_values (widget->window,
1348 /* text properties */
1349 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
1351 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
1352 clist->row_center_offset = widget->style->font->ascent + 1.5;
1357 gtk_clist_unrealize (GtkWidget * widget)
1361 g_return_if_fail (widget != NULL);
1362 g_return_if_fail (GTK_IS_CLIST (widget));
1364 clist = GTK_CLIST (widget);
1365 GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
1366 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1368 gdk_cursor_destroy (clist->cursor_drag);
1369 gdk_gc_destroy (clist->xor_gc);
1370 gdk_gc_destroy (clist->fg_gc);
1371 gdk_gc_destroy (clist->bg_gc);
1373 gtk_style_detach (widget->style);
1375 gdk_window_destroy (clist->clist_window);
1376 gdk_window_destroy (clist->title_window);
1377 gdk_window_set_user_data (widget->window, NULL);
1378 gdk_window_destroy (widget->window);
1380 widget->window = NULL;
1381 clist->clist_window = NULL;
1382 clist->title_window = NULL;
1383 clist->cursor_drag = NULL;
1384 clist->xor_gc = NULL;
1385 clist->fg_gc = NULL;
1386 clist->bg_gc = NULL;
1390 gtk_clist_map (GtkWidget * widget)
1395 g_return_if_fail (widget != NULL);
1396 g_return_if_fail (GTK_IS_CLIST (widget));
1398 clist = GTK_CLIST (widget);
1400 if (!GTK_WIDGET_MAPPED (widget))
1402 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1404 gdk_window_show (widget->window);
1405 gdk_window_show (clist->title_window);
1406 gdk_window_show (clist->clist_window);
1408 /* map column buttons*/
1409 for (i = 0; i < clist->columns; i++)
1410 if (GTK_WIDGET_VISIBLE (clist->column[i].button) &&
1411 !GTK_WIDGET_MAPPED (clist->column[i].button))
1412 gtk_widget_map (clist->column[i].button);
1414 /* map vscrollbars */
1415 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
1416 !GTK_WIDGET_MAPPED (clist->vscrollbar))
1417 gtk_widget_map (clist->vscrollbar);
1419 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
1420 !GTK_WIDGET_MAPPED (clist->hscrollbar))
1421 gtk_widget_map (clist->hscrollbar);
1423 /* unfreeze the list */
1424 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
1429 gtk_clist_unmap (GtkWidget * widget)
1434 g_return_if_fail (widget != NULL);
1435 g_return_if_fail (GTK_IS_CLIST (widget));
1437 clist = GTK_CLIST (widget);
1439 if (GTK_WIDGET_MAPPED (widget))
1441 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1443 gdk_window_hide (clist->clist_window);
1444 gdk_window_hide (clist->title_window);
1445 gdk_window_hide (widget->window);
1447 /* unmap scrollbars */
1448 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
1449 gtk_widget_unmap (clist->vscrollbar);
1451 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
1452 gtk_widget_unmap (clist->hscrollbar);
1454 /* unmap column buttons */
1455 for (i = 0; i < clist->columns; i++)
1456 if (GTK_WIDGET_MAPPED (clist->column[i].button))
1457 gtk_widget_unmap (clist->column[i].button);
1459 /* freeze the list */
1460 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1465 gtk_clist_draw_row (GtkCList * clist,
1466 GdkRectangle * area,
1468 GtkCListRow * clist_row)
1471 GdkGC *fg_gc, *bg_gc;
1472 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
1474 gint i, offset = 0, width, height, pixmap_width = 0;
1475 gint xsrc, ysrc, xdest, ydest;
1477 g_return_if_fail (clist != NULL);
1479 /* bail now if we arn't drawable yet */
1480 if (!GTK_WIDGET_DRAWABLE (clist))
1483 if (row < 0 || row >= clist->rows)
1486 widget = GTK_WIDGET (clist);
1488 /* if the function is passed the pointer to the row instead of null,
1489 * it avoids this expensive lookup */
1491 clist_row = (g_list_nth (clist->row_list, row))->data;
1493 /* rectangle of the entire row */
1494 row_rectangle.x = 0;
1495 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1496 row_rectangle.width = clist->clist_window_width;
1497 row_rectangle.height = clist->row_height;
1499 /* rectangle of the cell spacing above the row */
1500 cell_rectangle.x = 0;
1501 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1502 cell_rectangle.width = row_rectangle.width;
1503 cell_rectangle.height = CELL_SPACING;
1505 /* rectangle used to clip drawing operations, it's y and height
1506 * positions only need to be set once, so we set them once here.
1507 * the x and width are set withing the drawing loop below once per
1509 clip_rectangle.y = row_rectangle.y;
1510 clip_rectangle.height = row_rectangle.height;
1512 /* select GC for background rectangle */
1513 if (clist_row->state == GTK_STATE_SELECTED)
1515 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
1516 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
1520 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1521 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1523 fg_gc = clist->fg_gc;
1524 bg_gc = clist->bg_gc;
1530 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1531 gdk_window_clear_area (clist->clist_window,
1532 intersect_rectangle.x,
1533 intersect_rectangle.y,
1534 intersect_rectangle.width,
1535 intersect_rectangle.height);
1537 /* the last row has to clear it's bottom cell spacing too */
1538 if (clist_row == clist->row_list_end->data)
1540 cell_rectangle.y += clist->row_height + CELL_SPACING;
1542 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1543 gdk_window_clear_area (clist->clist_window,
1544 intersect_rectangle.x,
1545 intersect_rectangle.y,
1546 intersect_rectangle.width,
1547 intersect_rectangle.height);
1550 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
1553 gdk_draw_rectangle (clist->clist_window,
1556 intersect_rectangle.x,
1557 intersect_rectangle.y,
1558 intersect_rectangle.width,
1559 intersect_rectangle.height);
1563 gdk_window_clear_area (clist->clist_window,
1566 cell_rectangle.width,
1567 cell_rectangle.height);
1569 cell_rectangle.y += clist->row_height + CELL_SPACING;
1570 gdk_window_clear_area (clist->clist_window,
1573 cell_rectangle.width,
1574 cell_rectangle.height);
1576 gdk_draw_rectangle (clist->clist_window,
1581 row_rectangle.width,
1582 row_rectangle.height);
1586 /* iterate and draw all the columns (row cells) and draw their contents */
1587 for (i = 0; i < clist->columns; i++)
1589 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1590 clip_rectangle.width = clist->column[i].area.width;
1592 /* calculate clipping region clipping region */
1595 rect = &clip_rectangle;
1599 if (!gdk_rectangle_intersect (area, &clip_rectangle, &intersect_rectangle))
1601 rect = &intersect_rectangle;
1604 /* calculate real width for column justification */
1605 switch (clist_row->cell[i].type)
1607 case GTK_CELL_EMPTY:
1612 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1613 GTK_CELL_TEXT (clist_row->cell[i])->text);
1616 case GTK_CELL_PIXMAP:
1617 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
1618 pixmap_width = width;
1621 case GTK_CELL_PIXTEXT:
1622 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
1623 pixmap_width = width;
1624 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1625 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1626 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1629 case GTK_CELL_WIDGET:
1639 switch (clist->column[i].justification)
1641 case GTK_JUSTIFY_LEFT:
1642 offset = clip_rectangle.x;
1645 case GTK_JUSTIFY_RIGHT:
1646 offset = (clip_rectangle.x + clip_rectangle.width) - width;
1649 case GTK_JUSTIFY_CENTER:
1650 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1653 case GTK_JUSTIFY_FILL:
1654 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1662 /* Draw Text or Pixmap */
1663 switch (clist_row->cell[i].type)
1665 case GTK_CELL_EMPTY:
1670 gdk_gc_set_clip_rectangle (fg_gc, rect);
1672 gdk_draw_string (clist->clist_window,
1673 widget->style->font,
1675 offset + clist_row->cell[i].horizontal,
1676 row_rectangle.y + clist->row_center_offset +
1677 clist_row->cell[i].verticle,
1678 GTK_CELL_TEXT (clist_row->cell[i])->text);
1680 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1683 case GTK_CELL_PIXMAP:
1686 xdest = offset + clist_row->cell[i].horizontal;
1687 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1688 clist_row->cell[i].verticle;
1690 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
1691 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1693 gdk_draw_pixmap (clist->clist_window,
1695 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1699 pixmap_width, height);
1701 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1702 gdk_gc_set_clip_mask (fg_gc, NULL);
1705 case GTK_CELL_PIXTEXT:
1706 /* draw the pixmap */
1709 xdest = offset + clist_row->cell[i].horizontal;
1710 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1711 clist_row->cell[i].verticle;
1713 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
1714 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1716 gdk_draw_pixmap (clist->clist_window,
1718 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1722 pixmap_width, height);
1724 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1726 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1728 /* draw the string */
1729 gdk_gc_set_clip_rectangle (fg_gc, rect);
1731 gdk_draw_string (clist->clist_window,
1732 widget->style->font,
1734 offset + clist_row->cell[i].horizontal,
1735 row_rectangle.y + clist->row_center_offset +
1736 clist_row->cell[i].verticle,
1737 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1739 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1743 case GTK_CELL_WIDGET:
1756 gtk_clist_draw_rows (GtkCList * clist,
1757 GdkRectangle * area)
1760 GtkCListRow *clist_row;
1761 int i, first_row, last_row;
1763 g_return_if_fail (clist != NULL);
1764 g_return_if_fail (GTK_IS_CLIST (clist));
1766 if (clist->row_height == 0)
1771 first_row = ROW_FROM_YPIXEL (clist, area->y);
1772 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
1776 first_row = ROW_FROM_YPIXEL (clist, 0);
1777 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
1780 list = g_list_nth (clist->row_list, first_row);
1784 clist_row = list->data;
1790 gtk_clist_draw_row (clist, area, i, clist_row);
1795 gdk_window_clear_area (clist->clist_window,
1796 0, ROW_TOP_YPIXEL (clist, i) - CELL_SPACING,
1801 gtk_clist_get_selection_info (GtkCList * clist,
1809 g_return_val_if_fail (clist != NULL, 0);
1811 /* bounds checking, return false if the user clicked
1812 * on a blank area */
1813 trow = ROW_FROM_YPIXEL (clist, y);
1814 if (trow >= clist->rows)
1820 tcol = COLUMN_FROM_XPIXEL (clist, x);
1821 if (tcol >= clist->columns)
1831 gtk_clist_real_select_row (GtkCList * clist,
1834 GdkEventButton * event)
1838 GtkCListRow *clist_row;
1840 g_return_if_fail (clist != NULL);
1842 if (row < 0 || row >= clist->rows)
1845 switch (clist->selection_mode)
1847 case GTK_SELECTION_SINGLE:
1849 list = clist->row_list;
1852 clist_row = list->data;
1857 if (clist_row->state == GTK_STATE_SELECTED)
1859 clist_row->state = GTK_STATE_NORMAL;
1860 gtk_clist_unselect_row (clist, i, column);
1864 clist_row->state = GTK_STATE_SELECTED;
1865 clist->selection = g_list_append (clist->selection, clist_row);
1868 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1869 gtk_clist_draw_row (clist, NULL, row, clist_row);
1871 else if (clist_row->state == GTK_STATE_SELECTED)
1873 gtk_clist_unselect_row (clist, i, column);
1880 case GTK_SELECTION_BROWSE:
1882 list = clist->row_list;
1885 clist_row = list->data;
1890 if (clist_row->state != GTK_STATE_SELECTED)
1892 clist_row->state = GTK_STATE_SELECTED;
1893 clist->selection = g_list_append (clist->selection, clist_row);
1895 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1896 gtk_clist_draw_row (clist, NULL, row, clist_row);
1899 else if (clist_row->state == GTK_STATE_SELECTED)
1901 gtk_clist_unselect_row (clist, i, column);
1908 case GTK_SELECTION_MULTIPLE:
1910 list = clist->row_list;
1913 clist_row = list->data;
1918 if (clist_row->state == GTK_STATE_SELECTED)
1920 clist_row->state = GTK_STATE_NORMAL;
1921 gtk_clist_unselect_row (clist, i, column);
1925 clist->selection = g_list_append (clist->selection, clist_row);
1926 clist_row->state = GTK_STATE_SELECTED;
1929 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1930 gtk_clist_draw_row (clist, NULL, row, clist_row);
1937 case GTK_SELECTION_EXTENDED:
1946 gtk_clist_real_unselect_row (GtkCList * clist,
1949 GdkEventButton * event)
1951 GtkCListRow *clist_row;
1953 g_return_if_fail (clist != NULL);
1955 if (row < 0 || row > (clist->rows - 1))
1958 clist_row = (g_list_nth (clist->row_list, row))->data;
1959 clist_row->state = GTK_STATE_NORMAL;
1960 clist->selection = g_list_remove (clist->selection, clist_row);
1962 if (!GTK_CLIST_FROZEN (clist) && gtk_clist_row_isvisable (clist, row))
1963 gtk_clist_draw_row (clist, NULL, row, clist_row);
1967 gtk_clist_draw (GtkWidget * widget,
1968 GdkRectangle * area)
1972 g_return_if_fail (widget != NULL);
1973 g_return_if_fail (GTK_IS_CLIST (widget));
1974 g_return_if_fail (area != NULL);
1976 if (GTK_WIDGET_DRAWABLE (widget))
1978 clist = GTK_CLIST (widget);
1980 gdk_window_clear_area (widget->window,
1982 area->width, area->height);
1984 /* draw list shadow/border */
1985 gtk_draw_shadow (widget->style, widget->window,
1986 GTK_STATE_NORMAL, clist->shadow_type,
1988 clist->clist_window_width + (2 * widget->style->klass->xthickness),
1989 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
1990 clist->column_title_area.height);
1992 gdk_window_clear_area (clist->clist_window,
1995 gtk_clist_draw_rows (clist, NULL);
2000 gtk_clist_expose (GtkWidget * widget,
2001 GdkEventExpose * event)
2005 g_return_val_if_fail (widget != NULL, FALSE);
2006 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2007 g_return_val_if_fail (event != NULL, FALSE);
2009 if (GTK_WIDGET_DRAWABLE (widget))
2011 clist = GTK_CLIST (widget);
2014 if (event->window == widget->window)
2015 gtk_draw_shadow (widget->style, widget->window,
2016 GTK_STATE_NORMAL, clist->shadow_type,
2018 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2019 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2020 clist->column_title_area.height);
2022 /* exposure events on the list */
2023 if (event->window == clist->clist_window)
2024 gtk_clist_draw_rows (clist, &event->area);
2031 gtk_clist_button_press (GtkWidget * widget,
2032 GdkEventButton * event)
2035 gint x, y, row, column;
2037 g_return_val_if_fail (widget != NULL, FALSE);
2038 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2039 g_return_val_if_fail (event != NULL, FALSE);
2041 clist = GTK_CLIST (widget);
2043 /* selections on the list */
2044 if (event->window == clist->clist_window)
2049 if (gtk_clist_get_selection_info (clist, x, y, &row, &column))
2050 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2051 row, column, event);
2058 gtk_clist_size_request (GtkWidget * widget,
2059 GtkRequisition * requisition)
2064 g_return_if_fail (widget != NULL);
2065 g_return_if_fail (GTK_IS_CLIST (widget));
2066 g_return_if_fail (requisition != NULL);
2068 clist = GTK_CLIST (widget);
2070 requisition->width = 0;
2071 requisition->height = 0;
2073 /* compute the size of the column title (title) area */
2074 clist->column_title_area.height = 0;
2075 for (i = 0; i < clist->columns; i++)
2077 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
2078 clist->column_title_area.height = MAX (clist->column_title_area.height,
2079 clist->column[i].button->requisition.height);
2081 requisition->height += clist->column_title_area.height;
2083 /* add the vscrollbar space */
2084 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2085 GTK_WIDGET_VISIBLE (clist->vscrollbar))
2087 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
2089 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
2090 requisition->height = MAX (requisition->height,
2091 clist->vscrollbar->requisition.height);
2094 /* add the hscrollbar space */
2095 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2096 GTK_WIDGET_VISIBLE (clist->hscrollbar))
2098 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
2100 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
2101 requisition->width = MAX (clist->hscrollbar->requisition.width,
2102 requisition->width -
2103 clist->vscrollbar->requisition.width);
2107 requisition->width += widget->style->klass->xthickness * 2 +
2108 GTK_CONTAINER (widget)->border_width * 2;
2109 requisition->height += widget->style->klass->ythickness * 2 +
2110 GTK_CONTAINER (widget)->border_width * 2;
2114 gtk_clist_size_allocate (GtkWidget * widget,
2115 GtkAllocation * allocation)
2118 GtkAllocation clist_allocation;
2119 GtkAllocation child_allocation;
2120 gint i, vscrollbar_vis, hscrollbar_vis;
2122 g_return_if_fail (widget != NULL);
2123 g_return_if_fail (GTK_IS_CLIST (widget));
2124 g_return_if_fail (allocation != NULL);
2126 clist = GTK_CLIST (widget);
2127 widget->allocation = *allocation;
2129 if (GTK_WIDGET_REALIZED (widget))
2131 gdk_window_move_resize (widget->window,
2132 allocation->x + GTK_CONTAINER (widget)->border_width,
2133 allocation->y + GTK_CONTAINER (widget)->border_width,
2134 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
2135 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
2137 /* use internal allocation structure for all the math
2138 * because it's easier than always subtracting the container
2140 clist->internal_allocation.x = 0;
2141 clist->internal_allocation.y = 0;
2142 clist->internal_allocation.width = allocation->width -
2143 GTK_CONTAINER (widget)->border_width * 2;
2144 clist->internal_allocation.height = allocation->height -
2145 GTK_CONTAINER (widget)->border_width * 2;
2147 /* allocate clist window assuming no scrollbars */
2148 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2149 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2150 clist->column_title_area.height;
2151 clist_allocation.width = clist->internal_allocation.width -
2152 (2 * widget->style->klass->xthickness);
2153 clist_allocation.height = clist->internal_allocation.height -
2154 (2 * widget->style->klass->xthickness) -
2155 clist->column_title_area.height;
2158 * here's where we decide to show/not show the scrollbars
2163 for (i = 0; i <= 1; i++)
2165 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
2166 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2172 if (!vscrollbar_vis)
2175 clist_allocation.width -= clist->vscrollbar->requisition.width +
2176 SCROLLBAR_SPACING (clist);
2180 if (LIST_WIDTH (clist) <= clist_allocation.width &&
2181 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2187 if (!hscrollbar_vis)
2190 clist_allocation.height -= clist->hscrollbar->requisition.height +
2191 SCROLLBAR_SPACING (clist);
2196 clist->clist_window_width = clist_allocation.width;
2197 clist->clist_window_height = clist_allocation.height;
2199 gdk_window_move_resize (clist->clist_window,
2202 clist_allocation.width,
2203 clist_allocation.height);
2205 /* position the window which holds the column title buttons */
2206 clist->column_title_area.x = widget->style->klass->xthickness;
2207 clist->column_title_area.y = widget->style->klass->ythickness;
2208 clist->column_title_area.width = clist_allocation.width;
2210 gdk_window_move_resize (clist->title_window,
2211 clist->column_title_area.x,
2212 clist->column_title_area.y,
2213 clist->column_title_area.width,
2214 clist->column_title_area.height);
2216 /* column button allocation */
2217 gtk_clist_size_allocate_title_buttons (clist);
2218 gtk_clist_size_allocate_columns (clist);
2220 /* allocate the vscrollbar */
2223 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2224 gtk_widget_show (clist->vscrollbar);
2226 child_allocation.x = clist->internal_allocation.x +
2227 clist->internal_allocation.width -
2228 clist->vscrollbar->requisition.width;
2229 child_allocation.y = clist->internal_allocation.y;
2230 child_allocation.width = clist->vscrollbar->requisition.width;
2231 child_allocation.height = clist->internal_allocation.height -
2232 SCROLLBAR_SPACING (clist) -
2233 (hscrollbar_vis ? clist->hscrollbar->requisition.height : 0);
2235 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
2239 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2240 gtk_widget_hide (clist->vscrollbar);
2245 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2246 gtk_widget_show (clist->hscrollbar);
2248 child_allocation.x = clist->internal_allocation.x;
2249 child_allocation.y = clist->internal_allocation.y +
2250 clist->internal_allocation.height -
2251 clist->hscrollbar->requisition.height;
2252 child_allocation.width = clist->internal_allocation.width -
2253 SCROLLBAR_SPACING (clist) -
2254 (vscrollbar_vis ? clist->vscrollbar->requisition.width : 0);
2255 child_allocation.height = clist->hscrollbar->requisition.height;
2257 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
2261 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2262 gtk_widget_hide (clist->hscrollbar);
2267 * set the vscrollbar adjustments
2269 gtk_clist_adjust_scrollbars (clist);
2273 gtk_clist_size_allocate_title_buttons (GtkCList * clist)
2276 GtkAllocation button_allocation;
2278 button_allocation.x = clist->hoffset;
2279 button_allocation.y = 0;
2280 button_allocation.height = clist->column_title_area.height;
2282 for (i = 0; i < clist->columns; i++)
2284 button_allocation.width = clist->column[i].width;
2286 if (i == clist->columns - 1)
2288 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
2290 if (button_allocation.width < (clist->column_title_area.width - button_allocation.x))
2291 button_allocation.width = clist->column_title_area.width - button_allocation.x;
2295 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
2298 gtk_widget_size_allocate (clist->column[i].button, &button_allocation);
2299 button_allocation.x += button_allocation.width;
2304 gtk_clist_size_allocate_columns (GtkCList * clist)
2310 for (i = 0; i < clist->columns; i++)
2312 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
2314 if (i == clist->columns - 1)
2316 clist->column[i].area.width = MAX (clist->column[i].width,
2317 clist->column_title_area.width -
2318 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
2322 clist->column[i].area.width = clist->column[i].width;
2325 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
2330 gtk_clist_foreach (GtkContainer * container,
2331 GtkCallback callback,
2332 gpointer callback_data)
2337 g_return_if_fail (container != NULL);
2338 g_return_if_fail (GTK_IS_CLIST (container));
2339 g_return_if_fail (callback != NULL);
2341 clist = GTK_CLIST (container);
2343 /* callback for the column buttons */
2344 for (i = 0; i < clist->columns; i++)
2345 (*callback) (clist->column[i].button, callback_data);
2347 /* callbacks for the scrollbars */
2348 (*callback) (clist->vscrollbar, callback_data);
2349 (*callback) (clist->hscrollbar, callback_data);
2354 gtk_clist_column_button_realize (GtkWidget * widget,
2359 g_return_if_fail (widget != NULL);
2360 g_return_if_fail (GTK_IS_CLIST (data));
2362 clist = GTK_CLIST (data);
2364 if (widget->window && clist->title_window)
2365 gdk_window_reparent (widget->window, clist->title_window,
2366 widget->allocation.x, 0);
2370 gtk_clist_column_button_clicked (GtkWidget * widget,
2376 g_return_if_fail (widget != NULL);
2377 g_return_if_fail (GTK_IS_CLIST (data));
2379 clist = GTK_CLIST (data);
2381 /* find the column who's button was pressed */
2382 for (i = 0; i < clist->columns; i++)
2383 if (clist->column[i].button == widget)
2386 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
2393 * gtk_clist_adjust_scrollbars
2394 * gtk_clist_vadjustment_changed
2395 * gtk_clist_hadjustment_changed
2396 * gtk_clist_vadjustment_value_changed
2397 * gtk_clist_hadjustment_value_changed
2400 gtk_clist_adjust_scrollbars (GtkCList * clist)
2402 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
2403 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
2404 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
2405 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
2406 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
2408 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
2410 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
2411 clist->clist_window_height;
2412 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
2416 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
2417 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
2418 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
2419 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
2420 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
2422 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
2424 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
2425 clist->clist_window_width;
2426 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
2430 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
2431 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2433 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2435 gtk_widget_hide (clist->vscrollbar);
2436 gtk_widget_queue_resize (GTK_WIDGET (clist));
2441 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2443 gtk_widget_show (clist->vscrollbar);
2444 gtk_widget_queue_resize (GTK_WIDGET (clist));
2448 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
2449 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2451 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2453 gtk_widget_hide (clist->hscrollbar);
2454 gtk_widget_queue_resize (GTK_WIDGET (clist));
2459 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2461 gtk_widget_show (clist->hscrollbar);
2462 gtk_widget_queue_resize (GTK_WIDGET (clist));
2466 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
2467 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
2471 gtk_clist_vadjustment_changed (GtkAdjustment * adjustment,
2476 g_return_if_fail (adjustment != NULL);
2477 g_return_if_fail (data != NULL);
2479 clist = GTK_CLIST (data);
2483 gtk_clist_hadjustment_changed (GtkAdjustment * adjustment,
2488 g_return_if_fail (adjustment != NULL);
2489 g_return_if_fail (data != NULL);
2491 clist = GTK_CLIST (data);
2495 gtk_clist_vadjustment_value_changed (GtkAdjustment * adjustment,
2502 g_return_if_fail (adjustment != NULL);
2503 g_return_if_fail (data != NULL);
2504 g_return_if_fail (GTK_IS_CLIST (data));
2506 clist = GTK_CLIST (data);
2508 value = adjustment->value;
2510 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
2512 if (value > -clist->voffset)
2515 diff = value + clist->voffset;
2517 /* we have to re-draw the whole screen here... */
2518 if (diff >= clist->clist_window_height)
2520 clist->voffset = -value;
2521 gtk_clist_draw_rows (clist, NULL);
2525 gdk_window_copy_area (clist->clist_window,
2526 GTK_WIDGET (clist)->style->white_gc,
2528 clist->clist_window,
2531 clist->clist_window_width,
2532 clist->clist_window_height - diff);
2535 area.y = clist->clist_window_height - diff;
2536 area.width = clist->clist_window_width;
2542 diff = -clist->voffset - value;
2544 /* we have to re-draw the whole screen here... */
2545 if (diff >= clist->clist_window_height)
2547 clist->voffset = -value;
2548 gtk_clist_draw_rows (clist, NULL);
2552 gdk_window_copy_area (clist->clist_window,
2553 GTK_WIDGET (clist)->style->white_gc,
2555 clist->clist_window,
2558 clist->clist_window_width,
2559 clist->clist_window_height - diff);
2563 area.width = clist->clist_window_width;
2568 clist->voffset = -value;
2571 gtk_clist_draw_rows (clist, &area);
2575 gtk_clist_hadjustment_value_changed (GtkAdjustment * adjustment,
2580 gint i, diff, value;
2582 g_return_if_fail (adjustment != NULL);
2583 g_return_if_fail (data != NULL);
2584 g_return_if_fail (GTK_IS_CLIST (data));
2586 clist = GTK_CLIST (data);
2588 value = adjustment->value;
2590 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
2592 for (i = 0; i < clist->columns; i++)
2594 clist->column[i].button->allocation.x -= value + clist->hoffset;
2596 if (clist->column[i].button->window)
2597 gdk_window_move (clist->column[i].button->window,
2598 clist->column[i].button->allocation.x,
2599 clist->column[i].button->allocation.y);
2602 if (value > -clist->hoffset)
2605 diff = value + clist->hoffset;
2607 /* we have to re-draw the whole screen here... */
2608 if (diff >= clist->clist_window_width)
2610 clist->hoffset = -value;
2611 gtk_clist_draw_rows (clist, NULL);
2615 gdk_window_copy_area (clist->clist_window,
2616 GTK_WIDGET (clist)->style->white_gc,
2618 clist->clist_window,
2621 clist->clist_window_width - diff,
2622 clist->clist_window_height);
2624 area.x = clist->clist_window_width - diff;
2627 area.height = clist->clist_window_height;
2632 diff = -clist->hoffset - value;
2634 /* we have to re-draw the whole screen here... */
2635 if (diff >= clist->clist_window_width)
2637 clist->hoffset = -value;
2638 gtk_clist_draw_rows (clist, NULL);
2642 gdk_window_copy_area (clist->clist_window,
2643 GTK_WIDGET (clist)->style->white_gc,
2645 clist->clist_window,
2648 clist->clist_window_width - diff,
2649 clist->clist_window_height);
2654 area.height = clist->clist_window_height;
2657 clist->hoffset = -value;
2660 gtk_clist_draw_rows (clist, &area);
2664 * Memory Allocation/Distruction Routines for GtkCList stuctures
2667 * gtk_clist_columns_new
2668 * gtk_clist_column_title_new
2669 * gtk_clist_columns_delete
2671 * gtk_clist_row_delete
2672 * gtk_clist_cell_empty
2673 * gtk_clist_cell_set_text
2674 * gtk_clist_cell_set_pixmap
2676 static GtkCListColumn *
2677 gtk_clist_columns_new (GtkCList * clist)
2680 GtkCListColumn *column;
2682 column = g_new (GtkCListColumn, clist->columns);
2684 for (i = 0; i < clist->columns; i++)
2686 column[i].area.x = 0;
2687 column[i].area.y = 0;
2688 column[i].area.width = 0;
2689 column[i].area.height = 0;
2690 column[i].title = NULL;
2691 column[i].button = NULL;
2692 column[i].width = 0;
2693 column[i].justification = GTK_JUSTIFY_LEFT;
2700 gtk_clist_column_title_new (GtkCList * clist,
2704 if (clist->column[column].title)
2705 g_free (clist->column[column].title);
2707 clist->column[column].title = g_strdup (title);
2711 gtk_clist_columns_delete (GtkCList * clist)
2715 for (i = 0; i < clist->columns; i++)
2716 if (clist->column[i].title)
2717 g_free (clist->column[i].title);
2719 g_free (clist->column);
2722 static GtkCListRow *
2723 gtk_clist_row_new (GtkCList * clist)
2726 GtkCListRow *clist_row;
2728 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
2729 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
2731 for (i = 0; i < clist->columns; i++)
2733 clist_row->cell[i].type = GTK_CELL_EMPTY;
2734 clist_row->cell[i].verticle = 0;
2735 clist_row->cell[i].horizontal = 0;
2738 clist_row->foreground = GTK_WIDGET (clist)->style->fg[GTK_STATE_NORMAL];
2739 clist_row->background = GTK_WIDGET (clist)->style->bg[GTK_STATE_PRELIGHT];
2740 clist_row->state = GTK_STATE_NORMAL;
2741 clist_row->data = NULL;
2747 gtk_clist_row_delete (GtkCList * clist,
2748 GtkCListRow * clist_row)
2752 for (i = 0; i < clist->columns; i++)
2753 gtk_clist_cell_empty (clist, clist_row, i);
2755 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
2756 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
2761 gtk_clist_cell_empty (GtkCList * clist,
2762 GtkCListRow * clist_row,
2765 switch (clist_row->cell[column].type)
2767 case GTK_CELL_EMPTY:
2771 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2774 case GTK_CELL_PIXMAP:
2775 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2776 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2779 case GTK_CELL_PIXTEXT:
2780 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2781 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2782 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2785 case GTK_CELL_WIDGET:
2793 clist_row->cell[column].type = GTK_CELL_EMPTY;
2797 gtk_clist_cell_set_text (GtkCList * clist,
2798 GtkCListRow * clist_row,
2802 gtk_clist_cell_empty (clist, clist_row, column);
2806 clist_row->cell[column].type = GTK_CELL_TEXT;
2807 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2812 gtk_clist_cell_set_pixmap (GtkCList * clist,
2813 GtkCListRow * clist_row,
2818 gtk_clist_cell_empty (clist, clist_row, column);
2822 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2823 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2824 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2829 gtk_clist_cell_set_pixtext (GtkCList * clist,
2830 GtkCListRow * clist_row,
2837 gtk_clist_cell_empty (clist, clist_row, column);
2839 if (text && pixmap && mask)
2841 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2842 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2843 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2844 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2845 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;