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 number rows memchunk expands at a time */
24 #define CLIST_OPTIMUM_SIZE 512
26 /* the width of the column resize windows */
29 /* minimum allowed width of a column */
30 #define COLUMN_MIN_WIDTH 5
32 /* this defigns the base grid spacing */
33 #define CELL_SPACING 1
35 /* added the horizontal space at the beginning and end of a row*/
36 #define COLUMN_INSET 3
38 /* scrollbar spacing class macro */
39 #define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
41 /* gives the top pixel of the given row in context of
42 * the clist's voffset */
43 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
44 (((row) + 1) * CELL_SPACING) + \
47 /* returns the row index from a y pixel location in the
48 * context of the clist's voffset */
49 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
50 ((clist)->row_height + CELL_SPACING))
52 /* gives the left pixel of the given column in context of
53 * the clist's hoffset */
54 #define COLUMN_LEFT_XPIXEL(clist, column) ((clist)->column[(column)].area.x + \
57 /* returns the column index from a x pixel location in the
58 * context of the clist's hoffset */
60 COLUMN_FROM_XPIXEL (GtkCList * clist,
65 for (i = 0; i < clist->columns; i++)
67 cx = clist->column[i].area.x + clist->hoffset;
69 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
70 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
78 /* returns the top pixel of the given row in the context of
80 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
82 /* returns the left pixel of the given column in the context of
84 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
86 /* returns the total height of the list */
87 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
88 (CELL_SPACING * ((clist)->rows + 1)))
90 /* returns the total width of the list */
91 #define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
92 (clist)->column[(clist)->columns - 1].area.width + \
93 COLUMN_INSET + CELL_SPACING)
112 typedef void (*GtkCListSignal1) (GtkObject * object,
115 GdkEventButton * arg3,
118 typedef void (*GtkCListSignal2) (GtkObject * object,
123 static void sync_selection (GtkCList * clist,
127 /* GtkCList Methods */
128 static void gtk_clist_class_init (GtkCListClass * klass);
129 static void gtk_clist_init (GtkCList * clist);
131 /* GtkObject Methods */
132 static void gtk_clist_destroy (GtkObject * object);
133 static void gtk_clist_finalize (GtkObject * object);
136 /* GtkWidget Methods */
137 static void gtk_clist_realize (GtkWidget * widget);
138 static void gtk_clist_unrealize (GtkWidget * widget);
139 static void gtk_clist_map (GtkWidget * widget);
140 static void gtk_clist_unmap (GtkWidget * widget);
141 static void gtk_clist_draw (GtkWidget * widget,
142 GdkRectangle * area);
143 static gint gtk_clist_expose (GtkWidget * widget,
144 GdkEventExpose * event);
145 static gint gtk_clist_button_press (GtkWidget * widget,
146 GdkEventButton * event);
147 static gint gtk_clist_button_release (GtkWidget * widget,
148 GdkEventButton * event);
149 static gint gtk_clist_motion (GtkWidget * widget,
150 GdkEventMotion * event);
152 static void gtk_clist_size_request (GtkWidget * widget,
153 GtkRequisition * requisition);
154 static void gtk_clist_size_allocate (GtkWidget * widget,
155 GtkAllocation * allocation);
156 static gint get_selection_info (GtkCList * clist,
162 /* GtkContainer Methods */
163 static void gtk_clist_foreach (GtkContainer * container,
164 GtkCallback callback,
165 gpointer callback_data);
168 static void draw_row (GtkCList * clist,
171 GtkCListRow * clist_row);
172 static void draw_rows (GtkCList * clist,
173 GdkRectangle * area);
175 /* Size Allocation */
176 static void size_allocate_title_buttons (GtkCList * clist);
177 static void size_allocate_columns (GtkCList * clist);
180 static void toggle_row (GtkCList * clist,
183 GdkEventButton * event);
184 static void select_row (GtkCList * clist,
187 GdkEventButton * event);
188 static void unselect_row (GtkCList * clist,
191 GdkEventButton * event);
193 static void real_select_row (GtkCList * clist,
196 GdkEventButton * event);
197 static void real_unselect_row (GtkCList * clist,
200 GdkEventButton * event);
203 static void draw_xor_line (GtkCList * clist);
204 static gint new_column_width (GtkCList * clist,
208 static void resize_column (GtkCList * clist,
213 static void column_button_create (GtkCList * clist,
215 static void column_button_clicked (GtkWidget * widget,
219 static void create_scrollbars (GtkCList * clist);
220 static void adjust_scrollbars (GtkCList * clist);
221 static void check_exposures (GtkCList * clist);
222 static void vadjustment_changed (GtkAdjustment * adjustment,
224 static void vadjustment_value_changed (GtkAdjustment * adjustment,
226 static void hadjustment_changed (GtkAdjustment * adjustment,
228 static void hadjustment_value_changed (GtkAdjustment * adjustment,
232 /* Memory Allocation/Distruction Routines */
233 static GtkCListColumn *columns_new (GtkCList * clist);
235 static void column_title_new (GtkCList * clist,
238 static void columns_delete (GtkCList * clist);
240 static GtkCListRow *row_new (GtkCList * clist);
242 static void row_delete (GtkCList * clist,
243 GtkCListRow * clist_row);
244 static void cell_empty (GtkCList * clist,
245 GtkCListRow * clist_row,
247 static void cell_set_text (GtkCList * clist,
248 GtkCListRow * clist_row,
251 static void cell_set_pixmap (GtkCList * clist,
252 GtkCListRow * clist_row,
256 static void cell_set_pixtext (GtkCList * clist,
257 GtkCListRow * clist_row,
265 static void gtk_clist_marshal_signal_1 (GtkObject * object,
269 static void gtk_clist_marshal_signal_2 (GtkObject * object,
274 /* Fill in data after widget is realized and has style */
276 static void add_style_data (GtkCList * clist);
278 static GtkContainerClass *parent_class = NULL;
279 static guint clist_signals[LAST_SIGNAL] = {0};
283 gtk_clist_get_type ()
285 static guint clist_type = 0;
289 GtkTypeInfo clist_info =
293 sizeof (GtkCListClass),
294 (GtkClassInitFunc) gtk_clist_class_init,
295 (GtkObjectInitFunc) gtk_clist_init,
296 (GtkArgSetFunc) NULL,
297 (GtkArgGetFunc) NULL,
300 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
307 gtk_clist_class_init (GtkCListClass * klass)
309 GtkObjectClass *object_class;
310 GtkWidgetClass *widget_class;
311 GtkContainerClass *container_class;
313 object_class = (GtkObjectClass *) klass;
314 widget_class = (GtkWidgetClass *) klass;
315 container_class = (GtkContainerClass *) klass;
317 parent_class = gtk_type_class (gtk_container_get_type ());
319 clist_signals[SELECT_ROW] =
320 gtk_signal_new ("select_row",
323 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
324 gtk_clist_marshal_signal_1,
325 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
326 clist_signals[UNSELECT_ROW] =
327 gtk_signal_new ("unselect_row",
330 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
331 gtk_clist_marshal_signal_1,
332 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
333 clist_signals[CLICK_COLUMN] =
334 gtk_signal_new ("click_column",
337 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
338 gtk_clist_marshal_signal_2,
339 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
341 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
343 object_class->destroy = gtk_clist_destroy;
344 object_class->finalize = gtk_clist_finalize;
346 widget_class->realize = gtk_clist_realize;
347 widget_class->unrealize = gtk_clist_unrealize;
348 widget_class->map = gtk_clist_map;
349 widget_class->unmap = gtk_clist_unmap;
350 widget_class->draw = gtk_clist_draw;
351 widget_class->button_press_event = gtk_clist_button_press;
352 widget_class->button_release_event = gtk_clist_button_release;
353 widget_class->motion_notify_event = gtk_clist_motion;
354 widget_class->expose_event = gtk_clist_expose;
355 widget_class->size_request = gtk_clist_size_request;
356 widget_class->size_allocate = gtk_clist_size_allocate;
358 container_class->add = NULL;
359 container_class->remove = NULL;
360 container_class->foreach = gtk_clist_foreach;
362 klass->select_row = real_select_row;
363 klass->unselect_row = real_unselect_row;
364 klass->click_column = NULL;
366 klass->scrollbar_spacing = 5;
370 gtk_clist_marshal_signal_1 (GtkObject * object,
375 GtkCListSignal1 rfunc;
377 rfunc = (GtkCListSignal1) func;
379 (*rfunc) (object, GTK_VALUE_INT (args[0]),
380 GTK_VALUE_INT (args[1]),
381 GTK_VALUE_POINTER (args[2]),
386 gtk_clist_marshal_signal_2 (GtkObject * object,
391 GtkCListSignal2 rfunc;
393 rfunc = (GtkCListSignal2) func;
395 (*rfunc) (object, GTK_VALUE_INT (args[0]),
400 gtk_clist_init (GtkCList * clist)
404 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
405 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
407 clist->row_mem_chunk = NULL;
408 clist->cell_mem_chunk = NULL;
411 clist->row_center_offset = 0;
412 clist->row_height = 0;
413 clist->row_list = NULL;
414 clist->row_list_end = NULL;
418 clist->title_window = NULL;
419 clist->column_title_area.x = 0;
420 clist->column_title_area.y = 0;
421 clist->column_title_area.width = 0;
422 clist->column_title_area.height = 0;
424 clist->clist_window = NULL;
425 clist->clist_window_width = 0;
426 clist->clist_window_height = 0;
431 clist->shadow_type = GTK_SHADOW_IN;
432 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
433 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
435 clist->cursor_drag = NULL;
436 clist->xor_gc = NULL;
441 clist->selection_mode = GTK_SELECTION_SINGLE;
442 clist->selection = NULL;
447 gtk_clist_construct (GtkCList * clist,
453 g_return_if_fail (clist != NULL);
454 g_return_if_fail (GTK_IS_CLIST (clist));
455 g_return_if_fail (clist->row_mem_chunk == NULL);
458 /* initalize memory chunks */
459 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
460 sizeof (GtkCListRow),
461 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
464 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
465 sizeof (GtkCell) * columns,
466 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
469 /* set number of columns, allocate memory */
470 clist->columns = columns;
471 clist->column = columns_new (clist);
473 /* there needs to be at least one column button
474 * because there is alot of code that will break if it
476 column_button_create (clist, 0);
478 /* create scrollbars */
479 create_scrollbars (clist);
483 GTK_CLIST_SET_FLAGS (clist, CLIST_SHOW_TITLES);
484 for (i = 0; i < columns; i++)
485 gtk_clist_set_column_title (clist, i, titles[i]);
489 GTK_CLIST_UNSET_FLAGS (clist, CLIST_SHOW_TITLES);
494 * GTKCLIST PUBLIC INTERFACE
495 * gtk_clist_new_with_titles
499 gtk_clist_new_with_titles (gint columns,
504 g_return_val_if_fail (titles != NULL, NULL);
506 widget = gtk_type_new (gtk_clist_get_type ());
508 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
514 gtk_clist_new (gint columns)
521 clist = gtk_type_new (gtk_clist_get_type ());
522 gtk_clist_construct (clist, columns, NULL);
523 return GTK_WIDGET (clist);
527 gtk_clist_set_border (GtkCList * clist,
528 GtkShadowType border)
530 g_return_if_fail (clist != NULL);
532 clist->shadow_type = border;
534 if (GTK_WIDGET_VISIBLE (clist))
535 gtk_widget_queue_resize (GTK_WIDGET (clist));
539 gtk_clist_set_selection_mode (GtkCList * clist,
540 GtkSelectionMode mode)
542 g_return_if_fail (clist != NULL);
544 clist->selection_mode = mode;
548 gtk_clist_freeze (GtkCList * clist)
550 g_return_if_fail (clist != NULL);
552 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
556 gtk_clist_thaw (GtkCList * clist)
558 g_return_if_fail (clist != NULL);
560 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
562 adjust_scrollbars (clist);
563 draw_rows (clist, NULL);
567 gtk_clist_column_titles_show (GtkCList * clist)
569 g_return_if_fail (clist != NULL);
571 if (!GTK_CLIST_SHOW_TITLES (clist))
573 GTK_CLIST_SET_FLAGS (clist, CLIST_SHOW_TITLES);
574 if (clist->title_window)
575 gdk_window_show (clist->title_window);
576 gtk_widget_queue_resize (GTK_WIDGET (clist));
581 gtk_clist_column_titles_hide (GtkCList * clist)
583 g_return_if_fail (clist != NULL);
585 if (GTK_CLIST_SHOW_TITLES (clist))
587 GTK_CLIST_UNSET_FLAGS (clist, CLIST_SHOW_TITLES);
588 if (clist->title_window)
589 gdk_window_hide (clist->title_window);
590 gtk_widget_queue_resize (GTK_WIDGET (clist));
595 gtk_clist_column_title_active (GtkCList * clist,
598 g_return_if_fail (clist != NULL);
600 if (column < 0 || column >= clist->columns)
603 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
604 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
606 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
607 if (GTK_WIDGET_VISIBLE (clist))
608 gtk_widget_queue_draw (clist->column[column].button);
613 gtk_clist_column_title_passive (GtkCList * clist,
616 g_return_if_fail (clist != NULL);
618 if (column < 0 || column >= clist->columns)
621 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
622 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
624 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
625 if (GTK_WIDGET_VISIBLE (clist))
626 gtk_widget_queue_draw (clist->column[column].button);
631 gtk_clist_column_titles_active (GtkCList * clist)
635 g_return_if_fail (clist != NULL);
637 for (i = 0; i < clist->columns; i++)
638 if (clist->column[i].button)
639 gtk_clist_column_title_active (clist, i);
643 gtk_clist_column_titles_passive (GtkCList * clist)
647 g_return_if_fail (clist != NULL);
649 for (i = 0; i < clist->columns; i++)
650 if (clist->column[i].button)
651 gtk_clist_column_title_passive (clist, i);
655 gtk_clist_set_column_title (GtkCList * clist,
660 GtkWidget *old_widget;
661 GtkWidget *alignment = NULL;
664 g_return_if_fail (clist != NULL);
666 if (column < 0 || column >= clist->columns)
669 /* if the column button doesn't currently exist,
670 * it has to be created first */
671 if (!clist->column[column].button)
673 column_button_create (clist, column);
677 column_title_new (clist, column, title);
679 /* remove and destroy the old widget */
680 old_widget = GTK_BUTTON (clist->column[column].button)->child;
682 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
684 /* create new alignment based no column justification */
685 switch (clist->column[column].justification)
687 case GTK_JUSTIFY_LEFT:
688 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
691 case GTK_JUSTIFY_RIGHT:
692 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
695 case GTK_JUSTIFY_CENTER:
696 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
699 case GTK_JUSTIFY_FILL:
700 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
704 label = gtk_label_new (clist->column[column].title);
705 gtk_container_add (GTK_CONTAINER (alignment), label);
706 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
707 gtk_widget_show (label);
708 gtk_widget_show (alignment);
710 /* if this button didn't previously exist, then the
711 * column button positions have to be re-computed */
712 if (GTK_WIDGET_VISIBLE (clist) && new_button)
713 size_allocate_title_buttons (clist);
717 gtk_clist_set_column_widget (GtkCList * clist,
722 GtkWidget *old_widget;
724 g_return_if_fail (clist != NULL);
726 if (column < 0 || column >= clist->columns)
729 /* if the column button doesn't currently exist,
730 * it has to be created first */
731 if (!clist->column[column].button)
733 column_button_create (clist, column);
737 column_title_new (clist, column, NULL);
739 /* remove and destroy the old widget */
740 old_widget = GTK_BUTTON (clist->column[column].button)->child;
742 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
744 /* add and show the widget */
747 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
748 gtk_widget_show (widget);
751 /* if this button didn't previously exist, then the
752 * column button positions have to be re-computed */
753 if (GTK_WIDGET_VISIBLE (clist) && new_button)
754 size_allocate_title_buttons (clist);
758 gtk_clist_set_column_justification (GtkCList * clist,
760 GtkJustification justification)
762 GtkWidget *alignment;
764 g_return_if_fail (clist != NULL);
766 if (column < 0 || column >= clist->columns)
769 clist->column[column].justification = justification;
771 /* change the alinment of the button title if it's not a
773 if (clist->column[column].title)
775 alignment = GTK_BUTTON (clist->column[column].button)->child;
777 switch (clist->column[column].justification)
779 case GTK_JUSTIFY_LEFT:
780 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
783 case GTK_JUSTIFY_RIGHT:
784 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
787 case GTK_JUSTIFY_CENTER:
788 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
791 case GTK_JUSTIFY_FILL:
792 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
800 if (!GTK_CLIST_FROZEN (clist))
801 draw_rows (clist, NULL);
805 gtk_clist_set_column_width (GtkCList * clist,
809 g_return_if_fail (clist != NULL);
811 if (column < 0 || column >= clist->columns)
814 clist->column[column].width = width;
815 clist->column[column].width_set = TRUE;
817 /* FIXME: this is quite expensive to do if the widget hasn't
818 * been size_allocated yet, and pointless. Should
821 size_allocate_columns (clist);
822 size_allocate_title_buttons (clist);
824 if (!GTK_CLIST_FROZEN (clist))
826 adjust_scrollbars (clist);
827 draw_rows (clist, NULL);
832 gtk_clist_set_row_height (GtkCList * clist,
837 g_return_if_fail (clist != NULL);
840 clist->row_height = height;
844 GTK_CLIST_SET_FLAGS (clist, CLIST_ROW_HEIGHT_SET);
846 if (GTK_WIDGET_REALIZED (clist))
848 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
849 GTK_WIDGET (clist) ->style->font->descent + 1);
850 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
853 if (!GTK_CLIST_FROZEN (clist))
855 adjust_scrollbars (clist);
856 draw_rows (clist, NULL);
861 gtk_clist_moveto (GtkCList * clist,
869 g_return_if_fail (clist != NULL);
871 if (row < -1 || row >= clist->rows)
873 if (column < -1 || column >= clist->columns)
876 /* adjust vertical scrollbar */
879 x = ROW_TOP (clist, row) - (row_align * (clist->clist_window_height -
880 (clist->row_height + 2 * CELL_SPACING)));
883 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
884 else if (x > LIST_HEIGHT (clist) - clist->clist_window_height)
885 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
886 clist->clist_window_height;
888 GTK_RANGE (clist->vscrollbar)->adjustment->value = x;
890 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
894 /* adjust horizontal scrollbar */
897 y = COLUMN_LEFT (clist, column) - (col_align * (clist->clist_window_width -
898 clist->column[column].area.width +
899 2 * (CELL_SPACING + COLUMN_INSET)));
902 GTK_RANGE (clist->hscrollbar)->adjustment->value = 0.0;
903 else if (y > LIST_WIDTH (clist) - clist->clist_window_width)
904 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
905 clist->clist_window_width;
907 GTK_RANGE (clist->hscrollbar)->adjustment->value = y;
909 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
915 gtk_clist_get_cell_type (GtkCList * clist,
919 GtkCListRow *clist_row;
921 g_return_val_if_fail (clist != NULL, -1);
923 if (row < 0 || row >= clist->rows)
925 if (column < 0 || column >= clist->columns)
928 clist_row = (g_list_nth (clist->row_list, row))->data;
930 return clist_row->cell[column].type;
934 gtk_clist_set_text (GtkCList * clist,
939 GtkCListRow *clist_row;
941 g_return_if_fail (clist != NULL);
943 if (row < 0 || row >= clist->rows)
945 if (column < 0 || column >= clist->columns)
948 clist_row = (g_list_nth (clist->row_list, row))->data;
950 /* if text is null, then the cell is empty */
952 cell_set_text (clist, clist_row, column, text);
954 cell_empty (clist, clist_row, column);
956 /* redraw the list if it's not frozen */
957 if (!GTK_CLIST_FROZEN (clist))
959 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
960 draw_row (clist, NULL, row, clist_row);
965 gtk_clist_get_text (GtkCList * clist,
970 GtkCListRow *clist_row;
972 g_return_val_if_fail (clist != NULL, 0);
974 if (row < 0 || row >= clist->rows)
976 if (column < 0 || column >= clist->columns)
979 clist_row = (g_list_nth (clist->row_list, row))->data;
981 if (clist_row->cell[column].type != GTK_CELL_TEXT)
985 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
991 gtk_clist_set_pixmap (GtkCList * clist,
997 GtkCListRow *clist_row;
999 g_return_if_fail (clist != NULL);
1001 if (row < 0 || row >= clist->rows)
1003 if (column < 0 || column >= clist->columns)
1006 clist_row = (g_list_nth (clist->row_list, row))->data;
1008 gdk_pixmap_ref (pixmap);
1010 if (mask) gdk_pixmap_ref (mask);
1012 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1014 /* redraw the list if it's not frozen */
1015 if (!GTK_CLIST_FROZEN (clist))
1017 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1018 draw_row (clist, NULL, row, clist_row);
1023 gtk_clist_get_pixmap (GtkCList * clist,
1026 GdkPixmap ** pixmap,
1029 GtkCListRow *clist_row;
1031 g_return_val_if_fail (clist != NULL, 0);
1033 if (row < 0 || row >= clist->rows)
1035 if (column < 0 || column >= clist->columns)
1038 clist_row = (g_list_nth (clist->row_list, row))->data;
1040 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1045 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1046 /* mask can be NULL */
1047 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1054 gtk_clist_set_pixtext (GtkCList * clist,
1062 GtkCListRow *clist_row;
1064 g_return_if_fail (clist != NULL);
1066 if (row < 0 || row >= clist->rows)
1068 if (column < 0 || column >= clist->columns)
1071 clist_row = (g_list_nth (clist->row_list, row))->data;
1073 gdk_pixmap_ref (pixmap);
1074 if (mask) gdk_pixmap_ref (mask);
1075 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1077 /* redraw the list if it's not frozen */
1078 if (!GTK_CLIST_FROZEN (clist))
1080 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1081 draw_row (clist, NULL, row, clist_row);
1086 gtk_clist_get_pixtext (GtkCList * clist,
1091 GdkPixmap ** pixmap,
1094 GtkCListRow *clist_row;
1096 g_return_val_if_fail (clist != NULL, 0);
1098 if (row < 0 || row >= clist->rows)
1100 if (column < 0 || column >= clist->columns)
1103 clist_row = (g_list_nth (clist->row_list, row))->data;
1105 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1109 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1111 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1113 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1115 /* mask can be NULL */
1116 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1122 gtk_clist_set_foreground (GtkCList * clist,
1126 GtkCListRow *clist_row;
1128 g_return_if_fail (clist != NULL);
1130 if (row < 0 || row >= clist->rows)
1133 clist_row = (g_list_nth (clist->row_list, row))->data;
1137 clist_row->foreground = *color;
1138 clist_row->fg_set = TRUE;
1141 clist_row->fg_set = FALSE;
1143 if (!GTK_CLIST_FROZEN (clist)
1144 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1145 draw_row (clist, NULL, row, clist_row);
1149 gtk_clist_set_background (GtkCList * clist,
1153 GtkCListRow *clist_row;
1155 g_return_if_fail (clist != NULL);
1157 if (row < 0 || row >= clist->rows)
1160 clist_row = (g_list_nth (clist->row_list, row))->data;
1164 clist_row->background = *color;
1165 clist_row->bg_set = TRUE;
1168 clist_row->bg_set = FALSE;
1170 if (!GTK_CLIST_FROZEN (clist)
1171 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1172 draw_row (clist, NULL, row, clist_row);
1176 gtk_clist_set_shift (GtkCList * clist,
1182 GtkCListRow *clist_row;
1184 g_return_if_fail (clist != NULL);
1186 if (row < 0 || row >= clist->rows)
1188 if (column < 0 || column >= clist->columns)
1191 clist_row = (g_list_nth (clist->row_list, row))->data;
1193 clist_row->cell[column].vertical = vertical;
1194 clist_row->cell[column].horizontal = horizontal;
1196 if (!GTK_CLIST_FROZEN (clist)
1197 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1198 draw_row (clist, NULL, row, clist_row);
1202 gtk_clist_append (GtkCList * clist,
1206 GtkCListRow *clist_row;
1208 g_return_val_if_fail (clist != NULL, -1);
1210 clist_row = row_new (clist);
1213 /* set the text in the row's columns */
1215 for (i = 0; i < clist->columns; i++)
1217 cell_set_text (clist, clist_row, i, text[i]);
1219 /* keeps track of the end of the list so the list
1220 * doesn't have to be traversed every time a item is added */
1221 if (!clist->row_list)
1223 clist->row_list = g_list_append (clist->row_list, clist_row);
1224 clist->row_list_end = clist->row_list;
1226 /* check the selection mode to see if we should select
1227 * the first row automaticly */
1228 switch (clist->selection_mode)
1230 case GTK_SELECTION_BROWSE:
1231 gtk_clist_select_row (clist, 0, -1);
1239 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1241 /* redraw the list if it's not frozen */
1242 if (!GTK_CLIST_FROZEN (clist))
1244 adjust_scrollbars (clist);
1246 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1247 draw_rows (clist, NULL);
1250 /* return index of the row */
1251 return clist->rows - 1;
1255 gtk_clist_insert (GtkCList * clist,
1260 GtkCListRow *clist_row;
1262 g_return_if_fail (clist != NULL);
1263 g_return_if_fail (text != NULL);
1265 /* return if out of bounds */
1266 if (row < 0 || row > clist->rows)
1269 if (clist->rows == 0)
1270 gtk_clist_append (clist, text);
1273 /* create the row */
1274 clist_row = row_new (clist);
1276 /* set the text in the row's columns */
1278 for (i = 0; i < clist->columns; i++)
1280 cell_set_text (clist, clist_row, i, text[i]);
1282 /* reset the row end pointer if we're inserting at the
1283 * end of the list */
1284 if (row == clist->rows)
1285 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1287 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1291 /* syncronize the selection list */
1292 sync_selection (clist, row, SYNC_INSERT);
1295 /* redraw the list if it isn't frozen */
1296 if (!GTK_CLIST_FROZEN (clist))
1298 adjust_scrollbars (clist);
1300 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1301 draw_rows (clist, NULL);
1306 gtk_clist_remove (GtkCList * clist,
1309 gint was_visible, was_selected;
1311 GtkCListRow *clist_row;
1313 g_return_if_fail (clist != NULL);
1315 /* return if out of bounds */
1316 if (row < 0 || row > (clist->rows - 1))
1319 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1322 /* get the row we're going to delete */
1323 list = g_list_nth (clist->row_list, row);
1324 clist_row = list->data;
1326 /* if we're removing a selected row, we have to make sure
1327 * it's properly unselected, and then sync up the clist->selected
1328 * list to reflect the deincrimented indexies of rows after the
1330 if (clist_row->state == GTK_STATE_SELECTED)
1334 switch (clist->selection_mode)
1336 case GTK_SELECTION_SINGLE:
1337 case GTK_SELECTION_BROWSE:
1338 case GTK_SELECTION_MULTIPLE:
1339 gtk_clist_unselect_row (clist, row, -1);
1347 /* reset the row end pointer if we're removing at the
1348 * end of the list */
1349 if (row == clist->rows - 1)
1350 clist->row_list_end = list->prev;
1352 clist->row_list = g_list_remove (clist->row_list, clist_row);
1354 sync_selection (clist, row, SYNC_REMOVE);
1356 /* preform any selections required by the selection mode */
1359 switch (clist->selection_mode)
1361 case GTK_SELECTION_BROWSE:
1362 if (row == clist->rows)
1363 gtk_clist_select_row (clist, row - 1, -1);
1365 gtk_clist_select_row (clist, row, -1);
1374 row_delete (clist, clist_row);
1376 /* redraw the row if it isn't frozen */
1377 if (!GTK_CLIST_FROZEN (clist))
1379 adjust_scrollbars (clist);
1382 draw_rows (clist, NULL);
1387 sync_selection (GtkCList * clist,
1393 list = clist->selection;
1396 if ((gint) list->data >= row)
1400 list->data = ((gchar*) list->data) + 1;
1404 list->data = ((gchar*) list->data) - 1;
1416 gtk_clist_clear (GtkCList * clist)
1420 g_return_if_fail (clist != NULL);
1422 /* remove all the rows */
1423 for (list = clist->row_list; list; list = list->next)
1425 GtkCListRow *clist_row;
1427 clist_row = list->data;
1428 row_delete (clist, clist_row);
1430 g_list_free (clist->row_list);
1432 /* free up the selection list */
1433 g_list_free (clist->selection);
1435 clist->row_list = NULL;
1436 clist->row_list_end = NULL;
1437 clist->selection = NULL;
1441 /* zero-out the scrollbars */
1442 if (clist->vscrollbar)
1444 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1445 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1447 if (!GTK_CLIST_FROZEN (clist))
1449 adjust_scrollbars (clist);
1450 draw_rows (clist, NULL);
1456 gtk_clist_set_row_data (GtkCList * clist,
1460 gtk_clist_set_row_data_full (clist, row, data, NULL);
1464 gtk_clist_set_row_data_full (GtkCList * clist,
1467 GtkDestroyNotify destroy)
1469 GtkCListRow *clist_row;
1471 g_return_if_fail (clist != NULL);
1473 if (row < 0 || row > (clist->rows - 1))
1476 clist_row = (g_list_nth (clist->row_list, row))->data;
1477 clist_row->data = data;
1478 clist_row->destroy = destroy;
1480 /* re-send the selected signal if data is changed/added
1481 * so the application can respond to the new data --
1482 * this could be questionable behavior */
1483 if (clist_row->state == GTK_STATE_SELECTED)
1484 gtk_clist_select_row (clist, 0, 0);
1488 gtk_clist_get_row_data (GtkCList * clist,
1491 GtkCListRow *clist_row;
1493 g_return_val_if_fail (clist != NULL, NULL);
1495 if (row < 0 || row > (clist->rows - 1))
1498 clist_row = (g_list_nth (clist->row_list, row))->data;
1499 return clist_row->data;
1503 gtk_clist_find_row_from_data (GtkCList * clist,
1509 g_return_val_if_fail (clist != NULL, -1);
1510 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1512 if (clist->rows < 1)
1513 return -1; /* is this an optimization or just worthless? */
1516 list = clist->row_list;
1519 GtkCListRow *clist_row;
1521 clist_row = list->data;
1522 if (clist_row->data == data)
1535 gtk_clist_select_row (GtkCList * clist,
1539 g_return_if_fail (clist != NULL);
1541 if (row < 0 || row >= clist->rows)
1544 if (column < -1 || column >= clist->columns)
1547 select_row (clist, row, column, NULL);
1551 gtk_clist_unselect_row (GtkCList * clist,
1555 g_return_if_fail (clist != NULL);
1557 if (row < 0 || row >= clist->rows)
1560 if (column < -1 || column >= clist->columns)
1563 unselect_row (clist, row, column, NULL);
1567 gtk_clist_row_is_visible (GtkCList * clist,
1572 g_return_val_if_fail (clist != NULL, 0);
1574 if (row < 0 || row >= clist->rows)
1575 return GTK_VISIBILITY_NONE;
1577 if (clist->row_height == 0)
1578 return GTK_VISIBILITY_NONE;
1580 if (row < ROW_FROM_YPIXEL (clist, 0))
1581 return GTK_VISIBILITY_NONE;
1583 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
1584 return GTK_VISIBILITY_NONE;
1586 top = ROW_TOP_YPIXEL (clist, row);
1589 || ((top + clist->row_height) >= clist->clist_window_height))
1590 return GTK_VISIBILITY_PARTIAL;
1592 return GTK_VISIBILITY_FULL;
1596 gtk_clist_get_vadjustment (GtkCList * clist)
1598 g_return_val_if_fail (clist != NULL, NULL);
1599 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1601 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
1605 gtk_clist_get_hadjustment (GtkCList * clist)
1607 g_return_val_if_fail (clist != NULL, NULL);
1608 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1610 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
1614 gtk_clist_set_policy (GtkCList * clist,
1615 GtkPolicyType vscrollbar_policy,
1616 GtkPolicyType hscrollbar_policy)
1618 g_return_if_fail (clist != NULL);
1619 g_return_if_fail (GTK_IS_CLIST (clist));
1621 if (clist->vscrollbar_policy != vscrollbar_policy)
1623 clist->vscrollbar_policy = vscrollbar_policy;
1625 if (GTK_WIDGET (clist)->parent)
1626 gtk_widget_queue_resize (GTK_WIDGET (clist));
1629 if (clist->hscrollbar_policy != hscrollbar_policy)
1631 clist->hscrollbar_policy = hscrollbar_policy;
1633 if (GTK_WIDGET (clist)->parent)
1634 gtk_widget_queue_resize (GTK_WIDGET (clist));
1641 * gtk_clist_finalize
1644 gtk_clist_destroy (GtkObject * object)
1649 g_return_if_fail (object != NULL);
1650 g_return_if_fail (GTK_IS_CLIST (object));
1652 clist = GTK_CLIST (object);
1654 /* freeze the list */
1655 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1657 /* get rid of all the rows */
1658 gtk_clist_clear (clist);
1660 /* Since we don't have a _remove method, unparent the children
1661 * instead of destroying them so the focus will be unset properly.
1662 * (For other containers, the _remove method takes care of the
1663 * unparent) The destroy will happen when the refcount drops
1667 /* destroy the scrollbars */
1668 if (clist->vscrollbar)
1670 gtk_widget_unparent (clist->vscrollbar);
1671 clist->vscrollbar = NULL;
1673 if (clist->hscrollbar)
1675 gtk_widget_unparent (clist->hscrollbar);
1676 clist->hscrollbar = NULL;
1679 /* destroy the column buttons */
1680 for (i = 0; i < clist->columns; i++)
1681 if (clist->column[i].button)
1683 gtk_widget_unparent (clist->column[i].button);
1684 clist->column[i].button = NULL;
1687 if (GTK_OBJECT_CLASS (parent_class)->destroy)
1688 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1692 gtk_clist_finalize (GtkObject * object)
1696 g_return_if_fail (object != NULL);
1697 g_return_if_fail (GTK_IS_CLIST (object));
1699 clist = GTK_CLIST (object);
1701 columns_delete (clist);
1703 g_mem_chunk_destroy (clist->cell_mem_chunk);
1704 g_mem_chunk_destroy (clist->row_mem_chunk);
1706 if (GTK_OBJECT_CLASS (parent_class)->finalize)
1707 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
1713 * gtk_clist_unrealize
1718 * gtk_clist_button_press
1719 * gtk_clist_button_release
1720 * gtk_clist_button_motion
1721 * gtk_clist_size_request
1722 * gtk_clist_size_allocate
1725 gtk_clist_realize (GtkWidget * widget)
1729 GdkWindowAttr attributes;
1730 gint attributes_mask;
1733 g_return_if_fail (widget != NULL);
1734 g_return_if_fail (GTK_IS_CLIST (widget));
1736 clist = GTK_CLIST (widget);
1738 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1740 attributes.window_type = GDK_WINDOW_CHILD;
1741 attributes.x = widget->allocation.x;
1742 attributes.y = widget->allocation.y;
1743 attributes.width = widget->allocation.width;
1744 attributes.height = widget->allocation.height;
1745 attributes.wclass = GDK_INPUT_OUTPUT;
1746 attributes.visual = gtk_widget_get_visual (widget);
1747 attributes.colormap = gtk_widget_get_colormap (widget);
1748 attributes.event_mask = gtk_widget_get_events (widget);
1749 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1750 GDK_BUTTON_PRESS_MASK |
1751 GDK_BUTTON_RELEASE_MASK |
1752 GDK_KEY_PRESS_MASK);
1753 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1757 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1758 gdk_window_set_user_data (widget->window, clist);
1760 widget->style = gtk_style_attach (widget->style, widget->window);
1762 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1764 /* column-title window */
1765 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1766 gdk_window_set_user_data (clist->title_window, clist);
1768 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
1769 gdk_window_show (clist->title_window);
1771 /* set things up so column buttons are drawn in title window */
1772 for (i = 0; i < clist->columns; i++)
1773 if (clist->column[i].button)
1774 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
1777 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1778 gdk_window_set_user_data (clist->clist_window, clist);
1780 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
1781 gdk_window_show (clist->clist_window);
1782 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
1783 &clist->clist_window_height);
1785 /* create resize windows */
1786 attributes.wclass = GDK_INPUT_ONLY;
1787 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
1788 GDK_BUTTON_RELEASE_MASK |
1789 GDK_POINTER_MOTION_MASK |
1790 GDK_POINTER_MOTION_HINT_MASK);
1791 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1792 attributes_mask = GDK_WA_CURSOR;
1794 for (i = 0; i < clist->columns; i++)
1796 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
1797 gdk_window_set_user_data (clist->column[i].window, clist);
1798 gdk_window_show (clist->column[i].window);
1802 clist->fg_gc = gdk_gc_new (widget->window);
1803 clist->bg_gc = gdk_gc_new (widget->window);
1805 /* We'll use this gc to do scrolling as well */
1806 gdk_gc_set_exposures (clist->fg_gc, TRUE);
1808 values.foreground = widget->style->white;
1809 values.function = GDK_XOR;
1810 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1811 clist->xor_gc = gdk_gc_new_with_values (widget->window,
1817 add_style_data (clist);
1821 gtk_clist_unrealize (GtkWidget * widget)
1826 g_return_if_fail (widget != NULL);
1827 g_return_if_fail (GTK_IS_CLIST (widget));
1829 clist = GTK_CLIST (widget);
1831 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1833 gdk_cursor_destroy (clist->cursor_drag);
1834 gdk_gc_destroy (clist->xor_gc);
1835 gdk_gc_destroy (clist->fg_gc);
1836 gdk_gc_destroy (clist->bg_gc);
1838 for (i = 0; i < clist->columns; i++)
1839 if (clist->column[i].window)
1841 gdk_window_set_user_data (clist->column[i].window, NULL);
1842 gdk_window_destroy (clist->column[i].window);
1843 clist->column[i].window = NULL;
1846 gdk_window_set_user_data (clist->clist_window, NULL);
1847 gdk_window_destroy (clist->clist_window);
1848 clist->clist_window = NULL;
1850 gdk_window_set_user_data (clist->title_window, NULL);
1851 gdk_window_destroy (clist->title_window);
1852 clist->title_window = NULL;
1854 clist->cursor_drag = NULL;
1855 clist->xor_gc = NULL;
1856 clist->fg_gc = NULL;
1857 clist->bg_gc = NULL;
1859 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1860 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1864 gtk_clist_map (GtkWidget * widget)
1869 g_return_if_fail (widget != NULL);
1870 g_return_if_fail (GTK_IS_CLIST (widget));
1872 clist = GTK_CLIST (widget);
1874 if (!GTK_WIDGET_MAPPED (widget))
1876 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1878 gdk_window_show (widget->window);
1879 gdk_window_show (clist->title_window);
1880 gdk_window_show (clist->clist_window);
1882 /* map column buttons */
1883 for (i = 0; i < clist->columns; i++)
1884 if (clist->column[i].button &&
1885 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
1886 !GTK_WIDGET_MAPPED (clist->column[i].button))
1887 gtk_widget_map (clist->column[i].button);
1889 /* map resize windows AFTER column buttons (above) */
1890 for (i = 0; i < clist->columns; i++)
1891 if (clist->column[i].window && clist->column[i].button)
1892 gdk_window_show (clist->column[i].window);
1894 /* map vscrollbars */
1895 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
1896 !GTK_WIDGET_MAPPED (clist->vscrollbar))
1897 gtk_widget_map (clist->vscrollbar);
1899 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
1900 !GTK_WIDGET_MAPPED (clist->hscrollbar))
1901 gtk_widget_map (clist->hscrollbar);
1903 /* unfreeze the list */
1904 GTK_CLIST_UNSET_FLAGS (clist, CLIST_FROZEN);
1909 gtk_clist_unmap (GtkWidget * widget)
1914 g_return_if_fail (widget != NULL);
1915 g_return_if_fail (GTK_IS_CLIST (widget));
1917 clist = GTK_CLIST (widget);
1919 if (GTK_WIDGET_MAPPED (widget))
1921 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1923 for (i = 0; i < clist->columns; i++)
1924 if (clist->column[i].window)
1925 gdk_window_hide (clist->column[i].window);
1927 gdk_window_hide (clist->clist_window);
1928 gdk_window_hide (clist->title_window);
1929 gdk_window_hide (widget->window);
1931 /* unmap scrollbars */
1932 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
1933 gtk_widget_unmap (clist->vscrollbar);
1935 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
1936 gtk_widget_unmap (clist->hscrollbar);
1938 /* unmap column buttons */
1939 for (i = 0; i < clist->columns; i++)
1940 if (clist->column[i].button &&
1941 GTK_WIDGET_MAPPED (clist->column[i].button))
1942 gtk_widget_unmap (clist->column[i].button);
1944 /* freeze the list */
1945 GTK_CLIST_SET_FLAGS (clist, CLIST_FROZEN);
1950 gtk_clist_draw (GtkWidget * widget,
1951 GdkRectangle * area)
1955 g_return_if_fail (widget != NULL);
1956 g_return_if_fail (GTK_IS_CLIST (widget));
1957 g_return_if_fail (area != NULL);
1959 if (GTK_WIDGET_DRAWABLE (widget))
1961 clist = GTK_CLIST (widget);
1963 gdk_window_clear_area (widget->window,
1965 area->width, area->height);
1967 /* draw list shadow/border */
1968 gtk_draw_shadow (widget->style, widget->window,
1969 GTK_STATE_NORMAL, clist->shadow_type,
1971 clist->clist_window_width + (2 * widget->style->klass->xthickness),
1972 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
1973 clist->column_title_area.height);
1975 gdk_window_clear_area (clist->clist_window,
1978 draw_rows (clist, NULL);
1983 gtk_clist_expose (GtkWidget * widget,
1984 GdkEventExpose * event)
1988 g_return_val_if_fail (widget != NULL, FALSE);
1989 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
1990 g_return_val_if_fail (event != NULL, FALSE);
1992 if (GTK_WIDGET_DRAWABLE (widget))
1994 clist = GTK_CLIST (widget);
1997 if (event->window == widget->window)
1998 gtk_draw_shadow (widget->style, widget->window,
1999 GTK_STATE_NORMAL, clist->shadow_type,
2001 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2002 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2003 clist->column_title_area.height);
2005 /* exposure events on the list */
2006 if (event->window == clist->clist_window)
2007 draw_rows (clist, &event->area);
2014 gtk_clist_button_press (GtkWidget * widget,
2015 GdkEventButton * event)
2019 gint x, y, row, column;
2021 g_return_val_if_fail (widget != NULL, FALSE);
2022 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2023 g_return_val_if_fail (event != NULL, FALSE);
2025 clist = GTK_CLIST (widget);
2027 /* selections on the list */
2028 if (event->window == clist->clist_window)
2033 if (get_selection_info (clist, x, y, &row, &column))
2034 toggle_row (clist, row, column, event);
2039 /* press on resize windows */
2040 for (i = 0; i < clist->columns; i++)
2041 if (clist->column[i].window && event->window == clist->column[i].window)
2043 GTK_CLIST_SET_FLAGS (clist, CLIST_IN_DRAG);
2044 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2046 gdk_pointer_grab (clist->column[i].window, FALSE,
2047 GDK_POINTER_MOTION_HINT_MASK |
2048 GDK_BUTTON1_MOTION_MASK |
2049 GDK_BUTTON_RELEASE_MASK,
2050 NULL, NULL, event->time);
2052 draw_xor_line (clist);
2060 gtk_clist_button_release (GtkWidget * widget,
2061 GdkEventButton * event)
2063 gint i, x, width, visible;
2066 g_return_val_if_fail (widget != NULL, FALSE);
2067 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2068 g_return_val_if_fail (event != NULL, FALSE);
2070 clist = GTK_CLIST (widget);
2072 /* release on resize windows */
2073 if (GTK_CLIST_IN_DRAG (clist))
2074 for (i = 0; i < clist->columns; i++)
2075 if (clist->column[i].window && event->window == clist->column[i].window)
2077 GTK_CLIST_UNSET_FLAGS (clist, CLIST_IN_DRAG);
2078 gtk_widget_get_pointer (widget, &x, NULL);
2079 width = new_column_width (clist, i, &x, &visible);
2080 gdk_pointer_ungrab (event->time);
2083 draw_xor_line (clist);
2085 resize_column (clist, i, width);
2093 gtk_clist_motion (GtkWidget * widget,
2094 GdkEventMotion * event)
2099 g_return_val_if_fail (widget != NULL, FALSE);
2100 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2102 clist = GTK_CLIST (widget);
2104 if (GTK_CLIST_IN_DRAG (clist))
2105 for (i = 0; i < clist->columns; i++)
2106 if (clist->column[i].window && event->window == clist->column[i].window)
2108 if (event->is_hint || event->window != widget->window)
2109 gtk_widget_get_pointer (widget, &x, NULL);
2113 new_column_width (clist, i, &x, &visible);
2114 /* Welcome to my hack! I'm going to use a value of x_drage = -99999 to
2115 * indicate the the xor line is already no visible */
2116 if (!visible && clist->x_drag != -99999)
2118 draw_xor_line (clist);
2119 clist->x_drag = -99999;
2122 if (x != clist->x_drag && visible)
2124 if (clist->x_drag != -99999)
2125 draw_xor_line (clist);
2128 draw_xor_line (clist);
2136 gtk_clist_size_request (GtkWidget * widget,
2137 GtkRequisition * requisition)
2142 g_return_if_fail (widget != NULL);
2143 g_return_if_fail (GTK_IS_CLIST (widget));
2144 g_return_if_fail (requisition != NULL);
2146 clist = GTK_CLIST (widget);
2148 requisition->width = 0;
2149 requisition->height = 0;
2151 /* compute the size of the column title (title) area */
2152 clist->column_title_area.height = 0;
2153 if (GTK_CLIST_SHOW_TITLES (clist))
2154 for (i = 0; i < clist->columns; i++)
2155 if (clist->column[i].button)
2157 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
2158 clist->column_title_area.height = MAX (clist->column_title_area.height,
2159 clist->column[i].button->requisition.height);
2161 requisition->height += clist->column_title_area.height;
2163 /* add the vscrollbar space */
2164 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2165 GTK_WIDGET_VISIBLE (clist->vscrollbar))
2167 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
2169 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
2170 requisition->height = MAX (requisition->height,
2171 clist->vscrollbar->requisition.height);
2174 /* add the hscrollbar space */
2175 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2176 GTK_WIDGET_VISIBLE (clist->hscrollbar))
2178 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
2180 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
2181 requisition->width = MAX (clist->hscrollbar->requisition.width,
2182 requisition->width -
2183 clist->vscrollbar->requisition.width);
2187 requisition->width += widget->style->klass->xthickness * 2 +
2188 GTK_CONTAINER (widget)->border_width * 2;
2189 requisition->height += widget->style->klass->ythickness * 2 +
2190 GTK_CONTAINER (widget)->border_width * 2;
2194 gtk_clist_size_allocate (GtkWidget * widget,
2195 GtkAllocation * allocation)
2198 GtkAllocation clist_allocation;
2199 GtkAllocation child_allocation;
2200 gint i, vscrollbar_vis, hscrollbar_vis;
2202 g_return_if_fail (widget != NULL);
2203 g_return_if_fail (GTK_IS_CLIST (widget));
2204 g_return_if_fail (allocation != NULL);
2206 clist = GTK_CLIST (widget);
2207 widget->allocation = *allocation;
2209 if (GTK_WIDGET_REALIZED (widget))
2211 gdk_window_move_resize (widget->window,
2212 allocation->x + GTK_CONTAINER (widget)->border_width,
2213 allocation->y + GTK_CONTAINER (widget)->border_width,
2214 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
2215 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
2217 /* use internal allocation structure for all the math
2218 * because it's easier than always subtracting the container
2220 clist->internal_allocation.x = 0;
2221 clist->internal_allocation.y = 0;
2222 clist->internal_allocation.width = allocation->width -
2223 GTK_CONTAINER (widget)->border_width * 2;
2224 clist->internal_allocation.height = allocation->height -
2225 GTK_CONTAINER (widget)->border_width * 2;
2227 /* allocate clist window assuming no scrollbars */
2228 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2229 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2230 clist->column_title_area.height;
2231 clist_allocation.width = clist->internal_allocation.width -
2232 (2 * widget->style->klass->xthickness);
2233 clist_allocation.height = clist->internal_allocation.height -
2234 (2 * widget->style->klass->xthickness) -
2235 clist->column_title_area.height;
2238 * here's where we decide to show/not show the scrollbars
2243 for (i = 0; i <= 1; i++)
2245 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
2246 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2252 if (!vscrollbar_vis)
2255 clist_allocation.width -= clist->vscrollbar->requisition.width +
2256 SCROLLBAR_SPACING (clist);
2260 if (LIST_WIDTH (clist) <= clist_allocation.width &&
2261 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2267 if (!hscrollbar_vis)
2270 clist_allocation.height -= clist->hscrollbar->requisition.height +
2271 SCROLLBAR_SPACING (clist);
2276 clist->clist_window_width = clist_allocation.width;
2277 clist->clist_window_height = clist_allocation.height;
2279 gdk_window_move_resize (clist->clist_window,
2282 clist_allocation.width,
2283 clist_allocation.height);
2285 /* position the window which holds the column title buttons */
2286 clist->column_title_area.x = widget->style->klass->xthickness;
2287 clist->column_title_area.y = widget->style->klass->ythickness;
2288 clist->column_title_area.width = clist_allocation.width;
2290 gdk_window_move_resize (clist->title_window,
2291 clist->column_title_area.x,
2292 clist->column_title_area.y,
2293 clist->column_title_area.width,
2294 clist->column_title_area.height);
2296 /* column button allocation */
2297 size_allocate_columns (clist);
2298 size_allocate_title_buttons (clist);
2299 adjust_scrollbars (clist);
2301 /* allocate the vscrollbar */
2304 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2305 gtk_widget_show (clist->vscrollbar);
2307 child_allocation.x = clist->internal_allocation.x +
2308 clist->internal_allocation.width -
2309 clist->vscrollbar->requisition.width;
2310 child_allocation.y = clist->internal_allocation.y;
2311 child_allocation.width = clist->vscrollbar->requisition.width;
2312 child_allocation.height = clist->internal_allocation.height -
2313 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0);
2315 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
2319 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2320 gtk_widget_hide (clist->vscrollbar);
2325 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2326 gtk_widget_show (clist->hscrollbar);
2328 child_allocation.x = clist->internal_allocation.x;
2329 child_allocation.y = clist->internal_allocation.y +
2330 clist->internal_allocation.height -
2331 clist->hscrollbar->requisition.height;
2332 child_allocation.width = clist->internal_allocation.width -
2333 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0);
2334 child_allocation.height = clist->hscrollbar->requisition.height;
2336 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
2340 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2341 gtk_widget_hide (clist->hscrollbar);
2345 /* set the vscrollbar adjustments */
2346 adjust_scrollbars (clist);
2350 gtk_clist_row_from_ypixel (GtkCList *clist, gint y)
2352 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
2353 g_return_val_if_fail (y >= 0, 0);
2355 return ROW_FROM_YPIXEL (clist, y);
2363 gtk_clist_foreach (GtkContainer * container,
2364 GtkCallback callback,
2365 gpointer callback_data)
2370 g_return_if_fail (container != NULL);
2371 g_return_if_fail (GTK_IS_CLIST (container));
2372 g_return_if_fail (callback != NULL);
2374 clist = GTK_CLIST (container);
2376 /* callback for the column buttons */
2377 for (i = 0; i < clist->columns; i++)
2378 if (clist->column[i].button)
2379 (*callback) (clist->column[i].button, callback_data);
2381 /* callbacks for the scrollbars */
2382 if (clist->vscrollbar)
2383 (*callback) (clist->vscrollbar, callback_data);
2384 if (clist->hscrollbar)
2385 (*callback) (clist->hscrollbar, callback_data);
2394 draw_row (GtkCList * clist,
2395 GdkRectangle * area,
2397 GtkCListRow * clist_row)
2400 GdkGC *fg_gc, *bg_gc;
2401 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
2403 gint i, offset = 0, width, height, pixmap_width = 0;
2404 gint xsrc, ysrc, xdest, ydest;
2406 g_return_if_fail (clist != NULL);
2408 /* bail now if we arn't drawable yet */
2409 if (!GTK_WIDGET_DRAWABLE (clist))
2412 if (row < 0 || row >= clist->rows)
2415 widget = GTK_WIDGET (clist);
2417 /* if the function is passed the pointer to the row instead of null,
2418 * it avoids this expensive lookup */
2420 clist_row = (g_list_nth (clist->row_list, row))->data;
2422 /* rectangle of the entire row */
2423 row_rectangle.x = 0;
2424 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
2425 row_rectangle.width = clist->clist_window_width;
2426 row_rectangle.height = clist->row_height;
2428 /* rectangle of the cell spacing above the row */
2429 cell_rectangle.x = 0;
2430 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
2431 cell_rectangle.width = row_rectangle.width;
2432 cell_rectangle.height = CELL_SPACING;
2434 /* rectangle used to clip drawing operations, it's y and height
2435 * positions only need to be set once, so we set them once here.
2436 * the x and width are set withing the drawing loop below once per
2438 clip_rectangle.y = row_rectangle.y;
2439 clip_rectangle.height = row_rectangle.height;
2441 /* select GC for background rectangle */
2442 if (clist_row->state == GTK_STATE_SELECTED)
2444 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
2445 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
2449 if (clist_row->fg_set)
2451 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
2452 fg_gc = clist->fg_gc;
2455 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
2457 if (clist_row->bg_set)
2459 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
2460 bg_gc = clist->bg_gc;
2463 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
2466 /* draw the cell borders and background */
2469 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2470 gdk_draw_rectangle (clist->clist_window,
2471 widget->style->white_gc,
2473 intersect_rectangle.x,
2474 intersect_rectangle.y,
2475 intersect_rectangle.width,
2476 intersect_rectangle.height);
2478 /* the last row has to clear it's bottom cell spacing too */
2479 if (clist_row == clist->row_list_end->data)
2481 cell_rectangle.y += clist->row_height + CELL_SPACING;
2483 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2484 gdk_draw_rectangle (clist->clist_window,
2485 widget->style->white_gc,
2487 intersect_rectangle.x,
2488 intersect_rectangle.y,
2489 intersect_rectangle.width,
2490 intersect_rectangle.height);
2493 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
2496 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
2497 gdk_draw_rectangle (clist->clist_window,
2500 intersect_rectangle.x,
2501 intersect_rectangle.y,
2502 intersect_rectangle.width,
2503 intersect_rectangle.height);
2505 gdk_window_clear_area (clist->clist_window,
2506 intersect_rectangle.x,
2507 intersect_rectangle.y,
2508 intersect_rectangle.width,
2509 intersect_rectangle.height);
2513 gdk_draw_rectangle (clist->clist_window,
2514 widget->style->white_gc,
2518 cell_rectangle.width,
2519 cell_rectangle.height);
2521 /* the last row has to clear it's bottom cell spacing too */
2522 if (clist_row == clist->row_list_end->data)
2524 cell_rectangle.y += clist->row_height + CELL_SPACING;
2526 gdk_draw_rectangle (clist->clist_window,
2527 widget->style->white_gc,
2531 cell_rectangle.width,
2532 cell_rectangle.height);
2535 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
2536 gdk_draw_rectangle (clist->clist_window,
2541 row_rectangle.width,
2542 row_rectangle.height);
2544 gdk_window_clear_area (clist->clist_window,
2547 row_rectangle.width,
2548 row_rectangle.height);
2551 /* iterate and draw all the columns (row cells) and draw their contents */
2552 for (i = 0; i < clist->columns; i++)
2554 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
2555 clip_rectangle.width = clist->column[i].area.width;
2557 /* calculate clipping region clipping region */
2560 rect = &clip_rectangle;
2564 if (!gdk_rectangle_intersect (area, &clip_rectangle, &intersect_rectangle))
2566 rect = &intersect_rectangle;
2569 /* calculate real width for column justification */
2570 switch (clist_row->cell[i].type)
2572 case GTK_CELL_EMPTY:
2577 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2578 GTK_CELL_TEXT (clist_row->cell[i])->text);
2581 case GTK_CELL_PIXMAP:
2582 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
2583 pixmap_width = width;
2586 case GTK_CELL_PIXTEXT:
2587 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
2588 pixmap_width = width;
2589 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2590 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2591 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2594 case GTK_CELL_WIDGET:
2604 switch (clist->column[i].justification)
2606 case GTK_JUSTIFY_LEFT:
2607 offset = clip_rectangle.x;
2610 case GTK_JUSTIFY_RIGHT:
2611 offset = (clip_rectangle.x + clip_rectangle.width) - width;
2614 case GTK_JUSTIFY_CENTER:
2615 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2618 case GTK_JUSTIFY_FILL:
2619 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2627 /* Draw Text or Pixmap */
2628 switch (clist_row->cell[i].type)
2630 case GTK_CELL_EMPTY:
2635 gdk_gc_set_clip_rectangle (fg_gc, rect);
2637 gdk_draw_string (clist->clist_window,
2638 widget->style->font,
2640 offset + clist_row->cell[i].horizontal,
2641 row_rectangle.y + clist->row_center_offset +
2642 clist_row->cell[i].vertical,
2643 GTK_CELL_TEXT (clist_row->cell[i])->text);
2645 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2648 case GTK_CELL_PIXMAP:
2651 xdest = offset + clist_row->cell[i].horizontal;
2652 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2653 clist_row->cell[i].vertical;
2655 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2657 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
2658 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2660 gdk_draw_pixmap (clist->clist_window,
2662 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2666 pixmap_width, height);
2668 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2670 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2671 gdk_gc_set_clip_mask (fg_gc, NULL);
2675 case GTK_CELL_PIXTEXT:
2676 /* draw the pixmap */
2679 xdest = offset + clist_row->cell[i].horizontal;
2680 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2681 clist_row->cell[i].vertical;
2683 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2685 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
2686 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2689 gdk_draw_pixmap (clist->clist_window,
2691 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2695 pixmap_width, height);
2697 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2699 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2701 /* draw the string */
2702 gdk_gc_set_clip_rectangle (fg_gc, rect);
2704 gdk_draw_string (clist->clist_window,
2705 widget->style->font,
2707 offset + clist_row->cell[i].horizontal,
2708 row_rectangle.y + clist->row_center_offset +
2709 clist_row->cell[i].vertical,
2710 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2712 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2716 case GTK_CELL_WIDGET:
2729 draw_rows (GtkCList * clist,
2730 GdkRectangle * area)
2733 GtkCListRow *clist_row;
2734 int i, first_row, last_row;
2736 g_return_if_fail (clist != NULL);
2737 g_return_if_fail (GTK_IS_CLIST (clist));
2739 if (clist->row_height == 0 ||
2740 !GTK_WIDGET_DRAWABLE (clist))
2745 first_row = ROW_FROM_YPIXEL (clist, area->y);
2746 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
2750 first_row = ROW_FROM_YPIXEL (clist, 0);
2751 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
2754 /* this is a small special case which exposes the bottom cell line
2755 * on the last row -- it might go away if I change the wall the cell spacings
2757 if (clist->rows == first_row)
2760 list = g_list_nth (clist->row_list, first_row);
2764 clist_row = list->data;
2770 draw_row (clist, area, i, clist_row);
2775 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
2780 * size_allocate_title_buttons
2781 * size_allocate_columns
2784 size_allocate_title_buttons (GtkCList * clist)
2786 gint i, last_button = 0;
2787 GtkAllocation button_allocation;
2789 if (!GTK_WIDGET_REALIZED (clist))
2792 button_allocation.x = clist->hoffset;
2793 button_allocation.y = 0;
2794 button_allocation.width = 0;
2795 button_allocation.height = clist->column_title_area.height;
2797 for (i = 0; i < clist->columns; i++)
2799 button_allocation.width += clist->column[i].area.width;
2801 if (i == clist->columns - 1)
2802 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
2804 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
2806 if (i == (clist->columns - 1) || clist->column[i + 1].button)
2808 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
2809 button_allocation.x += button_allocation.width;
2810 button_allocation.width = 0;
2812 gdk_window_show (clist->column[last_button].window);
2813 gdk_window_move_resize (clist->column[last_button].window,
2814 button_allocation.x - (DRAG_WIDTH / 2),
2815 0, DRAG_WIDTH, clist->column_title_area.height);
2817 last_button = i + 1;
2821 gdk_window_hide (clist->column[i].window);
2827 size_allocate_columns (GtkCList * clist)
2829 gint i, xoffset = 0;
2831 if (!GTK_WIDGET_REALIZED (clist))
2834 for (i = 0; i < clist->columns; i++)
2836 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
2838 if (i == clist->columns - 1)
2842 if (clist->column[i].width_set)
2843 width = clist->column[i].width;
2845 width = gdk_string_width (GTK_WIDGET (clist)->style->font, clist->column[i].title);
2846 clist->column[i].area.width = MAX (width,
2847 clist->clist_window_width -
2848 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
2853 clist->column[i].area.width = clist->column[i].width;
2856 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
2865 * get_selection_info
2868 toggle_row (GtkCList * clist,
2871 GdkEventButton * event)
2875 GtkCListRow *clist_row, *selected_row;
2878 list = clist->row_list;
2879 selected_row = NULL;
2881 switch (clist->selection_mode)
2883 case GTK_SELECTION_SINGLE:
2886 clist_row = list->data;
2890 selected_row = clist_row;
2891 else if (clist_row->state == GTK_STATE_SELECTED)
2892 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2898 if (selected_row && selected_row->state == GTK_STATE_SELECTED)
2899 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2900 row, column, event);
2902 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2903 row, column, event);
2907 case GTK_SELECTION_BROWSE:
2910 clist_row = list->data;
2913 if (i != row && clist_row->state == GTK_STATE_SELECTED)
2914 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2919 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2920 row, column, event);
2924 case GTK_SELECTION_MULTIPLE:
2925 clist_row = (g_list_nth (clist->row_list, row))->data;
2927 if (clist_row->state == GTK_STATE_SELECTED)
2928 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2929 row, column, event);
2931 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2932 row, column, event);
2936 case GTK_SELECTION_EXTENDED:
2945 select_row (GtkCList * clist,
2948 GdkEventButton * event)
2952 GtkCListRow *clist_row;
2954 switch (clist->selection_mode)
2956 case GTK_SELECTION_SINGLE:
2957 case GTK_SELECTION_BROWSE:
2959 list = clist->row_list;
2962 clist_row = list->data;
2965 if (row != i && clist_row->state == GTK_STATE_SELECTED)
2966 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
2972 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2973 row, column, event);
2976 case GTK_SELECTION_MULTIPLE:
2977 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
2978 row, column, event);
2982 case GTK_SELECTION_EXTENDED:
2991 unselect_row (GtkCList * clist,
2994 GdkEventButton * event)
2996 switch (clist->selection_mode)
2998 case GTK_SELECTION_SINGLE:
2999 case GTK_SELECTION_BROWSE:
3000 case GTK_SELECTION_MULTIPLE:
3001 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3002 row, column, event);
3005 case GTK_SELECTION_EXTENDED:
3014 real_select_row (GtkCList * clist,
3017 GdkEventButton * event)
3019 GtkCListRow *clist_row;
3021 g_return_if_fail (clist != NULL);
3023 if (row < 0 || row > (clist->rows - 1))
3026 clist_row = (g_list_nth (clist->row_list, row))->data;
3028 if (clist_row->state == GTK_STATE_NORMAL)
3030 clist_row->state = GTK_STATE_SELECTED;
3031 clist->selection = g_list_append (clist->selection, (gpointer) row);
3033 if (!GTK_CLIST_FROZEN (clist)
3034 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3035 draw_row (clist, NULL, row, clist_row);
3040 real_unselect_row (GtkCList * clist,
3043 GdkEventButton * event)
3045 GtkCListRow *clist_row;
3047 g_return_if_fail (clist != NULL);
3049 if (row < 0 || row > (clist->rows - 1))
3052 clist_row = (g_list_nth (clist->row_list, row))->data;
3054 if (clist_row->state == GTK_STATE_SELECTED)
3056 clist_row->state = GTK_STATE_NORMAL;
3057 clist->selection = g_list_remove (clist->selection, (gpointer) row);
3059 if (!GTK_CLIST_FROZEN (clist)
3060 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3061 draw_row (clist, NULL, row, clist_row);
3066 get_selection_info (GtkCList * clist,
3074 g_return_val_if_fail (clist != NULL, 0);
3076 /* bounds checking, return false if the user clicked
3077 * on a blank area */
3078 trow = ROW_FROM_YPIXEL (clist, y);
3079 if (trow >= clist->rows)
3085 tcol = COLUMN_FROM_XPIXEL (clist, x);
3086 if (tcol >= clist->columns)
3096 gtk_clist_get_selection_info (GtkCList *clist,
3102 g_return_val_if_fail (clist != NULL, 0);
3103 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3104 return get_selection_info (clist, x, y, row, column);
3114 draw_xor_line (GtkCList * clist)
3118 g_return_if_fail (clist != NULL);
3120 widget = GTK_WIDGET (clist);
3122 gdk_draw_line (widget->window, clist->xor_gc,
3124 widget->style->klass->ythickness,
3126 clist->column_title_area.height + clist->clist_window_height + 1);
3129 /* this function returns the new width of the column being resized given
3130 * the column and x position of the cursor; the x cursor position is passed
3131 * in as a pointer and automagicly corrected if it's beyond min/max limits */
3133 new_column_width (GtkCList * clist,
3142 /* first translate the x position from widget->window
3143 * to clist->clist_window */
3144 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3146 /* rx is x from the list beginning */
3147 rx = cx - clist->hoffset;
3149 /* you can't shrink a column to less than its minimum width */
3150 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
3152 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
3153 GTK_WIDGET (clist)->style->klass->xthickness;
3154 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3155 rx = cx - clist->hoffset;
3158 if (cx > clist->clist_window_width)
3163 /* calculate new column width making sure it doesn't end up
3164 * less than the minimum width */
3165 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
3166 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
3167 if (width < COLUMN_MIN_WIDTH)
3168 width = COLUMN_MIN_WIDTH;
3173 /* this will do more later */
3175 resize_column (GtkCList * clist,
3179 gtk_clist_set_column_width (clist, column, width);
3184 column_button_create (GtkCList * clist,
3189 button = clist->column[column].button = gtk_button_new ();
3190 gtk_widget_set_parent (button, GTK_WIDGET (clist));
3191 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
3192 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
3194 gtk_signal_connect (GTK_OBJECT (button),
3196 (GtkSignalFunc) column_button_clicked,
3199 gtk_widget_show (button);
3203 column_button_clicked (GtkWidget * widget,
3209 g_return_if_fail (widget != NULL);
3210 g_return_if_fail (GTK_IS_CLIST (data));
3212 clist = GTK_CLIST (data);
3214 /* find the column who's button was pressed */
3215 for (i = 0; i < clist->columns; i++)
3216 if (clist->column[i].button == widget)
3219 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
3228 * vadjustment_changed
3229 * hadjustment_changed
3230 * vadjustment_value_changed
3231 * hadjustment_value_changed
3234 create_scrollbars (GtkCList * clist)
3236 GtkAdjustment *adjustment;
3238 clist->vscrollbar = gtk_vscrollbar_new (NULL);
3239 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
3241 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3242 (GtkSignalFunc) vadjustment_changed,
3245 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3246 (GtkSignalFunc) vadjustment_value_changed,
3249 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
3250 gtk_widget_show (clist->vscrollbar);
3252 clist->hscrollbar = gtk_hscrollbar_new (NULL);
3253 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
3255 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3256 (GtkSignalFunc) hadjustment_changed,
3259 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3260 (GtkSignalFunc) hadjustment_value_changed,
3263 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
3264 gtk_widget_show (clist->hscrollbar);
3268 adjust_scrollbars (GtkCList * clist)
3270 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
3271 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
3272 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
3273 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
3274 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
3276 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
3278 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
3279 clist->clist_window_height;
3280 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
3284 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
3285 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
3286 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
3287 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
3288 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
3290 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
3292 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
3293 clist->clist_window_width;
3294 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
3298 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
3299 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3301 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3303 gtk_widget_hide (clist->vscrollbar);
3304 gtk_widget_queue_resize (GTK_WIDGET (clist));
3309 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3311 gtk_widget_show (clist->vscrollbar);
3312 gtk_widget_queue_resize (GTK_WIDGET (clist));
3316 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
3317 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3319 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3321 gtk_widget_hide (clist->hscrollbar);
3322 gtk_widget_queue_resize (GTK_WIDGET (clist));
3327 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3329 gtk_widget_show (clist->hscrollbar);
3330 gtk_widget_queue_resize (GTK_WIDGET (clist));
3334 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
3335 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
3339 vadjustment_changed (GtkAdjustment * adjustment,
3344 g_return_if_fail (adjustment != NULL);
3345 g_return_if_fail (data != NULL);
3347 clist = GTK_CLIST (data);
3351 hadjustment_changed (GtkAdjustment * adjustment,
3356 g_return_if_fail (adjustment != NULL);
3357 g_return_if_fail (data != NULL);
3359 clist = GTK_CLIST (data);
3363 check_exposures (GtkCList *clist)
3367 if (!GTK_WIDGET_REALIZED (clist))
3370 /* Make sure graphics expose events are processed before scrolling
3372 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
3374 gtk_widget_event (GTK_WIDGET (clist), event);
3375 if (event->expose.count == 0)
3377 gdk_event_free (event);
3380 gdk_event_free (event);
3385 vadjustment_value_changed (GtkAdjustment * adjustment,
3392 g_return_if_fail (adjustment != NULL);
3393 g_return_if_fail (data != NULL);
3394 g_return_if_fail (GTK_IS_CLIST (data));
3396 clist = GTK_CLIST (data);
3398 if (!GTK_WIDGET_DRAWABLE (clist))
3401 value = adjustment->value;
3403 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
3405 if (value > -clist->voffset)
3408 diff = value + clist->voffset;
3410 /* we have to re-draw the whole screen here... */
3411 if (diff >= clist->clist_window_height)
3413 clist->voffset = -value;
3414 draw_rows (clist, NULL);
3418 if ((diff != 0) && (diff != clist->clist_window_height))
3419 gdk_window_copy_area (clist->clist_window,
3422 clist->clist_window,
3425 clist->clist_window_width,
3426 clist->clist_window_height - diff);
3429 area.y = clist->clist_window_height - diff;
3430 area.width = clist->clist_window_width;
3436 diff = -clist->voffset - value;
3438 /* we have to re-draw the whole screen here... */
3439 if (diff >= clist->clist_window_height)
3441 clist->voffset = -value;
3442 draw_rows (clist, NULL);
3446 if ((diff != 0) && (diff != clist->clist_window_height))
3447 gdk_window_copy_area (clist->clist_window,
3450 clist->clist_window,
3453 clist->clist_window_width,
3454 clist->clist_window_height - diff);
3458 area.width = clist->clist_window_width;
3463 clist->voffset = -value;
3464 if ((diff != 0) && (diff != clist->clist_window_height))
3465 check_exposures (clist);
3468 draw_rows (clist, &area);
3472 hadjustment_value_changed (GtkAdjustment * adjustment,
3477 gint i, diff, value;
3479 g_return_if_fail (adjustment != NULL);
3480 g_return_if_fail (data != NULL);
3481 g_return_if_fail (GTK_IS_CLIST (data));
3483 clist = GTK_CLIST (data);
3485 if (!GTK_WIDGET_DRAWABLE (clist))
3488 value = adjustment->value;
3490 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
3492 /* move the column buttons and resize windows */
3493 for (i = 0; i < clist->columns; i++)
3495 if (clist->column[i].button)
3497 clist->column[i].button->allocation.x -= value + clist->hoffset;
3499 if (clist->column[i].button->window)
3501 gdk_window_move (clist->column[i].button->window,
3502 clist->column[i].button->allocation.x,
3503 clist->column[i].button->allocation.y);
3505 if (clist->column[i].window)
3506 gdk_window_move (clist->column[i].window,
3507 clist->column[i].button->allocation.x +
3508 clist->column[i].button->allocation.width -
3509 (DRAG_WIDTH / 2), 0);
3514 if (value > -clist->hoffset)
3517 diff = value + clist->hoffset;
3519 /* we have to re-draw the whole screen here... */
3520 if (diff >= clist->clist_window_width)
3522 clist->hoffset = -value;
3523 draw_rows (clist, NULL);
3527 if ((diff != 0) && (diff != clist->clist_window_width))
3528 gdk_window_copy_area (clist->clist_window,
3531 clist->clist_window,
3534 clist->clist_window_width - diff,
3535 clist->clist_window_height);
3537 area.x = clist->clist_window_width - diff;
3540 area.height = clist->clist_window_height;
3545 diff = -clist->hoffset - value;
3547 /* we have to re-draw the whole screen here... */
3548 if (diff >= clist->clist_window_width)
3550 clist->hoffset = -value;
3551 draw_rows (clist, NULL);
3555 if ((diff != 0) && (diff != clist->clist_window_width))
3556 gdk_window_copy_area (clist->clist_window,
3559 clist->clist_window,
3562 clist->clist_window_width - diff,
3563 clist->clist_window_height);
3568 area.height = clist->clist_window_height;
3571 clist->hoffset = -value;
3572 if ((diff != 0) && (diff != clist->clist_window_width))
3573 check_exposures (clist);
3576 draw_rows (clist, &area);
3580 * Memory Allocation/Distruction Routines for GtkCList stuctures
3592 static GtkCListColumn *
3593 columns_new (GtkCList * clist)
3596 GtkCListColumn *column;
3598 column = g_new (GtkCListColumn, clist->columns);
3600 for (i = 0; i < clist->columns; i++)
3602 column[i].area.x = 0;
3603 column[i].area.y = 0;
3604 column[i].area.width = 0;
3605 column[i].area.height = 0;
3606 column[i].title = NULL;
3607 column[i].button = NULL;
3608 column[i].window = NULL;
3609 column[i].width = 0;
3610 column[i].width_set = FALSE;
3611 column[i].justification = GTK_JUSTIFY_LEFT;
3618 column_title_new (GtkCList * clist,
3622 if (clist->column[column].title)
3623 g_free (clist->column[column].title);
3625 clist->column[column].title = g_strdup (title);
3629 columns_delete (GtkCList * clist)
3633 for (i = 0; i < clist->columns; i++)
3634 if (clist->column[i].title)
3635 g_free (clist->column[i].title);
3637 g_free (clist->column);
3640 static GtkCListRow *
3641 row_new (GtkCList * clist)
3644 GtkCListRow *clist_row;
3646 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
3647 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3649 for (i = 0; i < clist->columns; i++)
3651 clist_row->cell[i].type = GTK_CELL_EMPTY;
3652 clist_row->cell[i].vertical = 0;
3653 clist_row->cell[i].horizontal = 0;
3656 clist_row->fg_set = FALSE;
3657 clist_row->bg_set = FALSE;
3658 clist_row->state = GTK_STATE_NORMAL;
3659 clist_row->data = NULL;
3660 clist_row->destroy = NULL;
3666 row_delete (GtkCList * clist,
3667 GtkCListRow * clist_row)
3671 for (i = 0; i < clist->columns; i++)
3672 cell_empty (clist, clist_row, i);
3674 if (clist_row->destroy)
3675 clist_row->destroy (clist_row->data);
3677 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
3678 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
3682 cell_empty (GtkCList * clist,
3683 GtkCListRow * clist_row,
3686 switch (clist_row->cell[column].type)
3688 case GTK_CELL_EMPTY:
3692 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3695 case GTK_CELL_PIXMAP:
3696 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3697 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3698 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3701 case GTK_CELL_PIXTEXT:
3702 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3703 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3704 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3705 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3708 case GTK_CELL_WIDGET:
3716 clist_row->cell[column].type = GTK_CELL_EMPTY;
3720 cell_set_text (GtkCList * clist,
3721 GtkCListRow * clist_row,
3725 cell_empty (clist, clist_row, column);
3729 clist_row->cell[column].type = GTK_CELL_TEXT;
3730 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3735 cell_set_pixmap (GtkCList * clist,
3736 GtkCListRow * clist_row,
3741 cell_empty (clist, clist_row, column);
3745 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3746 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3747 /* We set the mask even if it is NULL */
3748 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3753 cell_set_pixtext (GtkCList * clist,
3754 GtkCListRow * clist_row,
3761 cell_empty (clist, clist_row, column);
3765 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3766 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3767 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3768 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3769 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3773 /* Fill in data after widget is realized and has style */
3776 add_style_data (GtkCList * clist)
3780 widget = GTK_WIDGET(clist);
3782 /* text properties */
3783 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
3785 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
3786 clist->row_center_offset = widget->style->font->ascent + 1.5;
3791 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
3792 GTK_WIDGET (clist) ->style->font->descent + 1);
3793 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;