1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald,
3 * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "../config.h"
24 /* the number rows memchunk expands at a time */
25 #define CLIST_OPTIMUM_SIZE 512
27 /* the width of the column resize windows */
30 /* minimum allowed width of a column */
31 #define COLUMN_MIN_WIDTH 5
33 /* this defigns the base grid spacing */
34 #define CELL_SPACING 1
36 /* added the horizontal space at the beginning and end of a row*/
37 #define COLUMN_INSET 3
39 /* scrollbar spacing class macro */
40 #define SCROLLBAR_SPACING(w) (GTK_CLIST_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
42 /* gives the top pixel of the given row in context of
43 * the clist's voffset */
44 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
45 (((row) + 1) * CELL_SPACING) + \
48 /* returns the row index from a y pixel location in the
49 * context of the clist's voffset */
50 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
51 ((clist)->row_height + CELL_SPACING))
53 /* gives the left pixel of the given column in context of
54 * the clist's hoffset */
55 #define COLUMN_LEFT_XPIXEL(clist, column) ((clist)->column[(column)].area.x + \
58 /* returns the column index from a x pixel location in the
59 * context of the clist's hoffset */
61 COLUMN_FROM_XPIXEL (GtkCList * clist,
66 for (i = 0; i < clist->columns; i++)
68 cx = clist->column[i].area.x + clist->hoffset;
70 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
71 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
79 /* returns the top pixel of the given row in the context of
81 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
83 /* returns the left pixel of the given column in the context of
85 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
87 /* returns the total height of the list */
88 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
89 (CELL_SPACING * ((clist)->rows + 1)))
91 /* returns the total width of the list */
92 #define LIST_WIDTH(clist) ((clist)->column[(clist)->columns - 1].area.x + \
93 (clist)->column[(clist)->columns - 1].area.width + \
94 COLUMN_INSET + CELL_SPACING)
113 typedef void (*GtkCListSignal1) (GtkObject * object,
116 GdkEventButton * arg3,
119 typedef void (*GtkCListSignal2) (GtkObject * object,
124 static void sync_selection (GtkCList * clist,
128 /* GtkCList Methods */
129 static void gtk_clist_class_init (GtkCListClass * klass);
130 static void gtk_clist_init (GtkCList * clist);
132 /* GtkObject Methods */
133 static void gtk_clist_destroy (GtkObject * object);
134 static void gtk_clist_finalize (GtkObject * object);
137 /* GtkWidget Methods */
138 static void gtk_clist_realize (GtkWidget * widget);
139 static void gtk_clist_unrealize (GtkWidget * widget);
140 static void gtk_clist_map (GtkWidget * widget);
141 static void gtk_clist_unmap (GtkWidget * widget);
142 static void gtk_clist_draw (GtkWidget * widget,
143 GdkRectangle * area);
144 static gint gtk_clist_expose (GtkWidget * widget,
145 GdkEventExpose * event);
146 static gint gtk_clist_button_press (GtkWidget * widget,
147 GdkEventButton * event);
148 static gint gtk_clist_button_release (GtkWidget * widget,
149 GdkEventButton * event);
150 static gint gtk_clist_motion (GtkWidget * widget,
151 GdkEventMotion * event);
153 static void gtk_clist_size_request (GtkWidget * widget,
154 GtkRequisition * requisition);
155 static void gtk_clist_size_allocate (GtkWidget * widget,
156 GtkAllocation * allocation);
157 static gint get_selection_info (GtkCList * clist,
163 /* GtkContainer Methods */
164 static void gtk_clist_foreach (GtkContainer * container,
165 GtkCallback callback,
166 gpointer callback_data);
169 static void draw_row (GtkCList * clist,
172 GtkCListRow * clist_row);
173 static void draw_rows (GtkCList * clist,
174 GdkRectangle * area);
176 /* Size Allocation */
177 static void size_allocate_title_buttons (GtkCList * clist);
178 static void size_allocate_columns (GtkCList * clist);
181 static void toggle_row (GtkCList * clist,
184 GdkEventButton * event);
185 static void select_row (GtkCList * clist,
188 GdkEventButton * event);
189 static void unselect_row (GtkCList * clist,
192 GdkEventButton * event);
194 static void real_select_row (GtkCList * clist,
197 GdkEventButton * event);
198 static void real_unselect_row (GtkCList * clist,
201 GdkEventButton * event);
204 static void draw_xor_line (GtkCList * clist);
205 static gint new_column_width (GtkCList * clist,
209 static void resize_column (GtkCList * clist,
214 static void column_button_create (GtkCList * clist,
216 static void column_button_clicked (GtkWidget * widget,
220 static void create_scrollbars (GtkCList * clist);
221 static void adjust_scrollbars (GtkCList * clist);
222 static void check_exposures (GtkCList * clist);
223 static void vadjustment_changed (GtkAdjustment * adjustment,
225 static void vadjustment_value_changed (GtkAdjustment * adjustment,
227 static void hadjustment_changed (GtkAdjustment * adjustment,
229 static void hadjustment_value_changed (GtkAdjustment * adjustment,
233 /* Memory Allocation/Distruction Routines */
234 static GtkCListColumn *columns_new (GtkCList * clist);
236 static void column_title_new (GtkCList * clist,
239 static void columns_delete (GtkCList * clist);
241 static GtkCListRow *row_new (GtkCList * clist);
243 static void row_delete (GtkCList * clist,
244 GtkCListRow * clist_row);
245 static void cell_empty (GtkCList * clist,
246 GtkCListRow * clist_row,
248 static void cell_set_text (GtkCList * clist,
249 GtkCListRow * clist_row,
252 static void cell_set_pixmap (GtkCList * clist,
253 GtkCListRow * clist_row,
257 static void cell_set_pixtext (GtkCList * clist,
258 GtkCListRow * clist_row,
266 static void gtk_clist_marshal_signal_1 (GtkObject * object,
270 static void gtk_clist_marshal_signal_2 (GtkObject * object,
275 /* Fill in data after widget is realized and has style */
277 static void add_style_data (GtkCList * clist);
279 static GtkContainerClass *parent_class = NULL;
280 static guint clist_signals[LAST_SIGNAL] = {0};
284 gtk_clist_get_type (void)
286 static GtkType clist_type = 0;
290 GtkTypeInfo clist_info =
294 sizeof (GtkCListClass),
295 (GtkClassInitFunc) gtk_clist_class_init,
296 (GtkObjectInitFunc) gtk_clist_init,
297 /* reversed_1 */ NULL,
298 /* reversed_2 */ NULL,
299 (GtkClassInitFunc) NULL,
302 clist_type = gtk_type_unique (gtk_container_get_type (), &clist_info);
309 gtk_clist_class_init (GtkCListClass * klass)
311 GtkObjectClass *object_class;
312 GtkWidgetClass *widget_class;
313 GtkContainerClass *container_class;
315 object_class = (GtkObjectClass *) klass;
316 widget_class = (GtkWidgetClass *) klass;
317 container_class = (GtkContainerClass *) klass;
319 parent_class = gtk_type_class (gtk_container_get_type ());
321 clist_signals[SELECT_ROW] =
322 gtk_signal_new ("select_row",
325 GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
326 gtk_clist_marshal_signal_1,
327 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
328 clist_signals[UNSELECT_ROW] =
329 gtk_signal_new ("unselect_row",
332 GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
333 gtk_clist_marshal_signal_1,
334 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_GDK_EVENT);
335 clist_signals[CLICK_COLUMN] =
336 gtk_signal_new ("click_column",
339 GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
340 gtk_clist_marshal_signal_2,
341 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
343 gtk_object_class_add_signals (object_class, clist_signals, LAST_SIGNAL);
345 object_class->destroy = gtk_clist_destroy;
346 object_class->finalize = gtk_clist_finalize;
348 widget_class->realize = gtk_clist_realize;
349 widget_class->unrealize = gtk_clist_unrealize;
350 widget_class->map = gtk_clist_map;
351 widget_class->unmap = gtk_clist_unmap;
352 widget_class->draw = gtk_clist_draw;
353 widget_class->button_press_event = gtk_clist_button_press;
354 widget_class->button_release_event = gtk_clist_button_release;
355 widget_class->motion_notify_event = gtk_clist_motion;
356 widget_class->expose_event = gtk_clist_expose;
357 widget_class->size_request = gtk_clist_size_request;
358 widget_class->size_allocate = gtk_clist_size_allocate;
360 /* container_class->add = NULL; use the default GtkContainerClass warning */
361 /* container_class->remove = NULL; use the default GtkContainerClass warning */
362 container_class->foreach = gtk_clist_foreach;
364 klass->select_row = real_select_row;
365 klass->unselect_row = real_unselect_row;
366 klass->click_column = NULL;
368 klass->draw_row = draw_row;
370 klass->scrollbar_spacing = 5;
374 gtk_clist_marshal_signal_1 (GtkObject * object,
379 GtkCListSignal1 rfunc;
381 rfunc = (GtkCListSignal1) func;
383 (*rfunc) (object, GTK_VALUE_INT (args[0]),
384 GTK_VALUE_INT (args[1]),
385 GTK_VALUE_POINTER (args[2]),
390 gtk_clist_marshal_signal_2 (GtkObject * object,
395 GtkCListSignal2 rfunc;
397 rfunc = (GtkCListSignal2) func;
399 (*rfunc) (object, GTK_VALUE_INT (args[0]),
404 gtk_clist_init (GtkCList * clist)
408 GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
409 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
411 clist->row_mem_chunk = NULL;
412 clist->cell_mem_chunk = NULL;
415 clist->row_center_offset = 0;
416 clist->row_height = 0;
417 clist->row_list = NULL;
418 clist->row_list_end = NULL;
422 clist->title_window = NULL;
423 clist->column_title_area.x = 0;
424 clist->column_title_area.y = 0;
425 clist->column_title_area.width = 1;
426 clist->column_title_area.height = 1;
428 clist->clist_window = NULL;
429 clist->clist_window_width = 1;
430 clist->clist_window_height = 1;
435 clist->shadow_type = GTK_SHADOW_IN;
436 clist->hscrollbar_policy = GTK_POLICY_ALWAYS;
437 clist->vscrollbar_policy = GTK_POLICY_ALWAYS;
439 clist->cursor_drag = NULL;
440 clist->xor_gc = NULL;
445 clist->selection_mode = GTK_SELECTION_SINGLE;
446 clist->selection = NULL;
451 gtk_clist_construct (GtkCList * clist,
457 g_return_if_fail (clist != NULL);
458 g_return_if_fail (GTK_IS_CLIST (clist));
459 g_return_if_fail (GTK_CLIST_CONSTRUCTED (clist) == FALSE);
461 GTK_CLIST_SET_FLAG (clist, CLIST_CONSTRUCTED);
463 /* initalize memory chunks, if this has not been done by any
464 * possibly derived widget
466 if (!clist->row_mem_chunk)
467 clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
468 sizeof (GtkCListRow),
469 sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE,
472 if (!clist->cell_mem_chunk)
473 clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
474 sizeof (GtkCell) * columns,
475 sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE,
478 /* set number of columns, allocate memory */
479 clist->columns = columns;
480 clist->column = columns_new (clist);
482 /* there needs to be at least one column button
483 * because there is alot of code that will break if it
485 column_button_create (clist, 0);
487 /* create scrollbars */
488 create_scrollbars (clist);
492 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
493 for (i = 0; i < columns; i++)
494 gtk_clist_set_column_title (clist, i, titles[i]);
498 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
503 * GTKCLIST PUBLIC INTERFACE
504 * gtk_clist_new_with_titles
508 gtk_clist_new_with_titles (gint columns,
513 g_return_val_if_fail (titles != NULL, NULL);
515 widget = gtk_type_new (gtk_clist_get_type ());
517 gtk_clist_construct (GTK_CLIST (widget), columns, titles);
523 gtk_clist_new (gint columns)
530 clist = gtk_type_new (gtk_clist_get_type ());
531 gtk_clist_construct (clist, columns, NULL);
532 return GTK_WIDGET (clist);
536 gtk_clist_set_border (GtkCList * clist,
537 GtkShadowType border)
539 g_return_if_fail (clist != NULL);
541 clist->shadow_type = border;
543 if (GTK_WIDGET_VISIBLE (clist))
544 gtk_widget_queue_resize (GTK_WIDGET (clist));
548 gtk_clist_set_selection_mode (GtkCList * clist,
549 GtkSelectionMode mode)
551 g_return_if_fail (clist != NULL);
553 clist->selection_mode = mode;
557 gtk_clist_freeze (GtkCList * clist)
559 g_return_if_fail (clist != NULL);
561 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
565 gtk_clist_thaw (GtkCList * clist)
567 g_return_if_fail (clist != NULL);
569 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
571 adjust_scrollbars (clist);
572 draw_rows (clist, NULL);
576 gtk_clist_column_titles_show (GtkCList * clist)
578 g_return_if_fail (clist != NULL);
580 if (!GTK_CLIST_SHOW_TITLES (clist))
582 GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
583 if (clist->title_window)
584 gdk_window_show (clist->title_window);
585 gtk_widget_queue_resize (GTK_WIDGET (clist));
590 gtk_clist_column_titles_hide (GtkCList * clist)
592 g_return_if_fail (clist != NULL);
594 if (GTK_CLIST_SHOW_TITLES (clist))
596 GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
597 if (clist->title_window)
598 gdk_window_hide (clist->title_window);
599 gtk_widget_queue_resize (GTK_WIDGET (clist));
604 gtk_clist_column_title_active (GtkCList * clist,
607 g_return_if_fail (clist != NULL);
609 if (column < 0 || column >= clist->columns)
612 if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
613 !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
615 GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
616 if (GTK_WIDGET_VISIBLE (clist))
617 gtk_widget_queue_draw (clist->column[column].button);
622 gtk_clist_column_title_passive (GtkCList * clist,
625 g_return_if_fail (clist != NULL);
627 if (column < 0 || column >= clist->columns)
630 if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
631 GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
633 GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
634 if (GTK_WIDGET_VISIBLE (clist))
635 gtk_widget_queue_draw (clist->column[column].button);
640 gtk_clist_column_titles_active (GtkCList * clist)
644 g_return_if_fail (clist != NULL);
646 for (i = 0; i < clist->columns; i++)
647 if (clist->column[i].button)
648 gtk_clist_column_title_active (clist, i);
652 gtk_clist_column_titles_passive (GtkCList * clist)
656 g_return_if_fail (clist != NULL);
658 for (i = 0; i < clist->columns; i++)
659 if (clist->column[i].button)
660 gtk_clist_column_title_passive (clist, i);
664 gtk_clist_set_column_title (GtkCList * clist,
669 GtkWidget *old_widget;
670 GtkWidget *alignment = NULL;
673 g_return_if_fail (clist != NULL);
675 if (column < 0 || column >= clist->columns)
678 /* if the column button doesn't currently exist,
679 * it has to be created first */
680 if (!clist->column[column].button)
682 column_button_create (clist, column);
686 column_title_new (clist, column, title);
688 /* remove and destroy the old widget */
689 old_widget = GTK_BUTTON (clist->column[column].button)->child;
691 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
693 /* create new alignment based no column justification */
694 switch (clist->column[column].justification)
696 case GTK_JUSTIFY_LEFT:
697 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
700 case GTK_JUSTIFY_RIGHT:
701 alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
704 case GTK_JUSTIFY_CENTER:
705 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
708 case GTK_JUSTIFY_FILL:
709 alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
713 label = gtk_label_new (clist->column[column].title);
714 gtk_container_add (GTK_CONTAINER (alignment), label);
715 gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
716 gtk_widget_show (label);
717 gtk_widget_show (alignment);
719 /* if this button didn't previously exist, then the
720 * column button positions have to be re-computed */
721 if (GTK_WIDGET_VISIBLE (clist) && new_button)
722 size_allocate_title_buttons (clist);
726 gtk_clist_set_column_widget (GtkCList * clist,
731 GtkWidget *old_widget;
733 g_return_if_fail (clist != NULL);
735 if (column < 0 || column >= clist->columns)
738 /* if the column button doesn't currently exist,
739 * it has to be created first */
740 if (!clist->column[column].button)
742 column_button_create (clist, column);
746 column_title_new (clist, column, NULL);
748 /* remove and destroy the old widget */
749 old_widget = GTK_BUTTON (clist->column[column].button)->child;
751 gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
753 /* add and show the widget */
756 gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
757 gtk_widget_show (widget);
760 /* if this button didn't previously exist, then the
761 * column button positions have to be re-computed */
762 if (GTK_WIDGET_VISIBLE (clist) && new_button)
763 size_allocate_title_buttons (clist);
767 gtk_clist_set_column_justification (GtkCList * clist,
769 GtkJustification justification)
771 GtkWidget *alignment;
773 g_return_if_fail (clist != NULL);
775 if (column < 0 || column >= clist->columns)
778 clist->column[column].justification = justification;
780 /* change the alinment of the button title if it's not a
782 if (clist->column[column].title)
784 alignment = GTK_BUTTON (clist->column[column].button)->child;
786 switch (clist->column[column].justification)
788 case GTK_JUSTIFY_LEFT:
789 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
792 case GTK_JUSTIFY_RIGHT:
793 gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
796 case GTK_JUSTIFY_CENTER:
797 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
800 case GTK_JUSTIFY_FILL:
801 gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
809 if (!GTK_CLIST_FROZEN (clist))
810 draw_rows (clist, NULL);
814 gtk_clist_set_column_width (GtkCList * clist,
818 g_return_if_fail (clist != NULL);
820 if (column < 0 || column >= clist->columns)
823 clist->column[column].width = width;
824 clist->column[column].width_set = TRUE;
826 /* FIXME: this is quite expensive to do if the widget hasn't
827 * been size_allocated yet, and pointless. Should
830 size_allocate_columns (clist);
831 size_allocate_title_buttons (clist);
833 if (!GTK_CLIST_FROZEN (clist))
835 adjust_scrollbars (clist);
836 draw_rows (clist, NULL);
841 gtk_clist_set_row_height (GtkCList * clist,
846 g_return_if_fail (clist != NULL);
849 clist->row_height = height;
853 GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
855 if (GTK_WIDGET_REALIZED (clist))
857 text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
858 GTK_WIDGET (clist) ->style->font->descent + 1);
859 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
862 if (!GTK_CLIST_FROZEN (clist))
864 adjust_scrollbars (clist);
865 draw_rows (clist, NULL);
870 gtk_clist_moveto (GtkCList * clist,
878 g_return_if_fail (clist != NULL);
880 if (row < -1 || row >= clist->rows)
882 if (column < -1 || column >= clist->columns)
885 /* adjust vertical scrollbar */
888 x = ROW_TOP (clist, row) - (row_align * (clist->clist_window_height -
889 (clist->row_height + 2 * CELL_SPACING)));
892 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
893 else if (x > LIST_HEIGHT (clist) - clist->clist_window_height)
894 GTK_RANGE (clist->vscrollbar)->adjustment->value = LIST_HEIGHT (clist) -
895 clist->clist_window_height;
897 GTK_RANGE (clist->vscrollbar)->adjustment->value = x;
899 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
903 /* adjust horizontal scrollbar */
906 y = COLUMN_LEFT (clist, column) - (col_align * (clist->clist_window_width -
907 clist->column[column].area.width +
908 2 * (CELL_SPACING + COLUMN_INSET)));
911 GTK_RANGE (clist->hscrollbar)->adjustment->value = 0.0;
912 else if (y > LIST_WIDTH (clist) - clist->clist_window_width)
913 GTK_RANGE (clist->hscrollbar)->adjustment->value = LIST_WIDTH (clist) -
914 clist->clist_window_width;
916 GTK_RANGE (clist->hscrollbar)->adjustment->value = y;
918 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
924 gtk_clist_get_cell_type (GtkCList * clist,
928 GtkCListRow *clist_row;
930 g_return_val_if_fail (clist != NULL, -1);
932 if (row < 0 || row >= clist->rows)
934 if (column < 0 || column >= clist->columns)
937 clist_row = (g_list_nth (clist->row_list, row))->data;
939 return clist_row->cell[column].type;
943 gtk_clist_set_text (GtkCList * clist,
948 GtkCListRow *clist_row;
950 g_return_if_fail (clist != NULL);
952 if (row < 0 || row >= clist->rows)
954 if (column < 0 || column >= clist->columns)
957 clist_row = (g_list_nth (clist->row_list, row))->data;
959 /* if text is null, then the cell is empty */
961 cell_set_text (clist, clist_row, column, text);
963 cell_empty (clist, clist_row, column);
965 /* redraw the list if it's not frozen */
966 if (!GTK_CLIST_FROZEN (clist))
968 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
969 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
970 (clist, NULL, row, clist_row);
975 gtk_clist_get_text (GtkCList * clist,
980 GtkCListRow *clist_row;
982 g_return_val_if_fail (clist != NULL, 0);
984 if (row < 0 || row >= clist->rows)
986 if (column < 0 || column >= clist->columns)
989 clist_row = (g_list_nth (clist->row_list, row))->data;
991 if (clist_row->cell[column].type != GTK_CELL_TEXT)
995 *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
1001 gtk_clist_set_pixmap (GtkCList * clist,
1007 GtkCListRow *clist_row;
1009 g_return_if_fail (clist != NULL);
1011 if (row < 0 || row >= clist->rows)
1013 if (column < 0 || column >= clist->columns)
1016 clist_row = (g_list_nth (clist->row_list, row))->data;
1018 gdk_pixmap_ref (pixmap);
1020 if (mask) gdk_pixmap_ref (mask);
1022 cell_set_pixmap (clist, clist_row, column, pixmap, mask);
1024 /* redraw the list if it's not frozen */
1025 if (!GTK_CLIST_FROZEN (clist))
1027 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1028 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1029 (clist, NULL, row, clist_row);
1034 gtk_clist_get_pixmap (GtkCList * clist,
1037 GdkPixmap ** pixmap,
1040 GtkCListRow *clist_row;
1042 g_return_val_if_fail (clist != NULL, 0);
1044 if (row < 0 || row >= clist->rows)
1046 if (column < 0 || column >= clist->columns)
1049 clist_row = (g_list_nth (clist->row_list, row))->data;
1051 if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
1056 *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
1057 /* mask can be NULL */
1058 *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
1065 gtk_clist_set_pixtext (GtkCList * clist,
1073 GtkCListRow *clist_row;
1075 g_return_if_fail (clist != NULL);
1077 if (row < 0 || row >= clist->rows)
1079 if (column < 0 || column >= clist->columns)
1082 clist_row = (g_list_nth (clist->row_list, row))->data;
1084 gdk_pixmap_ref (pixmap);
1085 if (mask) gdk_pixmap_ref (mask);
1086 cell_set_pixtext (clist, clist_row, column, text, spacing, pixmap, mask);
1088 /* redraw the list if it's not frozen */
1089 if (!GTK_CLIST_FROZEN (clist))
1091 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1092 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1093 (clist, NULL, row, clist_row);
1098 gtk_clist_get_pixtext (GtkCList * clist,
1103 GdkPixmap ** pixmap,
1106 GtkCListRow *clist_row;
1108 g_return_val_if_fail (clist != NULL, 0);
1110 if (row < 0 || row >= clist->rows)
1112 if (column < 0 || column >= clist->columns)
1115 clist_row = (g_list_nth (clist->row_list, row))->data;
1117 if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
1121 *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
1123 *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
1125 *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
1127 /* mask can be NULL */
1128 *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
1134 gtk_clist_set_foreground (GtkCList * clist,
1138 GtkCListRow *clist_row;
1140 g_return_if_fail (clist != NULL);
1142 if (row < 0 || row >= clist->rows)
1145 clist_row = (g_list_nth (clist->row_list, row))->data;
1149 clist_row->foreground = *color;
1150 clist_row->fg_set = TRUE;
1153 clist_row->fg_set = FALSE;
1155 if (!GTK_CLIST_FROZEN (clist)
1156 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1157 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1158 (clist, NULL, row, clist_row);
1162 gtk_clist_set_background (GtkCList * clist,
1166 GtkCListRow *clist_row;
1168 g_return_if_fail (clist != NULL);
1170 if (row < 0 || row >= clist->rows)
1173 clist_row = (g_list_nth (clist->row_list, row))->data;
1177 clist_row->background = *color;
1178 clist_row->bg_set = TRUE;
1181 clist_row->bg_set = FALSE;
1183 if (!GTK_CLIST_FROZEN (clist)
1184 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1185 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1186 (clist, NULL, row, clist_row);
1190 gtk_clist_set_shift (GtkCList * clist,
1196 GtkCListRow *clist_row;
1198 g_return_if_fail (clist != NULL);
1200 if (row < 0 || row >= clist->rows)
1202 if (column < 0 || column >= clist->columns)
1205 clist_row = (g_list_nth (clist->row_list, row))->data;
1207 clist_row->cell[column].vertical = vertical;
1208 clist_row->cell[column].horizontal = horizontal;
1210 if (!GTK_CLIST_FROZEN (clist)
1211 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
1212 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1213 (clist, NULL, row, clist_row);
1217 gtk_clist_append (GtkCList * clist,
1221 GtkCListRow *clist_row;
1223 g_return_val_if_fail (clist != NULL, -1);
1225 clist_row = row_new (clist);
1228 /* set the text in the row's columns */
1230 for (i = 0; i < clist->columns; i++)
1232 cell_set_text (clist, clist_row, i, text[i]);
1234 /* keeps track of the end of the list so the list
1235 * doesn't have to be traversed every time a item is added */
1236 if (!clist->row_list)
1238 clist->row_list = g_list_append (clist->row_list, clist_row);
1239 clist->row_list_end = clist->row_list;
1241 /* check the selection mode to see if we should select
1242 * the first row automaticly */
1243 switch (clist->selection_mode)
1245 case GTK_SELECTION_BROWSE:
1246 gtk_clist_select_row (clist, 0, -1);
1254 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1256 /* redraw the list if it's not frozen */
1257 if (!GTK_CLIST_FROZEN (clist))
1259 adjust_scrollbars (clist);
1261 if (gtk_clist_row_is_visible (clist, clist->rows - 1) != GTK_VISIBILITY_NONE)
1262 draw_rows (clist, NULL);
1265 /* return index of the row */
1266 return clist->rows - 1;
1270 gtk_clist_insert (GtkCList * clist,
1275 GtkCListRow *clist_row;
1277 g_return_if_fail (clist != NULL);
1278 g_return_if_fail (text != NULL);
1280 /* return if out of bounds */
1281 if (row < 0 || row > clist->rows)
1284 if (clist->rows == 0)
1285 gtk_clist_append (clist, text);
1288 /* create the row */
1289 clist_row = row_new (clist);
1291 /* set the text in the row's columns */
1293 for (i = 0; i < clist->columns; i++)
1295 cell_set_text (clist, clist_row, i, text[i]);
1297 /* reset the row end pointer if we're inserting at the
1298 * end of the list */
1299 if (row == clist->rows)
1300 clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
1302 clist->row_list = g_list_insert (clist->row_list, clist_row, row);
1306 /* syncronize the selection list */
1307 sync_selection (clist, row, SYNC_INSERT);
1310 /* redraw the list if it isn't frozen */
1311 if (!GTK_CLIST_FROZEN (clist))
1313 adjust_scrollbars (clist);
1315 if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
1316 draw_rows (clist, NULL);
1321 gtk_clist_remove (GtkCList * clist,
1324 gint was_visible, was_selected;
1326 GtkCListRow *clist_row;
1328 g_return_if_fail (clist != NULL);
1330 /* return if out of bounds */
1331 if (row < 0 || row > (clist->rows - 1))
1334 was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
1337 /* get the row we're going to delete */
1338 list = g_list_nth (clist->row_list, row);
1339 clist_row = list->data;
1341 /* if we're removing a selected row, we have to make sure
1342 * it's properly unselected, and then sync up the clist->selected
1343 * list to reflect the deincrimented indexies of rows after the
1345 if (clist_row->state == GTK_STATE_SELECTED)
1349 switch (clist->selection_mode)
1351 case GTK_SELECTION_SINGLE:
1352 case GTK_SELECTION_BROWSE:
1353 case GTK_SELECTION_MULTIPLE:
1354 gtk_clist_unselect_row (clist, row, -1);
1362 /* reset the row end pointer if we're removing at the
1363 * end of the list */
1364 if (row == clist->rows - 1)
1365 clist->row_list_end = list->prev;
1367 clist->row_list = g_list_remove (clist->row_list, clist_row);
1369 sync_selection (clist, row, SYNC_REMOVE);
1371 /* preform any selections required by the selection mode */
1374 switch (clist->selection_mode)
1376 case GTK_SELECTION_BROWSE:
1377 if (row == clist->rows)
1378 gtk_clist_select_row (clist, row - 1, -1);
1380 gtk_clist_select_row (clist, row, -1);
1389 row_delete (clist, clist_row);
1391 /* redraw the row if it isn't frozen */
1392 if (!GTK_CLIST_FROZEN (clist))
1394 adjust_scrollbars (clist);
1397 draw_rows (clist, NULL);
1402 sync_selection (GtkCList * clist,
1408 list = clist->selection;
1411 if (GPOINTER_TO_INT (list->data) >= row)
1415 list->data = ((gchar*) list->data) + 1;
1419 list->data = ((gchar*) list->data) - 1;
1431 gtk_clist_clear (GtkCList * clist)
1435 g_return_if_fail (clist != NULL);
1437 /* remove all the rows */
1438 for (list = clist->row_list; list; list = list->next)
1440 GtkCListRow *clist_row;
1442 clist_row = list->data;
1443 row_delete (clist, clist_row);
1445 g_list_free (clist->row_list);
1447 /* free up the selection list */
1448 g_list_free (clist->selection);
1450 clist->row_list = NULL;
1451 clist->row_list_end = NULL;
1452 clist->selection = NULL;
1456 /* zero-out the scrollbars */
1457 if (clist->vscrollbar)
1459 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
1460 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
1462 if (!GTK_CLIST_FROZEN (clist))
1464 adjust_scrollbars (clist);
1465 draw_rows (clist, NULL);
1471 gtk_clist_swap_rows (GtkCList * clist,
1476 GList *list, *link1, *link2;
1479 g_return_if_fail (clist != NULL);
1481 if (row1 < 0 || row1 > (clist->rows - 1))
1484 if (row2 < 0 || row2 > (clist->rows - 1))
1487 first = MIN (row1, row2);
1488 last = MAX (row1, row2);
1490 link1 = g_list_nth (clist->row_list, first);
1491 link2 = g_list_nth (link1, row2 - row1);
1494 link1->data = link2->data;
1497 list = clist->selection;
1500 if (GPOINTER_TO_INT (list->data) == row1)
1501 GPOINTER_TO_INT (list->data) = row2;
1503 if (GPOINTER_TO_INT (list->data) == row2)
1504 GPOINTER_TO_INT (list->data) = row1;
1509 if (!GTK_CLIST_FROZEN (clist))
1511 if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
1512 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1513 (clist, NULL, row1, (GtkCListRow *) link2->data);
1515 if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
1516 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1517 (clist, NULL, row2, (GtkCListRow *) link1->data);
1522 gtk_clist_set_row_data (GtkCList * clist,
1526 gtk_clist_set_row_data_full (clist, row, data, NULL);
1530 gtk_clist_set_row_data_full (GtkCList * clist,
1533 GtkDestroyNotify destroy)
1535 GtkCListRow *clist_row;
1537 g_return_if_fail (clist != NULL);
1539 if (row < 0 || row > (clist->rows - 1))
1542 clist_row = (g_list_nth (clist->row_list, row))->data;
1543 clist_row->data = data;
1544 clist_row->destroy = destroy;
1546 /* re-send the selected signal if data is changed/added
1547 * so the application can respond to the new data --
1548 * this could be questionable behavior */
1549 if (clist_row->state == GTK_STATE_SELECTED)
1550 gtk_clist_select_row (clist, row, -1);
1554 gtk_clist_get_row_data (GtkCList * clist,
1557 GtkCListRow *clist_row;
1559 g_return_val_if_fail (clist != NULL, NULL);
1561 if (row < 0 || row > (clist->rows - 1))
1564 clist_row = (g_list_nth (clist->row_list, row))->data;
1565 return clist_row->data;
1569 gtk_clist_find_row_from_data (GtkCList * clist,
1575 g_return_val_if_fail (clist != NULL, -1);
1576 g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
1578 if (clist->rows < 1)
1579 return -1; /* is this an optimization or just worthless? */
1582 list = clist->row_list;
1585 GtkCListRow *clist_row;
1587 clist_row = list->data;
1588 if (clist_row->data == data)
1601 gtk_clist_select_row (GtkCList * clist,
1605 g_return_if_fail (clist != NULL);
1607 if (row < 0 || row >= clist->rows)
1610 if (column < -1 || column >= clist->columns)
1613 select_row (clist, row, column, NULL);
1617 gtk_clist_unselect_row (GtkCList * clist,
1621 g_return_if_fail (clist != NULL);
1623 if (row < 0 || row >= clist->rows)
1626 if (column < -1 || column >= clist->columns)
1629 unselect_row (clist, row, column, NULL);
1633 gtk_clist_row_is_visible (GtkCList * clist,
1638 g_return_val_if_fail (clist != NULL, 0);
1640 if (row < 0 || row >= clist->rows)
1641 return GTK_VISIBILITY_NONE;
1643 if (clist->row_height == 0)
1644 return GTK_VISIBILITY_NONE;
1646 if (row < ROW_FROM_YPIXEL (clist, 0))
1647 return GTK_VISIBILITY_NONE;
1649 if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
1650 return GTK_VISIBILITY_NONE;
1652 top = ROW_TOP_YPIXEL (clist, row);
1655 || ((top + clist->row_height) >= clist->clist_window_height))
1656 return GTK_VISIBILITY_PARTIAL;
1658 return GTK_VISIBILITY_FULL;
1662 gtk_clist_get_vadjustment (GtkCList * clist)
1664 g_return_val_if_fail (clist != NULL, NULL);
1665 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1667 return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
1671 gtk_clist_get_hadjustment (GtkCList * clist)
1673 g_return_val_if_fail (clist != NULL, NULL);
1674 g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
1676 return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
1680 gtk_clist_set_policy (GtkCList * clist,
1681 GtkPolicyType vscrollbar_policy,
1682 GtkPolicyType hscrollbar_policy)
1684 g_return_if_fail (clist != NULL);
1685 g_return_if_fail (GTK_IS_CLIST (clist));
1687 if (clist->vscrollbar_policy != vscrollbar_policy)
1689 clist->vscrollbar_policy = vscrollbar_policy;
1691 if (GTK_WIDGET (clist)->parent)
1692 gtk_widget_queue_resize (GTK_WIDGET (clist));
1695 if (clist->hscrollbar_policy != hscrollbar_policy)
1697 clist->hscrollbar_policy = hscrollbar_policy;
1699 if (GTK_WIDGET (clist)->parent)
1700 gtk_widget_queue_resize (GTK_WIDGET (clist));
1707 * gtk_clist_finalize
1710 gtk_clist_destroy (GtkObject * object)
1715 g_return_if_fail (object != NULL);
1716 g_return_if_fail (GTK_IS_CLIST (object));
1718 clist = GTK_CLIST (object);
1720 /* freeze the list */
1721 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1723 /* get rid of all the rows */
1724 gtk_clist_clear (clist);
1726 /* Since we don't have a _remove method, unparent the children
1727 * instead of destroying them so the focus will be unset properly.
1728 * (For other containers, the _remove method takes care of the
1729 * unparent) The destroy will happen when the refcount drops
1733 /* destroy the scrollbars */
1734 if (clist->vscrollbar)
1736 gtk_widget_unparent (clist->vscrollbar);
1737 clist->vscrollbar = NULL;
1739 if (clist->hscrollbar)
1741 gtk_widget_unparent (clist->hscrollbar);
1742 clist->hscrollbar = NULL;
1745 /* destroy the column buttons */
1746 for (i = 0; i < clist->columns; i++)
1747 if (clist->column[i].button)
1749 gtk_widget_unparent (clist->column[i].button);
1750 clist->column[i].button = NULL;
1753 if (GTK_OBJECT_CLASS (parent_class)->destroy)
1754 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1758 gtk_clist_finalize (GtkObject * object)
1762 g_return_if_fail (object != NULL);
1763 g_return_if_fail (GTK_IS_CLIST (object));
1765 clist = GTK_CLIST (object);
1767 columns_delete (clist);
1769 g_mem_chunk_destroy (clist->cell_mem_chunk);
1770 g_mem_chunk_destroy (clist->row_mem_chunk);
1772 if (GTK_OBJECT_CLASS (parent_class)->finalize)
1773 (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
1779 * gtk_clist_unrealize
1784 * gtk_clist_button_press
1785 * gtk_clist_button_release
1786 * gtk_clist_button_motion
1787 * gtk_clist_size_request
1788 * gtk_clist_size_allocate
1791 gtk_clist_realize (GtkWidget * widget)
1795 GdkWindowAttr attributes;
1796 gint attributes_mask;
1800 g_return_if_fail (widget != NULL);
1801 g_return_if_fail (GTK_IS_CLIST (widget));
1803 clist = GTK_CLIST (widget);
1805 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1807 add_style_data (clist);
1809 border_width = GTK_CONTAINER (widget)->border_width;
1811 attributes.window_type = GDK_WINDOW_CHILD;
1812 attributes.x = widget->allocation.x + border_width;
1813 attributes.y = widget->allocation.y + border_width;
1814 attributes.width = widget->allocation.width - border_width * 2;
1815 attributes.height = widget->allocation.height - border_width * 2;
1816 attributes.wclass = GDK_INPUT_OUTPUT;
1817 attributes.visual = gtk_widget_get_visual (widget);
1818 attributes.colormap = gtk_widget_get_colormap (widget);
1819 attributes.event_mask = gtk_widget_get_events (widget);
1820 attributes.event_mask |= (GDK_EXPOSURE_MASK |
1821 GDK_BUTTON_PRESS_MASK |
1822 GDK_BUTTON_RELEASE_MASK |
1823 GDK_KEY_PRESS_MASK);
1824 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1828 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1829 gdk_window_set_user_data (widget->window, clist);
1831 widget->style = gtk_style_attach (widget->style, widget->window);
1833 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1835 /* column-title window */
1837 attributes.x = clist->column_title_area.x;
1838 attributes.y = clist->column_title_area.y;
1839 attributes.width = clist->column_title_area.width;
1840 attributes.height = clist->column_title_area.height;
1842 clist->title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1843 gdk_window_set_user_data (clist->title_window, clist);
1845 gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
1846 gdk_window_show (clist->title_window);
1848 /* set things up so column buttons are drawn in title window */
1849 for (i = 0; i < clist->columns; i++)
1850 if (clist->column[i].button)
1851 gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
1854 attributes.x = clist->internal_allocation.x + widget->style->klass->xthickness;
1855 attributes.y = clist->internal_allocation.y + widget->style->klass->ythickness +
1856 clist->column_title_area.height;
1857 attributes.width = clist->clist_window_width;
1858 attributes.height = clist->clist_window_height;
1860 clist->clist_window = gdk_window_new (widget->window, &attributes, attributes_mask);
1861 gdk_window_set_user_data (clist->clist_window, clist);
1863 gdk_window_set_background (clist->clist_window, &widget->style->bg[GTK_STATE_PRELIGHT]);
1864 gdk_window_show (clist->clist_window);
1865 gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
1866 &clist->clist_window_height);
1868 /* create resize windows */
1869 attributes.wclass = GDK_INPUT_ONLY;
1870 attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
1871 GDK_BUTTON_RELEASE_MASK |
1872 GDK_POINTER_MOTION_MASK |
1873 GDK_POINTER_MOTION_HINT_MASK);
1874 attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1875 attributes_mask = GDK_WA_CURSOR;
1877 for (i = 0; i < clist->columns; i++)
1879 clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
1880 gdk_window_set_user_data (clist->column[i].window, clist);
1883 /* This is slightly less efficient than creating them with the
1884 * right size to begin with, but easier
1886 size_allocate_title_buttons (clist);
1889 clist->fg_gc = gdk_gc_new (widget->window);
1890 clist->bg_gc = gdk_gc_new (widget->window);
1892 /* We'll use this gc to do scrolling as well */
1893 gdk_gc_set_exposures (clist->fg_gc, TRUE);
1895 values.foreground = widget->style->white;
1896 values.function = GDK_XOR;
1897 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1898 clist->xor_gc = gdk_gc_new_with_values (widget->window,
1906 gtk_clist_unrealize (GtkWidget * widget)
1911 g_return_if_fail (widget != NULL);
1912 g_return_if_fail (GTK_IS_CLIST (widget));
1914 clist = GTK_CLIST (widget);
1916 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
1918 gdk_cursor_destroy (clist->cursor_drag);
1919 gdk_gc_destroy (clist->xor_gc);
1920 gdk_gc_destroy (clist->fg_gc);
1921 gdk_gc_destroy (clist->bg_gc);
1923 for (i = 0; i < clist->columns; i++)
1924 if (clist->column[i].window)
1926 gdk_window_set_user_data (clist->column[i].window, NULL);
1927 gdk_window_destroy (clist->column[i].window);
1928 clist->column[i].window = NULL;
1931 gdk_window_set_user_data (clist->clist_window, NULL);
1932 gdk_window_destroy (clist->clist_window);
1933 clist->clist_window = NULL;
1935 gdk_window_set_user_data (clist->title_window, NULL);
1936 gdk_window_destroy (clist->title_window);
1937 clist->title_window = NULL;
1939 clist->cursor_drag = NULL;
1940 clist->xor_gc = NULL;
1941 clist->fg_gc = NULL;
1942 clist->bg_gc = NULL;
1944 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1945 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1949 gtk_clist_map (GtkWidget * widget)
1954 g_return_if_fail (widget != NULL);
1955 g_return_if_fail (GTK_IS_CLIST (widget));
1957 clist = GTK_CLIST (widget);
1959 if (!GTK_WIDGET_MAPPED (widget))
1961 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1963 gdk_window_show (widget->window);
1964 gdk_window_show (clist->title_window);
1965 gdk_window_show (clist->clist_window);
1967 /* map column buttons */
1968 for (i = 0; i < clist->columns; i++)
1969 if (clist->column[i].button &&
1970 GTK_WIDGET_VISIBLE (clist->column[i].button) &&
1971 !GTK_WIDGET_MAPPED (clist->column[i].button))
1972 gtk_widget_map (clist->column[i].button);
1974 /* map resize windows AFTER column buttons (above) */
1975 for (i = 0; i < clist->columns; i++)
1976 if (clist->column[i].window && clist->column[i].button)
1977 gdk_window_show (clist->column[i].window);
1979 /* map vscrollbars */
1980 if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
1981 !GTK_WIDGET_MAPPED (clist->vscrollbar))
1982 gtk_widget_map (clist->vscrollbar);
1984 if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
1985 !GTK_WIDGET_MAPPED (clist->hscrollbar))
1986 gtk_widget_map (clist->hscrollbar);
1988 /* unfreeze the list */
1989 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
1994 gtk_clist_unmap (GtkWidget * widget)
1999 g_return_if_fail (widget != NULL);
2000 g_return_if_fail (GTK_IS_CLIST (widget));
2002 clist = GTK_CLIST (widget);
2004 if (GTK_WIDGET_MAPPED (widget))
2006 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2008 for (i = 0; i < clist->columns; i++)
2009 if (clist->column[i].window)
2010 gdk_window_hide (clist->column[i].window);
2012 gdk_window_hide (clist->clist_window);
2013 gdk_window_hide (clist->title_window);
2014 gdk_window_hide (widget->window);
2016 /* unmap scrollbars */
2017 if (GTK_WIDGET_MAPPED (clist->vscrollbar))
2018 gtk_widget_unmap (clist->vscrollbar);
2020 if (GTK_WIDGET_MAPPED (clist->hscrollbar))
2021 gtk_widget_unmap (clist->hscrollbar);
2023 /* unmap column buttons */
2024 for (i = 0; i < clist->columns; i++)
2025 if (clist->column[i].button &&
2026 GTK_WIDGET_MAPPED (clist->column[i].button))
2027 gtk_widget_unmap (clist->column[i].button);
2029 /* freeze the list */
2030 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
2035 gtk_clist_draw (GtkWidget * widget,
2036 GdkRectangle * area)
2041 g_return_if_fail (widget != NULL);
2042 g_return_if_fail (GTK_IS_CLIST (widget));
2043 g_return_if_fail (area != NULL);
2045 if (GTK_WIDGET_DRAWABLE (widget))
2047 clist = GTK_CLIST (widget);
2048 border_width = GTK_CONTAINER (widget)->border_width;
2050 gdk_window_clear_area (widget->window,
2051 area->x - border_width,
2052 area->y - border_width,
2053 area->width, area->height);
2055 /* draw list shadow/border */
2056 gtk_draw_shadow (widget->style, widget->window,
2057 GTK_STATE_NORMAL, clist->shadow_type,
2059 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2060 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2061 clist->column_title_area.height);
2063 gdk_window_clear_area (clist->clist_window,
2066 draw_rows (clist, NULL);
2071 gtk_clist_expose (GtkWidget * widget,
2072 GdkEventExpose * event)
2076 g_return_val_if_fail (widget != NULL, FALSE);
2077 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2078 g_return_val_if_fail (event != NULL, FALSE);
2080 if (GTK_WIDGET_DRAWABLE (widget))
2082 clist = GTK_CLIST (widget);
2085 if (event->window == widget->window)
2086 gtk_draw_shadow (widget->style, widget->window,
2087 GTK_STATE_NORMAL, clist->shadow_type,
2089 clist->clist_window_width + (2 * widget->style->klass->xthickness),
2090 clist->clist_window_height + (2 * widget->style->klass->ythickness) +
2091 clist->column_title_area.height);
2093 /* exposure events on the list */
2094 if (event->window == clist->clist_window)
2095 draw_rows (clist, &event->area);
2102 gtk_clist_button_press (GtkWidget * widget,
2103 GdkEventButton * event)
2107 gint x, y, row, column;
2109 g_return_val_if_fail (widget != NULL, FALSE);
2110 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2111 g_return_val_if_fail (event != NULL, FALSE);
2113 clist = GTK_CLIST (widget);
2115 /* selections on the list */
2116 if (event->window == clist->clist_window)
2121 if (get_selection_info (clist, x, y, &row, &column))
2122 toggle_row (clist, row, column, event);
2127 /* press on resize windows */
2128 for (i = 0; i < clist->columns; i++)
2129 if (clist->column[i].window && event->window == clist->column[i].window)
2131 GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
2132 gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
2134 gdk_pointer_grab (clist->column[i].window, FALSE,
2135 GDK_POINTER_MOTION_HINT_MASK |
2136 GDK_BUTTON1_MOTION_MASK |
2137 GDK_BUTTON_RELEASE_MASK,
2138 NULL, NULL, event->time);
2140 draw_xor_line (clist);
2148 gtk_clist_button_release (GtkWidget * widget,
2149 GdkEventButton * event)
2151 gint i, x, width, visible;
2154 g_return_val_if_fail (widget != NULL, FALSE);
2155 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2156 g_return_val_if_fail (event != NULL, FALSE);
2158 clist = GTK_CLIST (widget);
2160 /* release on resize windows */
2161 if (GTK_CLIST_IN_DRAG (clist))
2162 for (i = 0; i < clist->columns; i++)
2163 if (clist->column[i].window && event->window == clist->column[i].window)
2165 GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
2166 gtk_widget_get_pointer (widget, &x, NULL);
2167 width = new_column_width (clist, i, &x, &visible);
2168 gdk_pointer_ungrab (event->time);
2171 draw_xor_line (clist);
2173 resize_column (clist, i, width);
2181 gtk_clist_motion (GtkWidget * widget,
2182 GdkEventMotion * event)
2187 g_return_val_if_fail (widget != NULL, FALSE);
2188 g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
2190 clist = GTK_CLIST (widget);
2192 if (GTK_CLIST_IN_DRAG (clist))
2193 for (i = 0; i < clist->columns; i++)
2194 if (clist->column[i].window && event->window == clist->column[i].window)
2196 if (event->is_hint || event->window != widget->window)
2197 gtk_widget_get_pointer (widget, &x, NULL);
2201 new_column_width (clist, i, &x, &visible);
2202 /* Welcome to my hack! I'm going to use a value of x_drage = -99999 to
2203 * indicate the the xor line is already no visible */
2204 if (!visible && clist->x_drag != -99999)
2206 draw_xor_line (clist);
2207 clist->x_drag = -99999;
2210 if (x != clist->x_drag && visible)
2212 if (clist->x_drag != -99999)
2213 draw_xor_line (clist);
2216 draw_xor_line (clist);
2224 gtk_clist_size_request (GtkWidget * widget,
2225 GtkRequisition * requisition)
2230 g_return_if_fail (widget != NULL);
2231 g_return_if_fail (GTK_IS_CLIST (widget));
2232 g_return_if_fail (requisition != NULL);
2234 clist = GTK_CLIST (widget);
2236 add_style_data (clist);
2238 requisition->width = 0;
2239 requisition->height = 0;
2241 /* compute the size of the column title (title) area */
2242 clist->column_title_area.height = 0;
2243 if (GTK_CLIST_SHOW_TITLES (clist))
2244 for (i = 0; i < clist->columns; i++)
2245 if (clist->column[i].button)
2247 gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
2248 clist->column_title_area.height = MAX (clist->column_title_area.height,
2249 clist->column[i].button->requisition.height);
2251 requisition->height += clist->column_title_area.height;
2253 /* add the vscrollbar space */
2254 if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2255 GTK_WIDGET_VISIBLE (clist->vscrollbar))
2257 gtk_widget_size_request (clist->vscrollbar, &clist->vscrollbar->requisition);
2259 requisition->width += clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist);
2260 requisition->height = MAX (requisition->height,
2261 clist->vscrollbar->requisition.height);
2264 /* add the hscrollbar space */
2265 if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
2266 GTK_WIDGET_VISIBLE (clist->hscrollbar))
2268 gtk_widget_size_request (clist->hscrollbar, &clist->hscrollbar->requisition);
2270 requisition->height += clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist);
2271 requisition->width = MAX (clist->hscrollbar->requisition.width,
2272 requisition->width -
2273 clist->vscrollbar->requisition.width);
2277 requisition->width += widget->style->klass->xthickness * 2 +
2278 GTK_CONTAINER (widget)->border_width * 2;
2279 requisition->height += widget->style->klass->ythickness * 2 +
2280 GTK_CONTAINER (widget)->border_width * 2;
2284 gtk_clist_size_allocate (GtkWidget * widget,
2285 GtkAllocation * allocation)
2288 GtkAllocation clist_allocation;
2289 GtkAllocation child_allocation;
2290 gint i, vscrollbar_vis, hscrollbar_vis;
2292 g_return_if_fail (widget != NULL);
2293 g_return_if_fail (GTK_IS_CLIST (widget));
2294 g_return_if_fail (allocation != NULL);
2296 clist = GTK_CLIST (widget);
2297 widget->allocation = *allocation;
2299 if (GTK_WIDGET_REALIZED (widget))
2301 gdk_window_move_resize (widget->window,
2302 allocation->x + GTK_CONTAINER (widget)->border_width,
2303 allocation->y + GTK_CONTAINER (widget)->border_width,
2304 allocation->width - GTK_CONTAINER (widget)->border_width * 2,
2305 allocation->height - GTK_CONTAINER (widget)->border_width * 2);
2308 /* use internal allocation structure for all the math
2309 * because it's easier than always subtracting the container
2311 clist->internal_allocation.x = 0;
2312 clist->internal_allocation.y = 0;
2313 clist->internal_allocation.width = MAX (1, allocation->width -
2314 GTK_CONTAINER (widget)->border_width * 2);
2315 clist->internal_allocation.height = MAX (1, allocation->height -
2316 GTK_CONTAINER (widget)->border_width * 2);
2318 /* allocate clist window assuming no scrollbars */
2319 clist_allocation.x = clist->internal_allocation.x + widget->style->klass->xthickness;
2320 clist_allocation.y = clist->internal_allocation.y + widget->style->klass->ythickness +
2321 clist->column_title_area.height;
2322 clist_allocation.width = MAX (1, clist->internal_allocation.width -
2323 (2 * widget->style->klass->xthickness));
2324 clist_allocation.height = MAX (1, clist->internal_allocation.height -
2325 (2 * widget->style->klass->ythickness) -
2326 clist->column_title_area.height);
2329 * here's where we decide to show/not show the scrollbars
2334 for (i = 0; i <= 1; i++)
2336 if (LIST_HEIGHT (clist) <= clist_allocation.height &&
2337 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
2343 if (!vscrollbar_vis)
2346 clist_allocation.width = MAX (1, clist_allocation.width -
2347 (clist->vscrollbar->requisition.width +
2348 SCROLLBAR_SPACING (clist)));
2352 if (LIST_WIDTH (clist) <= clist_allocation.width &&
2353 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
2359 if (!hscrollbar_vis)
2362 clist_allocation.height = MAX (1, clist_allocation.height -
2363 (clist->hscrollbar->requisition.height +
2364 SCROLLBAR_SPACING (clist)));
2369 clist->clist_window_width = clist_allocation.width;
2370 clist->clist_window_height = clist_allocation.height;
2372 if (GTK_WIDGET_REALIZED (widget))
2374 gdk_window_move_resize (clist->clist_window,
2377 clist_allocation.width,
2378 clist_allocation.height);
2381 /* position the window which holds the column title buttons */
2382 clist->column_title_area.x = widget->style->klass->xthickness;
2383 clist->column_title_area.y = widget->style->klass->ythickness;
2384 clist->column_title_area.width = clist_allocation.width;
2386 if (GTK_WIDGET_REALIZED (widget))
2388 gdk_window_move_resize (clist->title_window,
2389 clist->column_title_area.x,
2390 clist->column_title_area.y,
2391 clist->column_title_area.width,
2392 clist->column_title_area.height);
2395 /* column button allocation */
2396 size_allocate_columns (clist);
2398 if (GTK_WIDGET_REALIZED (widget))
2399 size_allocate_title_buttons (clist);
2401 adjust_scrollbars (clist);
2403 /* allocate the vscrollbar */
2406 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
2407 gtk_widget_show (clist->vscrollbar);
2409 child_allocation.x = clist->internal_allocation.x +
2410 clist->internal_allocation.width -
2411 clist->vscrollbar->requisition.width;
2412 child_allocation.y = clist->internal_allocation.y;
2413 child_allocation.width = clist->vscrollbar->requisition.width;
2414 child_allocation.height = MAX (1, clist->internal_allocation.height -
2415 (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0));
2417 gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
2421 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
2422 gtk_widget_hide (clist->vscrollbar);
2427 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
2428 gtk_widget_show (clist->hscrollbar);
2430 child_allocation.x = clist->internal_allocation.x;
2431 child_allocation.y = clist->internal_allocation.y +
2432 clist->internal_allocation.height -
2433 clist->hscrollbar->requisition.height;
2434 child_allocation.width = MAX (1, clist->internal_allocation.width -
2435 (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0));
2436 child_allocation.height = clist->hscrollbar->requisition.height;
2438 gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
2442 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
2443 gtk_widget_hide (clist->hscrollbar);
2446 /* set the vscrollbar adjustments */
2447 adjust_scrollbars (clist);
2455 gtk_clist_foreach (GtkContainer * container,
2456 GtkCallback callback,
2457 gpointer callback_data)
2462 g_return_if_fail (container != NULL);
2463 g_return_if_fail (GTK_IS_CLIST (container));
2464 g_return_if_fail (callback != NULL);
2466 clist = GTK_CLIST (container);
2468 /* callback for the column buttons */
2469 for (i = 0; i < clist->columns; i++)
2470 if (clist->column[i].button)
2471 (*callback) (clist->column[i].button, callback_data);
2473 /* callbacks for the scrollbars */
2474 if (clist->vscrollbar)
2475 (*callback) (clist->vscrollbar, callback_data);
2476 if (clist->hscrollbar)
2477 (*callback) (clist->hscrollbar, callback_data);
2486 draw_row (GtkCList * clist,
2487 GdkRectangle * area,
2489 GtkCListRow * clist_row)
2492 GdkGC *fg_gc, *bg_gc;
2493 GdkRectangle row_rectangle, cell_rectangle, clip_rectangle, intersect_rectangle,
2495 gint i, offset = 0, width, height, pixmap_width = 0;
2496 gint xsrc, ysrc, xdest, ydest;
2498 g_return_if_fail (clist != NULL);
2500 /* bail now if we arn't drawable yet */
2501 if (!GTK_WIDGET_DRAWABLE (clist))
2504 if (row < 0 || row >= clist->rows)
2507 widget = GTK_WIDGET (clist);
2509 /* if the function is passed the pointer to the row instead of null,
2510 * it avoids this expensive lookup */
2512 clist_row = (g_list_nth (clist->row_list, row))->data;
2514 /* rectangle of the entire row */
2515 row_rectangle.x = 0;
2516 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
2517 row_rectangle.width = clist->clist_window_width;
2518 row_rectangle.height = clist->row_height;
2520 /* rectangle of the cell spacing above the row */
2521 cell_rectangle.x = 0;
2522 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
2523 cell_rectangle.width = row_rectangle.width;
2524 cell_rectangle.height = CELL_SPACING;
2526 /* rectangle used to clip drawing operations, it's y and height
2527 * positions only need to be set once, so we set them once here.
2528 * the x and width are set withing the drawing loop below once per
2530 clip_rectangle.y = row_rectangle.y;
2531 clip_rectangle.height = row_rectangle.height;
2533 /* select GC for background rectangle */
2534 if (clist_row->state == GTK_STATE_SELECTED)
2536 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
2537 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
2541 if (clist_row->fg_set)
2543 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
2544 fg_gc = clist->fg_gc;
2547 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
2549 if (clist_row->bg_set)
2551 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
2552 bg_gc = clist->bg_gc;
2555 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
2558 /* draw the cell borders and background */
2561 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2562 gdk_draw_rectangle (clist->clist_window,
2563 widget->style->base_gc[GTK_STATE_NORMAL],
2565 intersect_rectangle.x,
2566 intersect_rectangle.y,
2567 intersect_rectangle.width,
2568 intersect_rectangle.height);
2570 /* the last row has to clear it's bottom cell spacing too */
2571 if (clist_row == clist->row_list_end->data)
2573 cell_rectangle.y += clist->row_height + CELL_SPACING;
2575 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
2576 gdk_draw_rectangle (clist->clist_window,
2577 widget->style->base_gc[GTK_STATE_NORMAL],
2579 intersect_rectangle.x,
2580 intersect_rectangle.y,
2581 intersect_rectangle.width,
2582 intersect_rectangle.height);
2585 if (!gdk_rectangle_intersect (area, &row_rectangle, &intersect_rectangle))
2588 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
2589 gdk_draw_rectangle (clist->clist_window,
2592 intersect_rectangle.x,
2593 intersect_rectangle.y,
2594 intersect_rectangle.width,
2595 intersect_rectangle.height);
2597 gdk_window_clear_area (clist->clist_window,
2598 intersect_rectangle.x,
2599 intersect_rectangle.y,
2600 intersect_rectangle.width,
2601 intersect_rectangle.height);
2605 gdk_draw_rectangle (clist->clist_window,
2606 widget->style->base_gc[GTK_STATE_NORMAL],
2610 cell_rectangle.width,
2611 cell_rectangle.height);
2613 /* the last row has to clear it's bottom cell spacing too */
2614 if (clist_row == clist->row_list_end->data)
2616 cell_rectangle.y += clist->row_height + CELL_SPACING;
2618 gdk_draw_rectangle (clist->clist_window,
2619 widget->style->base_gc[GTK_STATE_NORMAL],
2623 cell_rectangle.width,
2624 cell_rectangle.height);
2627 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
2628 gdk_draw_rectangle (clist->clist_window,
2633 row_rectangle.width,
2634 row_rectangle.height);
2636 gdk_window_clear_area (clist->clist_window,
2639 row_rectangle.width,
2640 row_rectangle.height);
2643 /* iterate and draw all the columns (row cells) and draw their contents */
2644 for (i = 0; i < clist->columns; i++)
2646 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
2647 clip_rectangle.width = clist->column[i].area.width;
2649 /* calculate clipping region clipping region */
2652 rect = &clip_rectangle;
2656 if (!gdk_rectangle_intersect (area, &clip_rectangle,
2657 &intersect_rectangle))
2659 rect = &intersect_rectangle;
2662 /* calculate real width for column justification */
2663 switch (clist_row->cell[i].type)
2665 case GTK_CELL_EMPTY:
2670 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2671 GTK_CELL_TEXT (clist_row->cell[i])->text);
2674 case GTK_CELL_PIXMAP:
2675 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
2676 pixmap_width = width;
2679 case GTK_CELL_PIXTEXT:
2680 gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap, &width, &height);
2681 pixmap_width = width;
2682 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2683 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2684 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2687 case GTK_CELL_WIDGET:
2697 switch (clist->column[i].justification)
2699 case GTK_JUSTIFY_LEFT:
2700 offset = clip_rectangle.x;
2703 case GTK_JUSTIFY_RIGHT:
2704 offset = (clip_rectangle.x + clip_rectangle.width) - width;
2707 case GTK_JUSTIFY_CENTER:
2708 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2711 case GTK_JUSTIFY_FILL:
2712 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
2720 /* Draw Text or Pixmap */
2721 switch (clist_row->cell[i].type)
2723 case GTK_CELL_EMPTY:
2728 gdk_gc_set_clip_rectangle (fg_gc, rect);
2730 gdk_draw_string (clist->clist_window,
2731 widget->style->font,
2733 offset + clist_row->cell[i].horizontal,
2734 row_rectangle.y + clist->row_center_offset +
2735 clist_row->cell[i].vertical,
2736 GTK_CELL_TEXT (clist_row->cell[i])->text);
2738 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2741 case GTK_CELL_PIXMAP:
2744 xdest = offset + clist_row->cell[i].horizontal;
2745 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2746 clist_row->cell[i].vertical;
2748 if (xdest < clip_rectangle.x)
2750 xsrc = clip_rectangle.x - xdest;
2751 pixmap_width -= xsrc;
2752 xdest = clip_rectangle.x;
2755 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
2756 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
2758 if (ydest < clip_rectangle.y)
2760 ysrc = clip_rectangle.y - ydest;
2762 ydest = clip_rectangle.y;
2765 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2766 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2768 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2770 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
2771 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2773 gdk_draw_pixmap (clist->clist_window,
2775 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2778 pixmap_width, height);
2780 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2782 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2783 gdk_gc_set_clip_mask (fg_gc, NULL);
2787 case GTK_CELL_PIXTEXT:
2788 /* draw the pixmap */
2791 xdest = offset + clist_row->cell[i].horizontal;
2792 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
2793 clist_row->cell[i].vertical;
2795 if (xdest < clip_rectangle.x)
2797 xsrc = clip_rectangle.x - xdest;
2798 pixmap_width -= xsrc;
2799 xdest = clip_rectangle.x;
2802 if (xdest + pixmap_width > clip_rectangle.x + clip_rectangle.width)
2803 pixmap_width = (clip_rectangle.x + clip_rectangle.width) - xdest;
2805 if (ydest < clip_rectangle.y)
2807 ysrc = clip_rectangle.y - ydest;
2809 ydest = clip_rectangle.y;
2812 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2813 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2815 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2817 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
2818 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2821 gdk_draw_pixmap (clist->clist_window,
2823 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2827 pixmap_width, height);
2829 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2831 offset += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2833 /* draw the string */
2834 gdk_gc_set_clip_rectangle (fg_gc, rect);
2836 gdk_draw_string (clist->clist_window,
2837 widget->style->font,
2839 offset + clist_row->cell[i].horizontal,
2840 row_rectangle.y + clist->row_center_offset +
2841 clist_row->cell[i].vertical,
2842 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2844 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2847 case GTK_CELL_WIDGET:
2860 draw_rows (GtkCList * clist,
2861 GdkRectangle * area)
2864 GtkCListRow *clist_row;
2865 int i, first_row, last_row;
2867 g_return_if_fail (clist != NULL);
2868 g_return_if_fail (GTK_IS_CLIST (clist));
2870 if (clist->row_height == 0 ||
2871 !GTK_WIDGET_DRAWABLE (clist))
2876 first_row = ROW_FROM_YPIXEL (clist, area->y);
2877 last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
2881 first_row = ROW_FROM_YPIXEL (clist, 0);
2882 last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
2885 /* this is a small special case which exposes the bottom cell line
2886 * on the last row -- it might go away if I change the wall the cell spacings
2888 if (clist->rows == first_row)
2891 list = g_list_nth (clist->row_list, first_row);
2895 clist_row = list->data;
2901 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
2902 (clist, area, i, clist_row);
2907 gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
2912 * size_allocate_title_buttons
2913 * size_allocate_columns
2916 size_allocate_title_buttons (GtkCList * clist)
2918 gint i, last_button = 0;
2919 GtkAllocation button_allocation;
2921 if (!GTK_WIDGET_REALIZED (clist))
2924 button_allocation.x = clist->hoffset;
2925 button_allocation.y = 0;
2926 button_allocation.width = 0;
2927 button_allocation.height = clist->column_title_area.height;
2929 for (i = 0; i < clist->columns; i++)
2931 button_allocation.width += clist->column[i].area.width;
2933 if (i == clist->columns - 1)
2934 button_allocation.width += 2 * (CELL_SPACING + COLUMN_INSET);
2936 button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
2938 if (i == (clist->columns - 1) || clist->column[i + 1].button)
2940 gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
2941 button_allocation.x += button_allocation.width;
2942 button_allocation.width = 0;
2944 gdk_window_show (clist->column[last_button].window);
2945 gdk_window_move_resize (clist->column[last_button].window,
2946 button_allocation.x - (DRAG_WIDTH / 2),
2947 0, DRAG_WIDTH, clist->column_title_area.height);
2949 last_button = i + 1;
2953 gdk_window_hide (clist->column[i].window);
2959 size_allocate_columns (GtkCList * clist)
2961 gint i, xoffset = 0;
2963 for (i = 0; i < clist->columns; i++)
2965 clist->column[i].area.x = xoffset + CELL_SPACING + COLUMN_INSET;
2967 if (i == clist->columns - 1)
2971 if (clist->column[i].width_set)
2973 width = clist->column[i].width;
2977 if (clist->column[i].title)
2978 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
2979 clist->column[i].title);
2984 clist->column[i].area.width = MAX (width,
2985 clist->clist_window_width -
2986 xoffset - (2 * (CELL_SPACING + COLUMN_INSET)));
2991 clist->column[i].area.width = clist->column[i].width;
2994 xoffset += clist->column[i].area.width + CELL_SPACING + (2 * COLUMN_INSET);
3003 * get_selection_info
3006 toggle_row (GtkCList * clist,
3009 GdkEventButton * event)
3013 GtkCListRow *clist_row, *selected_row;
3016 list = clist->row_list;
3017 selected_row = NULL;
3019 switch (clist->selection_mode)
3021 case GTK_SELECTION_SINGLE:
3024 clist_row = list->data;
3028 selected_row = clist_row;
3029 else if (clist_row->state == GTK_STATE_SELECTED)
3030 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3036 if (selected_row && selected_row->state == GTK_STATE_SELECTED)
3037 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3038 row, column, event);
3040 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3041 row, column, event);
3045 case GTK_SELECTION_BROWSE:
3048 clist_row = list->data;
3051 if (i != row && clist_row->state == GTK_STATE_SELECTED)
3052 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3057 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3058 row, column, event);
3062 case GTK_SELECTION_MULTIPLE:
3063 clist_row = (g_list_nth (clist->row_list, row))->data;
3065 if (clist_row->state == GTK_STATE_SELECTED)
3066 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3067 row, column, event);
3069 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3070 row, column, event);
3074 case GTK_SELECTION_EXTENDED:
3083 select_row (GtkCList * clist,
3086 GdkEventButton * event)
3090 GtkCListRow *clist_row;
3092 switch (clist->selection_mode)
3094 case GTK_SELECTION_SINGLE:
3095 case GTK_SELECTION_BROWSE:
3097 list = clist->row_list;
3100 clist_row = list->data;
3103 if (row != i && clist_row->state == GTK_STATE_SELECTED)
3104 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3110 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3111 row, column, event);
3114 case GTK_SELECTION_MULTIPLE:
3115 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
3116 row, column, event);
3120 case GTK_SELECTION_EXTENDED:
3129 unselect_row (GtkCList * clist,
3132 GdkEventButton * event)
3134 switch (clist->selection_mode)
3136 case GTK_SELECTION_SINGLE:
3137 case GTK_SELECTION_BROWSE:
3138 case GTK_SELECTION_MULTIPLE:
3139 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
3140 row, column, event);
3143 case GTK_SELECTION_EXTENDED:
3152 real_select_row (GtkCList * clist,
3155 GdkEventButton * event)
3157 GtkCListRow *clist_row;
3159 g_return_if_fail (clist != NULL);
3161 if (row < 0 || row > (clist->rows - 1))
3164 clist_row = (g_list_nth (clist->row_list, row))->data;
3166 if (clist_row->state == GTK_STATE_NORMAL)
3168 clist_row->state = GTK_STATE_SELECTED;
3169 clist->selection = g_list_append (clist->selection, GINT_TO_POINTER (row));
3171 if (!GTK_CLIST_FROZEN (clist)
3172 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3173 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
3174 (clist, NULL, row, clist_row);
3179 real_unselect_row (GtkCList * clist,
3182 GdkEventButton * event)
3184 GtkCListRow *clist_row;
3186 g_return_if_fail (clist != NULL);
3188 if (row < 0 || row > (clist->rows - 1))
3191 clist_row = (g_list_nth (clist->row_list, row))->data;
3193 if (clist_row->state == GTK_STATE_SELECTED)
3195 clist_row->state = GTK_STATE_NORMAL;
3196 clist->selection = g_list_remove (clist->selection, GINT_TO_POINTER (row));
3198 if (!GTK_CLIST_FROZEN (clist)
3199 && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
3200 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
3201 (clist, NULL, row, clist_row);
3206 get_selection_info (GtkCList * clist,
3214 g_return_val_if_fail (clist != NULL, 0);
3216 /* bounds checking, return false if the user clicked
3217 * on a blank area */
3218 trow = ROW_FROM_YPIXEL (clist, y);
3219 if (trow >= clist->rows)
3225 tcol = COLUMN_FROM_XPIXEL (clist, x);
3226 if (tcol >= clist->columns)
3236 gtk_clist_get_selection_info (GtkCList *clist,
3242 g_return_val_if_fail (clist != NULL, 0);
3243 g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
3244 return get_selection_info (clist, x, y, row, column);
3254 draw_xor_line (GtkCList * clist)
3258 g_return_if_fail (clist != NULL);
3260 widget = GTK_WIDGET (clist);
3262 gdk_draw_line (widget->window, clist->xor_gc,
3264 widget->style->klass->ythickness,
3266 clist->column_title_area.height + clist->clist_window_height + 1);
3269 /* this function returns the new width of the column being resized given
3270 * the column and x position of the cursor; the x cursor position is passed
3271 * in as a pointer and automagicly corrected if it's beyond min/max limits */
3273 new_column_width (GtkCList * clist,
3282 /* first translate the x position from widget->window
3283 * to clist->clist_window */
3284 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3286 /* rx is x from the list beginning */
3287 rx = cx - clist->hoffset;
3289 /* you can't shrink a column to less than its minimum width */
3290 if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
3292 *x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
3293 GTK_WIDGET (clist)->style->klass->xthickness;
3294 cx -= GTK_WIDGET (clist)->style->klass->xthickness;
3295 rx = cx - clist->hoffset;
3298 if (cx > clist->clist_window_width)
3303 /* calculate new column width making sure it doesn't end up
3304 * less than the minimum width */
3305 width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET -
3306 ((clist->columns == (column - 1)) ? CELL_SPACING : 0);
3307 if (width < COLUMN_MIN_WIDTH)
3308 width = COLUMN_MIN_WIDTH;
3313 /* this will do more later */
3315 resize_column (GtkCList * clist,
3319 gtk_clist_set_column_width (clist, column, width);
3324 column_button_create (GtkCList * clist,
3329 button = clist->column[column].button = gtk_button_new ();
3330 gtk_widget_set_parent (button, GTK_WIDGET (clist));
3331 if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
3332 gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
3334 gtk_signal_connect (GTK_OBJECT (button),
3336 (GtkSignalFunc) column_button_clicked,
3339 gtk_widget_show (button);
3343 column_button_clicked (GtkWidget * widget,
3349 g_return_if_fail (widget != NULL);
3350 g_return_if_fail (GTK_IS_CLIST (data));
3352 clist = GTK_CLIST (data);
3354 /* find the column who's button was pressed */
3355 for (i = 0; i < clist->columns; i++)
3356 if (clist->column[i].button == widget)
3359 gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
3368 * vadjustment_changed
3369 * hadjustment_changed
3370 * vadjustment_value_changed
3371 * hadjustment_value_changed
3374 create_scrollbars (GtkCList * clist)
3376 GtkAdjustment *adjustment;
3378 clist->vscrollbar = gtk_vscrollbar_new (NULL);
3379 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
3381 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3382 (GtkSignalFunc) vadjustment_changed,
3385 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3386 (GtkSignalFunc) vadjustment_value_changed,
3389 gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
3390 gtk_widget_show (clist->vscrollbar);
3392 clist->hscrollbar = gtk_hscrollbar_new (NULL);
3393 adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
3395 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
3396 (GtkSignalFunc) hadjustment_changed,
3399 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
3400 (GtkSignalFunc) hadjustment_value_changed,
3403 gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
3404 gtk_widget_show (clist->hscrollbar);
3408 adjust_scrollbars (GtkCList * clist)
3410 GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
3411 GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
3412 GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
3413 GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
3414 GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
3416 if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
3418 GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) -
3419 clist->clist_window_height);
3420 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment),
3424 GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
3425 GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
3426 GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
3427 GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
3428 GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
3430 if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
3432 GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) -
3433 clist->clist_window_width);
3434 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment),
3438 if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
3439 clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
3441 if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
3443 gtk_widget_hide (clist->vscrollbar);
3444 gtk_widget_queue_resize (GTK_WIDGET (clist));
3449 if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
3451 gtk_widget_show (clist->vscrollbar);
3452 gtk_widget_queue_resize (GTK_WIDGET (clist));
3456 if (LIST_WIDTH (clist) <= clist->clist_window_width &&
3457 clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
3459 if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
3461 gtk_widget_hide (clist->hscrollbar);
3462 gtk_widget_queue_resize (GTK_WIDGET (clist));
3467 if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
3469 gtk_widget_show (clist->hscrollbar);
3470 gtk_widget_queue_resize (GTK_WIDGET (clist));
3474 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
3475 gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
3479 vadjustment_changed (GtkAdjustment * adjustment,
3484 g_return_if_fail (adjustment != NULL);
3485 g_return_if_fail (data != NULL);
3487 clist = GTK_CLIST (data);
3491 hadjustment_changed (GtkAdjustment * adjustment,
3496 g_return_if_fail (adjustment != NULL);
3497 g_return_if_fail (data != NULL);
3499 clist = GTK_CLIST (data);
3503 check_exposures (GtkCList *clist)
3507 if (!GTK_WIDGET_REALIZED (clist))
3510 /* Make sure graphics expose events are processed before scrolling
3512 while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
3514 gtk_widget_event (GTK_WIDGET (clist), event);
3515 if (event->expose.count == 0)
3517 gdk_event_free (event);
3520 gdk_event_free (event);
3525 vadjustment_value_changed (GtkAdjustment * adjustment,
3532 g_return_if_fail (adjustment != NULL);
3533 g_return_if_fail (data != NULL);
3534 g_return_if_fail (GTK_IS_CLIST (data));
3536 clist = GTK_CLIST (data);
3538 if (!GTK_WIDGET_DRAWABLE (clist))
3541 value = adjustment->value;
3543 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
3545 if (value > -clist->voffset)
3548 diff = value + clist->voffset;
3550 /* we have to re-draw the whole screen here... */
3551 if (diff >= clist->clist_window_height)
3553 clist->voffset = -value;
3554 draw_rows (clist, NULL);
3558 if ((diff != 0) && (diff != clist->clist_window_height))
3559 gdk_window_copy_area (clist->clist_window,
3562 clist->clist_window,
3565 clist->clist_window_width,
3566 clist->clist_window_height - diff);
3569 area.y = clist->clist_window_height - diff;
3570 area.width = clist->clist_window_width;
3576 diff = -clist->voffset - value;
3578 /* we have to re-draw the whole screen here... */
3579 if (diff >= clist->clist_window_height)
3581 clist->voffset = -value;
3582 draw_rows (clist, NULL);
3586 if ((diff != 0) && (diff != clist->clist_window_height))
3587 gdk_window_copy_area (clist->clist_window,
3590 clist->clist_window,
3593 clist->clist_window_width,
3594 clist->clist_window_height - diff);
3598 area.width = clist->clist_window_width;
3603 clist->voffset = -value;
3604 if ((diff != 0) && (diff != clist->clist_window_height))
3605 check_exposures (clist);
3608 draw_rows (clist, &area);
3612 hadjustment_value_changed (GtkAdjustment * adjustment,
3617 gint i, diff, value;
3619 g_return_if_fail (adjustment != NULL);
3620 g_return_if_fail (data != NULL);
3621 g_return_if_fail (GTK_IS_CLIST (data));
3623 clist = GTK_CLIST (data);
3625 if (!GTK_WIDGET_DRAWABLE (clist))
3628 value = adjustment->value;
3630 if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
3632 /* move the column buttons and resize windows */
3633 for (i = 0; i < clist->columns; i++)
3635 if (clist->column[i].button)
3637 clist->column[i].button->allocation.x -= value + clist->hoffset;
3639 if (clist->column[i].button->window)
3641 gdk_window_move (clist->column[i].button->window,
3642 clist->column[i].button->allocation.x,
3643 clist->column[i].button->allocation.y);
3645 if (clist->column[i].window)
3646 gdk_window_move (clist->column[i].window,
3647 clist->column[i].button->allocation.x +
3648 clist->column[i].button->allocation.width -
3649 (DRAG_WIDTH / 2), 0);
3654 if (value > -clist->hoffset)
3657 diff = value + clist->hoffset;
3659 /* we have to re-draw the whole screen here... */
3660 if (diff >= clist->clist_window_width)
3662 clist->hoffset = -value;
3663 draw_rows (clist, NULL);
3667 if ((diff != 0) && (diff != clist->clist_window_width))
3668 gdk_window_copy_area (clist->clist_window,
3671 clist->clist_window,
3674 clist->clist_window_width - diff,
3675 clist->clist_window_height);
3677 area.x = clist->clist_window_width - diff;
3680 area.height = clist->clist_window_height;
3685 diff = -clist->hoffset - value;
3687 /* we have to re-draw the whole screen here... */
3688 if (diff >= clist->clist_window_width)
3690 clist->hoffset = -value;
3691 draw_rows (clist, NULL);
3695 if ((diff != 0) && (diff != clist->clist_window_width))
3696 gdk_window_copy_area (clist->clist_window,
3699 clist->clist_window,
3702 clist->clist_window_width - diff,
3703 clist->clist_window_height);
3708 area.height = clist->clist_window_height;
3711 clist->hoffset = -value;
3712 if ((diff != 0) && (diff != clist->clist_window_width))
3713 check_exposures (clist);
3716 draw_rows (clist, &area);
3720 * Memory Allocation/Distruction Routines for GtkCList stuctures
3732 static GtkCListColumn *
3733 columns_new (GtkCList * clist)
3736 GtkCListColumn *column;
3738 column = g_new (GtkCListColumn, clist->columns);
3740 for (i = 0; i < clist->columns; i++)
3742 column[i].area.x = 0;
3743 column[i].area.y = 0;
3744 column[i].area.width = 0;
3745 column[i].area.height = 0;
3746 column[i].title = NULL;
3747 column[i].button = NULL;
3748 column[i].window = NULL;
3749 column[i].width = 0;
3750 column[i].width_set = FALSE;
3751 column[i].justification = GTK_JUSTIFY_LEFT;
3758 column_title_new (GtkCList * clist,
3762 if (clist->column[column].title)
3763 g_free (clist->column[column].title);
3765 clist->column[column].title = g_strdup (title);
3769 columns_delete (GtkCList * clist)
3773 for (i = 0; i < clist->columns; i++)
3774 if (clist->column[i].title)
3775 g_free (clist->column[i].title);
3777 g_free (clist->column);
3780 static GtkCListRow *
3781 row_new (GtkCList * clist)
3784 GtkCListRow *clist_row;
3786 clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
3787 clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3789 for (i = 0; i < clist->columns; i++)
3791 clist_row->cell[i].type = GTK_CELL_EMPTY;
3792 clist_row->cell[i].vertical = 0;
3793 clist_row->cell[i].horizontal = 0;
3796 clist_row->fg_set = FALSE;
3797 clist_row->bg_set = FALSE;
3798 clist_row->state = GTK_STATE_NORMAL;
3799 clist_row->data = NULL;
3800 clist_row->destroy = NULL;
3806 row_delete (GtkCList * clist,
3807 GtkCListRow * clist_row)
3811 for (i = 0; i < clist->columns; i++)
3812 cell_empty (clist, clist_row, i);
3814 if (clist_row->destroy)
3815 clist_row->destroy (clist_row->data);
3817 g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
3818 g_mem_chunk_free (clist->row_mem_chunk, clist_row);
3822 cell_empty (GtkCList * clist,
3823 GtkCListRow * clist_row,
3826 switch (clist_row->cell[column].type)
3828 case GTK_CELL_EMPTY:
3832 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3835 case GTK_CELL_PIXMAP:
3836 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3837 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3838 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3841 case GTK_CELL_PIXTEXT:
3842 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3843 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3844 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3845 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3848 case GTK_CELL_WIDGET:
3856 clist_row->cell[column].type = GTK_CELL_EMPTY;
3860 cell_set_text (GtkCList * clist,
3861 GtkCListRow * clist_row,
3865 cell_empty (clist, clist_row, column);
3869 clist_row->cell[column].type = GTK_CELL_TEXT;
3870 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3875 cell_set_pixmap (GtkCList * clist,
3876 GtkCListRow * clist_row,
3881 cell_empty (clist, clist_row, column);
3885 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3886 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3887 /* We set the mask even if it is NULL */
3888 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3893 cell_set_pixtext (GtkCList * clist,
3894 GtkCListRow * clist_row,
3901 cell_empty (clist, clist_row, column);
3905 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3906 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3907 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3908 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3909 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3913 /* Fill in data after widget has correct style */
3916 add_style_data (GtkCList * clist)
3920 widget = GTK_WIDGET(clist);
3922 /* text properties */
3923 if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
3925 clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
3926 clist->row_center_offset = widget->style->font->ascent + 1.5;
3931 text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
3932 GTK_WIDGET (clist) ->style->font->descent + 1);
3933 clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;