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 * GtkCTree widget for GTK+
6 * Copyright (C) 1998 Lars Hamann and Stefan Jeske
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
29 #define CELL_SPACING 1
30 #define CLIST_OPTIMUM_SIZE 512
32 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
33 (((row) + 1) * CELL_SPACING) + \
35 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
36 ((clist)->row_height + CELL_SPACING))
37 #define COLUMN_LEFT_XPIXEL(clist, col) ((clist)->column[(col)].area.x \
40 static void gtk_ctree_class_init (GtkCTreeClass *klass);
41 static void gtk_ctree_init (GtkCTree *ctree);
42 static void gtk_ctree_destroy (GtkObject *object);
44 static gint gtk_ctree_button_press (GtkWidget *widget,
45 GdkEventButton *event);
46 static gint gtk_ctree_button_release (GtkWidget *widget,
47 GdkEventButton *event);
48 static gint gtk_ctree_button_motion (GtkWidget *widget,
49 GdkEventMotion *event);
50 static void gtk_ctree_realize (GtkWidget *widget);
51 static void gtk_ctree_unrealize (GtkWidget *widget);
53 static void create_xor_gc (GtkCTree *ctree);
54 static void draw_xor_line (GtkCTree *ctree);
55 static void draw_xor_rect (GtkCTree *ctree);
56 static void create_drag_icon (GtkCTree *ctree,
58 static void draw_row (GtkCList *clist,
61 GtkCListRow *clist_row);
62 static void tree_draw_row (GtkCTree *ctree,
64 static void cell_empty (GtkCList *clist,
65 GtkCListRow *clist_row,
67 static void cell_set_text (GtkCList *clist,
68 GtkCListRow *clist_row,
71 static void cell_set_pixmap (GtkCList *clist,
72 GtkCListRow *clist_row,
76 static void cell_set_pixtext (GtkCList *clist,
77 GtkCListRow *clist_row,
83 static void set_node_info (GtkCTree *ctree,
87 GdkPixmap *pixmap_closed,
88 GdkBitmap *mask_closed,
89 GdkPixmap *pixmap_opened,
90 GdkBitmap *mask_opened,
94 static GtkCTreeRow *row_new (GtkCTree *ctree);
95 static void row_delete (GtkCTree *ctree,
96 GtkCTreeRow *ctree_row);
97 static void tree_delete (GtkCTree *ctree,
100 static void tree_delete_raw (GtkCTree *ctree,
103 static void tree_update_level (GtkCTree *ctree,
106 static void tree_select (GtkCTree *ctree,
109 static void tree_unselect (GtkCTree *ctree,
112 static void tree_expand (GtkCTree *ctree,
115 static void tree_collapse (GtkCTree *ctree,
118 static void real_select_row (GtkCTree *ctree,
121 static void real_unselect_row (GtkCTree *ctree,
124 static void tree_toggle_row (GtkCTree *ctree,
127 static void real_tree_expand (GtkCTree *ctree,
129 static void real_tree_collapse (GtkCTree *ctree,
131 static void real_tree_move (GtkCTree *ctree,
135 static void gtk_ctree_link (GtkCTree *ctree,
139 static void gtk_ctree_unlink (GtkCTree *ctree,
141 static GList * gtk_ctree_last_visible (GtkCTree *ctree,
143 static void gtk_ctree_marshal_signal_1 (GtkObject *object,
147 static void gtk_ctree_marshal_signal_2 (GtkObject *object,
151 static void gtk_ctree_marshal_signal_3 (GtkObject *object,
155 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
160 static void tree_sort (GtkCTree *ctree,
164 static gint default_compare (GtkCTree *ctree,
178 typedef void (*GtkCTreeSignal1) (GtkObject *object,
182 typedef void (*GtkCTreeSignal2) (GtkObject *object,
187 typedef void (*GtkCTreeSignal3) (GtkObject *object,
192 static GtkCListClass *parent_class = NULL;
193 static GtkContainerClass *container_class = NULL;
194 static guint ctree_signals[LAST_SIGNAL] = {0};
199 gtk_ctree_get_type ()
201 static GtkType ctree_type = 0;
205 GtkTypeInfo ctree_info =
209 sizeof (GtkCTreeClass),
210 (GtkClassInitFunc) gtk_ctree_class_init,
211 (GtkObjectInitFunc) gtk_ctree_init,
212 (GtkArgSetFunc) NULL,
213 (GtkArgGetFunc) NULL,
216 ctree_type = gtk_type_unique (gtk_clist_get_type (), &ctree_info);
223 gtk_ctree_marshal_signal_1 (GtkObject *object,
228 GtkCTreeSignal1 rfunc;
230 rfunc = (GtkCTreeSignal1) func;
232 (*rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
237 gtk_ctree_marshal_signal_2 (GtkObject *object,
242 GtkCTreeSignal2 rfunc;
244 rfunc = (GtkCTreeSignal2) func;
246 (*rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_POINTER (args[1]),
247 GTK_VALUE_POINTER (args[2]), func_data);
251 gtk_ctree_marshal_signal_3 (GtkObject *object,
256 GtkCTreeSignal3 rfunc;
258 rfunc = (GtkCTreeSignal3) func;
260 (*rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
264 gtk_ctree_class_init (GtkCTreeClass *klass)
266 GtkObjectClass *object_class;
267 GtkWidgetClass *widget_class;
268 GtkCListClass *clist_class;
270 object_class = (GtkObjectClass *) klass;
271 widget_class = (GtkWidgetClass *) klass;
272 container_class = (GtkContainerClass *) klass;
273 clist_class = (GtkCListClass *) klass;
275 parent_class = gtk_type_class (gtk_clist_get_type ());
276 container_class = gtk_type_class (gtk_container_get_type ());
278 ctree_signals[TREE_SELECT_ROW] =
279 gtk_signal_new ("tree_select_row",
282 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
283 gtk_ctree_marshal_signal_1,
284 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
285 ctree_signals[TREE_UNSELECT_ROW] =
286 gtk_signal_new ("tree_unselect_row",
289 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
290 gtk_ctree_marshal_signal_1,
291 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
292 ctree_signals[TREE_EXPAND] =
293 gtk_signal_new ("tree_expand",
296 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
297 gtk_ctree_marshal_signal_3,
298 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
299 ctree_signals[TREE_COLLAPSE] =
300 gtk_signal_new ("tree_collapse",
303 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
304 gtk_ctree_marshal_signal_3,
305 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
306 ctree_signals[TREE_MOVE] =
307 gtk_signal_new ("tree_move",
310 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
311 gtk_ctree_marshal_signal_2,
312 GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER,
315 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
317 object_class->destroy = gtk_ctree_destroy;
319 widget_class->realize = gtk_ctree_realize;
320 widget_class->unrealize = gtk_ctree_unrealize;
321 widget_class->button_press_event = gtk_ctree_button_press;
322 widget_class->button_release_event = gtk_ctree_button_release;
323 widget_class->motion_notify_event = gtk_ctree_button_motion;
325 clist_class->select_row = NULL;
326 clist_class->unselect_row = NULL;
327 clist_class->click_column = NULL;
328 clist_class->draw_row = draw_row;
330 klass->tree_select_row = real_select_row;
331 klass->tree_unselect_row = real_unselect_row;
332 klass->tree_expand = real_tree_expand;
333 klass->tree_collapse = real_tree_collapse;
334 klass->tree_move = real_tree_move;
338 gtk_ctree_init (GtkCTree *ctree)
340 ctree->tree_indent = 20;
341 ctree->tree_column = 0;
342 ctree->selection_last = NULL;
343 ctree->draw_lines = TRUE;
344 ctree->line_style = GTK_CTREE_LINES_SOLID;
345 ctree->reorderable = FALSE;
346 ctree->use_icons = TRUE;
347 ctree->drag_row = -1;
348 ctree->drag_rect = FALSE;
349 ctree->xor_gc = NULL;
350 ctree->in_drag = FALSE;
351 ctree->drag_source = NULL;
352 ctree->drag_target = NULL;
353 ctree->insert_pos = GTK_CTREE_POS_AS_CHILD;
354 ctree->drag_icon = NULL;
355 ctree->auto_sort = FALSE;
356 ctree->node_compare = default_compare;
360 gtk_ctree_destroy (GtkObject *object)
365 g_return_if_fail (object != NULL);
366 g_return_if_fail (GTK_IS_CTREE (object));
368 clist = GTK_CLIST (object);
370 /* freeze the list */
371 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
373 /* get rid of all the rows */
374 gtk_ctree_clear (GTK_CTREE (object));
376 /* destroy the scrollbars */
377 if (clist->vscrollbar)
379 gtk_widget_unparent (clist->vscrollbar);
380 clist->vscrollbar = NULL;
382 if (clist->hscrollbar)
384 gtk_widget_unparent (clist->hscrollbar);
385 clist->hscrollbar = NULL;
388 /* destroy the column buttons */
389 for (i = 0; i < clist->columns; i++)
390 if (clist->column[i].button)
392 gtk_widget_unparent (clist->column[i].button);
393 clist->column[i].button = NULL;
396 if (GTK_OBJECT_CLASS (container_class)->destroy)
397 (*GTK_OBJECT_CLASS (container_class)->destroy) (object);
401 gtk_ctree_realize (GtkWidget *widget)
405 GdkGCPrivate *private;
407 ctree = GTK_CTREE (widget);
409 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
411 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
412 values.background = widget->style->bg[GTK_STATE_NORMAL];
413 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
414 values.line_style = GDK_LINE_SOLID;
415 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
422 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
424 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
425 GDK_LINE_ON_OFF_DASH, None, None);
426 private = (GdkGCPrivate *) ctree->lines_gc;
427 XSetDashes (private->xdisplay, private->xgc, 0, "\1\1", 2);
429 else if (ctree->line_style == GTK_CTREE_LINES_NONE)
430 ctree->draw_lines = FALSE;
432 if (ctree->reorderable)
433 create_xor_gc (ctree);
437 gtk_ctree_unrealize (GtkWidget *widget)
441 ctree = GTK_CTREE (widget);
443 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
445 gdk_gc_destroy (ctree->lines_gc);
447 if (ctree->reorderable)
448 gdk_gc_destroy (ctree->xor_gc);
452 gtk_ctree_button_press (GtkWidget *widget,
453 GdkEventButton *event)
458 g_return_val_if_fail (widget != NULL, FALSE);
459 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
460 g_return_val_if_fail (event != NULL, FALSE);
462 ctree = GTK_CTREE (widget);
463 clist = GTK_CLIST (widget);
465 if (event->window == clist->clist_window)
475 if (gtk_clist_get_selection_info (clist, x, y, &row, &column))
477 if (event->button == 1)
478 ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
480 work = g_list_nth (clist->row_list, row);
482 if (GTK_CTREE_ROW (work)->children &&
483 (event->type == GDK_2BUTTON_PRESS ||
484 (ctree_is_hot_spot (ctree, work, row, x, y)
485 && event->button == 1)))
487 if (GTK_CTREE_ROW (work)->expanded)
488 gtk_ctree_collapse (ctree, work);
490 gtk_ctree_expand (ctree, work);
492 else if (ctree->reorderable && event->button == 1 && !ctree->in_drag)
494 gdk_pointer_grab (event->window, FALSE,
495 GDK_POINTER_MOTION_HINT_MASK |
496 GDK_BUTTON1_MOTION_MASK |
497 GDK_BUTTON_RELEASE_MASK,
498 NULL, NULL, event->time);
499 ctree->in_drag = TRUE;
500 ctree->drag_source = work;
501 ctree->drag_target = NULL;
508 (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
512 gtk_ctree_button_motion (GtkWidget *widget,
513 GdkEventMotion *event)
520 gint insert_pos = GTK_CTREE_POS_AS_CHILD;
522 g_return_val_if_fail (widget != NULL, FALSE);
523 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
524 g_return_val_if_fail (event != NULL, FALSE);
526 ctree = GTK_CTREE (widget);
527 clist = GTK_CLIST (widget);
529 if (!ctree->reorderable)
531 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
533 if (event->window == clist->clist_window && ctree->in_drag)
535 GdkModifierType modmask;
542 gdk_window_get_pointer (event->window, &x, &y, NULL);
544 /* delayed drag start */
545 if (!ctree->drag_target &&
546 y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
547 y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
549 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
552 if (ctree->use_icons)
554 if (!ctree->drag_icon)
555 create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
558 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
559 gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
560 root_y - ctree->icon_height);
564 /* out of bounds check */
565 if (x < 0 || y < -3 || x > clist->clist_window_width ||
566 y > clist->clist_window_height + 3 ||
567 y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
569 if (ctree->drag_row >= 0)
571 if (ctree->drag_rect)
573 draw_xor_rect (ctree);
574 ctree->drag_rect = FALSE;
577 draw_xor_line (ctree);
578 ctree->drag_row = -1;
581 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
585 row = ROW_FROM_YPIXEL (clist, y);
587 /* re-calculate target */
588 if (ctree->drag_target && ctree->drag_row == -1)
589 ctree->drag_target = g_list_nth (clist->row_list, row);
591 if (y < 0 || y > clist->clist_window_height ||
592 ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
593 || row >= clist->rows)
594 return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
597 if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
598 insert_pos = GTK_CTREE_POS_BEFORE;
599 else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y
600 < clist->row_height / 4)
601 insert_pos = GTK_CTREE_POS_AFTER;
603 if (row != ctree->drag_row ||
604 (row == ctree->drag_row && ctree->insert_pos != insert_pos))
606 if (insert_pos != GTK_CTREE_POS_AS_CHILD)
608 if (ctree->drag_row >= 0)
610 if (ctree->drag_rect)
612 draw_xor_rect (ctree);
613 ctree->drag_rect = FALSE;
616 draw_xor_line (ctree);
618 ctree->insert_pos = insert_pos;
619 ctree->drag_target = g_list_nth (clist->row_list, row);
620 ctree->drag_row = row;
621 draw_xor_line (ctree);
623 else if (ctree->drag_target &&
624 !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
626 if (ctree->drag_row >= 0)
628 if (ctree->drag_rect)
629 draw_xor_rect (ctree);
631 draw_xor_line (ctree);
633 ctree->drag_rect = TRUE;
634 ctree->insert_pos = insert_pos;
635 ctree->drag_target = g_list_nth (clist->row_list, row);
636 ctree->drag_row = row;
637 draw_xor_rect (ctree);
643 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
647 gtk_ctree_button_release (GtkWidget *widget,
648 GdkEventButton *event)
653 g_return_val_if_fail (widget != NULL, FALSE);
654 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
655 g_return_val_if_fail (event != NULL, FALSE);
657 ctree = GTK_CTREE (widget);
658 clist = GTK_CLIST (widget);
660 if (event->button == 1)
662 gdk_pointer_ungrab (event->time);
663 ctree->in_drag = FALSE;
665 if (ctree->use_icons && ctree->drag_icon)
667 gdk_window_destroy (ctree->drag_icon);
668 ctree->drag_icon = NULL;
671 if (ctree->drag_row >= 0)
673 if (ctree->drag_rect)
675 draw_xor_rect (ctree);
676 ctree->drag_rect = FALSE;
679 draw_xor_line (ctree);
680 ctree->drag_row = -1;
684 if (event->window == clist->clist_window)
690 if (gtk_clist_get_selection_info (clist, event->x, event->y,
692 if (row == - (ctree->drag_row + 1) &&
693 (work = g_list_nth (clist->row_list, row)))
695 if (GTK_CTREE_ROW (work)->children &&
696 ctree_is_hot_spot (ctree, work, row, event->x,
698 return (* GTK_WIDGET_CLASS (parent_class)
699 ->button_release_event) (widget, event);
700 tree_toggle_row (ctree, work, column);
705 (* GTK_WIDGET_CLASS (parent_class)->button_release_event)
709 /* nop if out of bounds / source = target */
710 if (event->x < 0 || event->y < -3 ||
711 event->x > clist->clist_window_width ||
712 event->y > clist->clist_window_height + 3 ||
713 ctree->drag_target == ctree->drag_source)
715 (* GTK_WIDGET_CLASS (parent_class)->button_release_event)
718 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
719 !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
722 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
724 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
726 gtk_signal_emit (GTK_OBJECT (ctree),
727 ctree_signals[TREE_MOVE],
729 GTK_CTREE_ROW (ctree->drag_target)->parent,
730 GTK_CTREE_ROW (ctree->drag_target)->sibling);
732 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
734 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
736 gtk_signal_emit (GTK_OBJECT (ctree),
737 ctree_signals[TREE_MOVE],
739 GTK_CTREE_ROW (ctree->drag_target)->parent,
742 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
744 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
746 gtk_signal_emit (GTK_OBJECT (ctree),
747 ctree_signals[TREE_MOVE],
750 GTK_CTREE_ROW (ctree->drag_target)->children);
753 ctree->drag_source = NULL;
754 ctree->drag_target = NULL;
757 (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event);
761 create_drag_icon (GtkCTree *ctree,
764 GdkWindow *window = NULL;
765 GdkWindowAttr attributes;
766 gint attributes_mask;
771 GdkModifierType modmask;
775 clist = GTK_CLIST (ctree);
776 widget = GTK_WIDGET (ctree);
778 pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap;
779 mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
784 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
785 gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
787 attributes.window_type = GDK_WINDOW_TEMP;
788 attributes.x = root_x - ctree->icon_width / 2;
789 attributes.y = root_y - ctree->icon_height;
790 attributes.width = ctree->icon_width;
791 attributes.height = ctree->icon_height;
792 attributes.wclass = GDK_INPUT_OUTPUT;
793 attributes.visual = gtk_widget_get_visual (widget);
794 attributes.colormap = gtk_widget_get_colormap (widget);
795 attributes.event_mask = gtk_widget_get_events (widget);
797 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
799 window = gdk_window_new (widget->window, &attributes, attributes_mask);
800 gdk_window_set_back_pixmap (window, pixmap, FALSE);
802 gdk_window_shape_combine_mask (window, mask, 0, 0);
803 gdk_window_show (window);
805 ctree->drag_icon = window;
809 create_xor_gc (GtkCTree *ctree)
813 GdkGCPrivate *private;
815 clist = GTK_CLIST (ctree);
817 values.foreground = GTK_WIDGET (clist)->style->bg[GTK_STATE_NORMAL];
818 values.function = GDK_XOR;
819 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
820 ctree->xor_gc = gdk_gc_new_with_values (clist->clist_window, &values,
824 gdk_gc_set_line_attributes (ctree->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
827 private = (GdkGCPrivate*) ctree->xor_gc;
828 XSetDashes (private->xdisplay, private->xgc, 0, "\2\2", 2);
832 draw_xor_line (GtkCTree *ctree)
838 clist = GTK_CLIST (ctree);
840 level = GTK_CTREE_ROW (ctree->drag_target)->level;
842 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
843 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
845 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
847 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_LEFT)
849 if (ctree->tree_column > 0)
850 gdk_draw_line (clist->clist_window, ctree->xor_gc,
851 COLUMN_LEFT_XPIXEL(clist, 0), y,
852 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
853 clist->column[ctree->tree_column - 1].area.width, y);
855 gdk_draw_line (clist->clist_window, ctree->xor_gc,
856 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
857 ctree->tree_indent * level, y,
858 GTK_WIDGET (ctree)->allocation.width, y);
860 else if (clist->column[ctree->tree_column].justification ==
863 if (ctree->tree_column < clist->columns - 1)
864 gdk_draw_line (clist->clist_window, ctree->xor_gc,
865 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
866 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
867 clist->column[clist->columns - 1].area.width, y);
869 gdk_draw_line (clist->clist_window, ctree->xor_gc,
870 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
871 + clist->column[ctree->tree_column].area.width
872 - ctree->tree_indent * level, y);
877 draw_xor_rect (GtkCTree *ctree)
885 clist = GTK_CLIST (ctree);
887 level = GTK_CTREE_ROW (ctree->drag_target)->level;
889 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
891 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_LEFT)
893 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
894 ctree->tree_indent * level;
896 points[3].x = points[0].x;
897 points[3].y = y - clist->row_height - 1;
898 points[1].x = clist->clist_window_width - 1;
899 points[1].y = points[0].y;
900 points[2].x = points[1].x;
901 points[2].y = points[3].y;
903 for (i = 0; i < 3; i++)
904 gdk_draw_line (clist->clist_window, ctree->xor_gc,
905 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
907 if (ctree->tree_column > 0)
909 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
910 clist->column[ctree->tree_column - 1].area.width ;
912 points[3].x = points[0].x;
913 points[3].y = y - clist->row_height - 1;
915 points[1].y = points[0].y;
917 points[2].y = points[3].y;
919 for (i = 0; i < 3; i++)
920 gdk_draw_line (clist->clist_window, ctree->xor_gc,
921 points[i].x, points[i].y, points[i+1].x,
925 else if (clist->column[ctree->tree_column].justification ==
928 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
929 ctree->tree_indent * level +
930 clist->column[ctree->tree_column].area.width;
932 points[3].x = points[0].x;
933 points[3].y = y - clist->row_height - 1;
935 points[1].y = points[0].y;
937 points[2].y = points[3].y;
939 for (i = 0; i < 3; i++)
940 gdk_draw_line (clist->clist_window, ctree->xor_gc,
941 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
943 if (ctree->tree_column < clist->columns - 1)
945 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
947 points[3].x = points[0].x;
948 points[3].y = y - clist->row_height - 1;
949 points[1].x = clist->clist_window_width - 1;
950 points[1].y = points[0].y;
951 points[2].x = points[1].x;
952 points[2].y = points[3].y;
954 for (i = 0; i < 3; i++)
955 gdk_draw_line (clist->clist_window, ctree->xor_gc,
956 points[i].x, points[i].y, points[i+1].x,
963 draw_row (GtkCList *clist,
966 GtkCListRow *clist_row)
972 GdkRectangle row_rectangle;
973 GdkRectangle cell_rectangle;
974 GdkRectangle clip_rectangle;
975 GdkRectangle intersect_rectangle;
978 gint i, offset = 0, width, height, pixmap_width = 0, string_width = 0;
979 gint xsrc, ysrc, xdest, ydest;
980 gboolean need_redraw = TRUE;
982 g_return_if_fail (clist != NULL);
984 /* bail now if we arn't drawable yet */
985 if (!GTK_WIDGET_DRAWABLE (clist))
988 if (row < 0 || row >= clist->rows)
991 widget = GTK_WIDGET (clist);
992 ctree = GTK_CTREE (clist);
994 /* if the function is passed the pointer to the row instead of null,
995 * it avoids this expensive lookup */
997 clist_row = (g_list_nth (clist->row_list, row))->data;
999 /* rectangle of the entire row */
1000 row_rectangle.x = 0;
1001 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1002 row_rectangle.width = clist->clist_window_width;
1003 row_rectangle.height = clist->row_height;
1005 /* rectangle of the cell spacing above the row */
1006 cell_rectangle.x = 0;
1007 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1008 cell_rectangle.width = row_rectangle.width;
1009 cell_rectangle.height = CELL_SPACING;
1011 /* rectangle used to clip drawing operations, it's y and height
1012 * positions only need to be set once, so we set them once here.
1013 * the x and width are set withing the drawing loop below once per
1015 clip_rectangle.y = row_rectangle.y;
1016 clip_rectangle.height = row_rectangle.height;
1018 /* select GC for background rectangle */
1019 if (clist_row->state == GTK_STATE_SELECTED)
1021 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
1022 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
1026 if (clist_row->fg_set)
1028 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1029 fg_gc = clist->fg_gc;
1032 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
1034 if (clist_row->bg_set)
1036 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1037 bg_gc = clist->bg_gc;
1040 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1044 /* draw the cell borders and background */
1047 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1048 gdk_draw_rectangle (clist->clist_window,
1049 widget->style->base_gc[GTK_STATE_NORMAL],
1051 intersect_rectangle.x,
1052 intersect_rectangle.y,
1053 intersect_rectangle.width,
1054 intersect_rectangle.height);
1056 /* the last row has to clear it's bottom cell spacing too */
1057 if (clist_row == clist->row_list_end->data)
1059 cell_rectangle.y += clist->row_height + CELL_SPACING;
1061 if (gdk_rectangle_intersect (area, &cell_rectangle, &intersect_rectangle))
1062 gdk_draw_rectangle (clist->clist_window,
1063 widget->style->base_gc[GTK_STATE_NORMAL],
1065 intersect_rectangle.x,
1066 intersect_rectangle.y,
1067 intersect_rectangle.width,
1068 intersect_rectangle.height);
1071 if (gdk_rectangle_intersect
1072 (area, &row_rectangle, &intersect_rectangle))
1074 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
1075 gdk_draw_rectangle (clist->clist_window,
1078 intersect_rectangle.x,
1079 intersect_rectangle.y,
1080 intersect_rectangle.width,
1081 intersect_rectangle.height);
1083 gdk_window_clear_area (clist->clist_window,
1084 intersect_rectangle.x,
1085 intersect_rectangle.y,
1086 intersect_rectangle.width,
1087 intersect_rectangle.height);
1090 need_redraw = FALSE;
1094 gdk_draw_rectangle (clist->clist_window,
1095 widget->style->base_gc[GTK_STATE_NORMAL],
1099 cell_rectangle.width,
1100 cell_rectangle.height);
1102 /* the last row has to clear it's bottom cell spacing too */
1103 if (clist_row == clist->row_list_end->data)
1105 cell_rectangle.y += clist->row_height + CELL_SPACING;
1107 gdk_draw_rectangle (clist->clist_window,
1108 widget->style->base_gc[GTK_STATE_NORMAL],
1112 cell_rectangle.width,
1113 cell_rectangle.height);
1116 if (clist_row->state == GTK_STATE_SELECTED || clist_row->fg_set)
1117 gdk_draw_rectangle (clist->clist_window,
1122 row_rectangle.width,
1123 row_rectangle.height);
1125 gdk_window_clear_area (clist->clist_window,
1128 row_rectangle.width,
1129 row_rectangle.height);
1132 /* iterate and draw all the columns (row cells) and draw their contents */
1133 for (i = 0; i < clist->columns; i++)
1135 if (!need_redraw && ctree->tree_column != i)
1138 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1139 clip_rectangle.width = clist->column[i].area.width;
1141 /* calculate clipping region clipping region */
1142 if (i == ctree->tree_column)
1144 clip_rectangle.y -= CELL_SPACING;
1145 clip_rectangle.height += CELL_SPACING;
1150 rect = &clip_rectangle;
1155 if (!gdk_rectangle_intersect (area, &clip_rectangle,
1156 &intersect_rectangle))
1158 rect = &intersect_rectangle;
1161 /* calculate real width for column justification */
1162 switch (clist_row->cell[i].type)
1164 case GTK_CELL_EMPTY:
1169 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1170 GTK_CELL_TEXT (clist_row->cell[i])->text);
1173 case GTK_CELL_PIXMAP:
1174 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &width, &height);
1175 pixmap_width = width;
1178 case GTK_CELL_PIXTEXT:
1179 if (i == ctree->tree_column)
1184 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1185 gdk_window_get_size (GTK_CELL_PIXTEXT
1186 (clist_row->cell[i])->pixmap,
1189 pixmap_width = width;
1190 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1192 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
1193 string_width += gdk_string_width
1194 (GTK_WIDGET (clist)->style->font,
1195 GTK_CELL_PIXTEXT(clist_row->cell[i])->text);
1197 width += string_width +
1198 ((GtkCTreeRow *)clist_row)->level * ctree->tree_indent;
1202 gdk_window_get_size (GTK_CELL_PIXTEXT
1203 (clist_row->cell[i])->pixmap,
1205 pixmap_width = width;
1206 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1207 width += gdk_string_width (GTK_WIDGET (clist)->style->font,
1209 (clist_row->cell[i])->text);
1213 case GTK_CELL_WIDGET:
1223 switch (clist->column[i].justification)
1225 case GTK_JUSTIFY_LEFT:
1226 offset = clip_rectangle.x;
1229 case GTK_JUSTIFY_RIGHT:
1230 offset = (clip_rectangle.x + clip_rectangle.width) - width;
1233 case GTK_JUSTIFY_CENTER:
1234 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1237 case GTK_JUSTIFY_FILL:
1238 offset = (clip_rectangle.x + (clip_rectangle.width / 2)) - (width / 2);
1246 if (i == ctree->tree_column &&
1247 clist->column[i].justification == GTK_JUSTIFY_LEFT)
1259 xdest = clip_rectangle.x +
1260 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1262 if (clist_row->state == GTK_STATE_SELECTED)
1264 gdk_gc_set_foreground (ctree->lines_gc,
1265 >K_WIDGET (ctree)->style->
1266 fg[GTK_STATE_SELECTED]);
1267 gdk_gc_set_background (ctree->lines_gc,
1268 >K_WIDGET (ctree)->style->
1269 bg[GTK_STATE_SELECTED]);
1273 gdk_gc_set_foreground (ctree->lines_gc,
1274 >K_WIDGET (ctree)->style->
1275 fg[GTK_STATE_NORMAL]);
1276 if (clist_row->bg_set)
1277 gdk_gc_set_background (ctree->lines_gc,
1278 &clist_row->background);
1282 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1283 gdk_gc_set_clip_origin (ctree->lines_gc, 0, 0);
1284 gdk_gc_set_clip_rectangle (fg_gc, rect);
1285 gdk_gc_set_clip_rectangle (ctree->lines_gc, rect);
1287 yoffset = (clip_rectangle.height - PM_SIZE) / 2;
1288 xoffset = (ctree->tree_indent - PM_SIZE) / 2;
1289 ycenter = clip_rectangle.y + (clip_rectangle.height / 2);
1290 xcenter = xdest + (ctree->tree_indent / 2);
1292 if (ctree->draw_lines)
1294 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1296 offset_x += abs((clip_rectangle.x + clist->hoffset) % 2);
1297 offset_y = abs((clip_rectangle.y + clist->voffset) % 2);
1300 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1301 xcenter, clip_rectangle.y + offset_y, xcenter,
1302 (((GtkCTreeRow *)clist_row)->sibling) ?
1303 rect->y + rect->height : ycenter);
1305 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1306 xcenter + offset_x, ycenter,
1307 xcenter + PM_SIZE / 2 + 2, ycenter);
1310 if (((GtkCTreeRow *)clist_row)->children)
1315 if (clist_row->state == GTK_STATE_SELECTED)
1317 if (clist_row->fg_set)
1320 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
1325 cgc = GTK_WIDGET(clist)->style->fg_gc[GTK_STATE_SELECTED];
1329 gdk_gc_set_clip_rectangle (cgc, rect);
1331 gdk_draw_rectangle (clist->clist_window,
1332 GTK_WIDGET (clist)->style->
1333 fg_gc[GTK_STATE_SELECTED], TRUE,
1334 xdest + xoffset, clip_rectangle.y + yoffset,
1337 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
1338 xdest + xoffset, clip_rectangle.y + yoffset,
1341 gdk_draw_line (clist->clist_window, tgc, xdest + xoffset + 2,
1342 ycenter, xdest + xoffset + PM_SIZE - 2, ycenter);
1344 if (!((GtkCTreeRow *)clist_row)->expanded)
1345 gdk_draw_line (clist->clist_window, tgc, xcenter,
1346 clip_rectangle.y + yoffset + 2, xcenter,
1347 clip_rectangle.y + yoffset + PM_SIZE - 2);
1349 gdk_gc_set_clip_rectangle (cgc, NULL);
1352 work = ((GtkCTreeRow *)clist_row)->parent;
1355 xcenter -= ctree->tree_indent;
1356 if (ctree->draw_lines && GTK_CTREE_ROW (work)->sibling)
1357 gdk_draw_line (clist->clist_window, ctree->lines_gc, xcenter,
1358 clip_rectangle.y + offset_y, xcenter,
1359 rect->y + rect->height);
1360 work = GTK_CTREE_ROW (work)->parent;
1363 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1365 xdest += offset - clip_rectangle.x + ctree->tree_indent +
1366 clist_row->cell[i].horizontal;
1367 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) -
1368 height / 2 + clist_row->cell[i].vertical;
1370 if (pixmap_width && xdest + pixmap_width >= rect->x &&
1371 xdest <= rect->x + rect->width)
1373 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
1375 gdk_gc_set_clip_mask
1376 (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
1377 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1379 gdk_draw_pixmap (clist->clist_window, fg_gc,
1380 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1381 xsrc, ysrc, xdest, ydest, pixmap_width, height);
1383 if (xdest + pixmap_width >
1384 clip_rectangle.x + clip_rectangle.width)
1385 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1386 rect->x + rect->width, ydest + 1,
1387 xdest + pixmap_width -
1388 (rect->x + rect->width), height - 1);
1395 xdest += pixmap_width +
1396 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1398 delta = CELL_SPACING - (rect->y - clip_rectangle.y);
1402 rect->height -= delta;
1405 gdk_gc_set_clip_rectangle (fg_gc, rect);
1407 gdk_draw_string (clist->clist_window,
1408 widget->style->font, fg_gc, xdest,
1409 row_rectangle.y + clist->row_center_offset +
1410 clist_row->cell[i].vertical,
1411 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1414 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1416 else if (i == ctree->tree_column &&
1417 clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1429 xdest = clip_rectangle.x + clip_rectangle.width -
1430 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1432 if (clist_row->state == GTK_STATE_SELECTED)
1434 gdk_gc_set_foreground (ctree->lines_gc,
1435 >K_WIDGET (ctree)->style->
1436 fg[GTK_STATE_SELECTED]);
1437 gdk_gc_set_background (ctree->lines_gc,
1438 >K_WIDGET (ctree)->style->
1439 bg[GTK_STATE_SELECTED]);
1443 gdk_gc_set_foreground (ctree->lines_gc,
1444 >K_WIDGET (ctree)->style->
1445 fg[GTK_STATE_NORMAL]);
1446 if (clist_row->bg_set)
1447 gdk_gc_set_background (ctree->lines_gc,
1448 &clist_row->background);
1452 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1453 gdk_gc_set_clip_origin (ctree->lines_gc, 0, 0);
1454 gdk_gc_set_clip_rectangle (fg_gc, rect);
1455 gdk_gc_set_clip_rectangle (ctree->lines_gc, rect);
1457 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1458 gdk_gc_set_clip_rectangle (fg_gc, rect);
1460 yoffset = (clip_rectangle.height - PM_SIZE) / 2;
1461 xoffset = (ctree->tree_indent - PM_SIZE) / 2;
1462 ycenter = clip_rectangle.y + (clip_rectangle.height / 2);
1463 xcenter = xdest - (ctree->tree_indent / 2);
1465 if (ctree->draw_lines)
1467 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1469 offset_x += abs((clip_rectangle.x + clist->hoffset) % 2);
1470 offset_y = abs((clip_rectangle.y + clist->voffset) % 2);
1473 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1474 xcenter, clip_rectangle.y + offset_y, xcenter,
1475 (((GtkCTreeRow *)clist_row)->sibling) ?
1476 rect->y + rect->height : ycenter);
1478 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1479 xcenter - offset_x, ycenter,
1480 xcenter - PM_SIZE / 2 - 2, ycenter);
1483 if (((GtkCTreeRow *)clist_row)->children)
1488 if (clist_row->state == GTK_STATE_SELECTED)
1490 if (clist_row->fg_set)
1493 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
1498 cgc = GTK_WIDGET(clist)->style->fg_gc[GTK_STATE_SELECTED];
1502 gdk_gc_set_clip_rectangle (cgc, rect);
1504 gdk_draw_rectangle (clist->clist_window,
1505 GTK_WIDGET(clist)->style->
1506 fg_gc[GTK_STATE_SELECTED], TRUE,
1507 xdest - xoffset - PM_SIZE,
1508 clip_rectangle.y + yoffset,
1511 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
1512 xdest - xoffset - PM_SIZE,
1513 clip_rectangle.y + yoffset,
1516 gdk_draw_line (clist->clist_window, tgc, xdest - xoffset - 2,
1517 ycenter, xdest - xoffset - PM_SIZE + 2, ycenter);
1519 if (!((GtkCTreeRow *)clist_row)->expanded)
1521 gdk_draw_line (clist->clist_window, tgc, xcenter,
1522 clip_rectangle.y + yoffset + 2, xcenter,
1523 clip_rectangle.y + yoffset + PM_SIZE - 2);
1525 gdk_gc_set_clip_rectangle (cgc, NULL);
1528 work = ((GtkCTreeRow *)clist_row)->parent;
1531 xcenter += ctree->tree_indent;
1532 if (ctree->draw_lines && GTK_CTREE_ROW(work)->sibling)
1533 gdk_draw_line (clist->clist_window, ctree->lines_gc, xcenter,
1534 clip_rectangle.y - offset_y, xcenter,
1535 rect->y + rect->height);
1536 work = GTK_CTREE_ROW (work)->parent;
1539 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1541 xdest -= (ctree->tree_indent + pixmap_width
1542 + clist_row->cell[i].horizontal);
1543 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) -
1544 height / 2 + clist_row->cell[i].vertical;
1546 if (pixmap_width && xdest + pixmap_width >= rect->x &&
1547 xdest <= rect->x + rect->width && xdest >= clip_rectangle.x)
1549 gdk_gc_set_clip_mask
1550 (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
1551 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1552 gdk_draw_pixmap (clist->clist_window, fg_gc,
1553 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1554 xsrc, ysrc, xdest, ydest, pixmap_width, height);
1561 xdest -= (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
1564 delta = CELL_SPACING - (rect->y - clip_rectangle.y);
1568 rect->height -= delta;
1571 gdk_gc_set_clip_rectangle (fg_gc, rect);
1573 gdk_draw_string (clist->clist_window,
1574 widget->style->font, fg_gc, xdest,
1575 row_rectangle.y + clist->row_center_offset +
1576 clist_row->cell[i].vertical,
1577 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1579 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1584 switch (clist_row->cell[i].type)
1586 case GTK_CELL_EMPTY:
1591 gdk_gc_set_clip_rectangle (fg_gc, rect);
1593 gdk_draw_string (clist->clist_window,
1594 widget->style->font,
1596 offset + clist_row->cell[i].horizontal,
1597 row_rectangle.y + clist->row_center_offset +
1598 clist_row->cell[i].vertical,
1599 GTK_CELL_TEXT (clist_row->cell[i])->text);
1601 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1604 case GTK_CELL_PIXMAP:
1607 xdest = offset + clist_row->cell[i].horizontal;
1608 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1609 clist_row->cell[i].vertical;
1611 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
1613 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP (clist_row->cell[i])->mask);
1614 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1616 gdk_draw_pixmap (clist->clist_window, fg_gc,
1617 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1618 xsrc, ysrc, xdest, ydest, pixmap_width, height);
1620 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
1622 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1623 gdk_gc_set_clip_mask (fg_gc, NULL);
1627 case GTK_CELL_PIXTEXT:
1628 /* draw the pixmap */
1631 xdest = offset + clist_row->cell[i].horizontal;
1632 ydest = (clip_rectangle.y + (clip_rectangle.height / 2)) - height / 2 +
1633 clist_row->cell[i].vertical;
1635 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
1637 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
1638 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
1641 gdk_draw_pixmap (clist->clist_window, fg_gc,
1642 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1643 xsrc, ysrc, xdest, ydest, pixmap_width, height);
1645 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1647 xdest += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1649 /* draw the string */
1650 gdk_gc_set_clip_rectangle (fg_gc, rect);
1652 gdk_draw_string (clist->clist_window, widget->style->font, fg_gc,
1654 row_rectangle.y + clist->row_center_offset +
1655 clist_row->cell[i].vertical,
1656 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1658 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1662 case GTK_CELL_WIDGET:
1676 tree_draw_row (GtkCTree *ctree,
1681 clist = GTK_CLIST (ctree);
1683 if (!GTK_CLIST_FROZEN (clist) && gtk_ctree_is_visible (ctree, row))
1688 work = clist->row_list;
1694 if (gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
1695 (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row)
1696 (clist, NULL, num, &(GTK_CTREE_ROW (row)->row));
1701 gtk_ctree_last_visible (GtkCTree *ctree,
1709 sib = GTK_CTREE_ROW (list)->children;
1711 if (!sib || !GTK_CTREE_ROW (list)->expanded)
1714 while (GTK_CTREE_ROW (sib)->sibling)
1715 sib = GTK_CTREE_ROW (sib)->sibling;
1717 return gtk_ctree_last_visible (ctree, sib);
1721 gtk_ctree_link (GtkCTree *ctree,
1728 gint visible = TRUE;
1731 g_return_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent);
1732 g_return_if_fail (child != NULL);
1733 g_return_if_fail (sibling != child);
1734 g_return_if_fail (child != parent);
1736 clist = GTK_CLIST (ctree);
1738 for (rows = 1, list_end = child; list_end->next; list_end = list_end->next)
1741 GTK_CTREE_ROW (child)->parent = parent;
1742 GTK_CTREE_ROW (child)->sibling = sibling;
1746 if ((visible = gtk_ctree_is_visible (ctree, parent)) &&
1747 GTK_CTREE_ROW (parent)->expanded)
1748 clist->rows += rows;
1751 clist->rows += rows;
1758 work = GTK_CTREE_ROW (parent)->children;
1760 work = clist->row_list;
1761 if (work != sibling)
1763 while (GTK_CTREE_ROW (work)->sibling != sibling)
1764 work = GTK_CTREE_ROW (work)->sibling;
1765 GTK_CTREE_ROW (work)->sibling = child;
1768 if (sibling == clist->row_list)
1769 clist->row_list = child;
1770 if (sibling->prev && sibling->prev->next == sibling)
1771 sibling->prev->next = child;
1773 child->prev = sibling->prev;
1774 list_end->next = sibling;
1775 sibling->prev = list_end;
1776 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
1777 GTK_CTREE_ROW (parent)->children = child;
1784 work = GTK_CTREE_ROW (parent)->children;
1786 work = clist->row_list;
1791 while (GTK_CTREE_ROW (work)->sibling)
1792 work = GTK_CTREE_ROW (work)->sibling;
1793 GTK_CTREE_ROW (work)->sibling = child;
1795 /* find last visible child of sibling */
1796 work = gtk_ctree_last_visible (ctree, work);
1798 list_end->next = work->next;
1800 work->next->prev = list_end;
1808 GTK_CTREE_ROW (parent)->children = child;
1809 child->prev = parent;
1810 if (GTK_CTREE_ROW (parent)->expanded)
1812 list_end->next = parent->next;
1814 parent->next->prev = list_end;
1815 parent->next = child;
1818 list_end->next = NULL;
1822 clist->row_list = child;
1824 list_end->next = NULL;
1829 gtk_ctree_pre_recursive (ctree, child, tree_update_level, NULL);
1831 if (clist->row_list_end == NULL || clist->row_list_end->next == child)
1832 clist->row_list_end = list_end;
1834 if (!GTK_CLIST_FROZEN (clist) && visible)
1835 gtk_clist_thaw (clist);
1839 gtk_ctree_unlink (GtkCTree *ctree,
1849 g_return_if_fail (ctree != NULL);
1850 g_return_if_fail (GTK_IS_CTREE (ctree));
1851 g_return_if_fail (child != NULL);
1853 clist = GTK_CLIST (ctree);
1855 visible = gtk_ctree_is_visible (ctree, child);
1857 /* clist->row_list_end unlinked ? */
1859 (child->next == NULL ||
1860 (GTK_CTREE_ROW (child)->children &&
1861 gtk_ctree_is_ancestor (ctree, child, clist->row_list_end))))
1862 clist->row_list_end = child->prev;
1866 level = GTK_CTREE_ROW (child)->level;
1868 while (work && GTK_CTREE_ROW (work)->level > level)
1876 work->prev->next = NULL;
1877 work->prev = child->prev;
1881 if (child->prev && child->prev->next == child)
1882 child->prev->next = work;
1885 parent = GTK_CTREE_ROW (child)->parent;
1888 if (GTK_CTREE_ROW (parent)->children == child)
1890 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (child)->sibling;
1891 if (!GTK_CTREE_ROW (parent)->children &&
1892 GTK_CTREE_ROW (parent)->pixmap_closed)
1894 GTK_CTREE_ROW (parent)->expanded = FALSE;
1896 (GTK_CTREE_ROW(parent)->row.cell[ctree->tree_column])->pixmap =
1897 GTK_CTREE_ROW (parent)->pixmap_closed;
1899 (GTK_CTREE_ROW (parent)->row.cell[ctree->tree_column])->mask =
1900 GTK_CTREE_ROW (parent)->mask_closed;
1907 sibling = GTK_CTREE_ROW (parent)->children;
1908 while (GTK_CTREE_ROW (sibling)->sibling != child)
1909 sibling = GTK_CTREE_ROW (sibling)->sibling;
1910 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (child)->sibling;
1915 if (clist->row_list == child)
1916 clist->row_list = GTK_CTREE_ROW (child)->sibling;
1921 sibling = clist->row_list;
1922 while (GTK_CTREE_ROW (sibling)->sibling != child)
1923 sibling = GTK_CTREE_ROW (sibling)->sibling;
1924 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (child)->sibling;
1930 clist->rows -= (rows + 1);
1932 if (!GTK_CLIST_FROZEN (clist))
1933 gtk_clist_thaw (clist);
1938 real_tree_move (GtkCTree *ctree,
1945 gboolean thaw = FALSE;
1947 g_return_if_fail (ctree != NULL);
1948 g_return_if_fail (child != NULL);
1949 g_return_if_fail (!new_sibling ||
1950 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
1952 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
1955 /* new_parent != child of child */
1956 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
1960 clist = GTK_CLIST (ctree);
1962 if (ctree->auto_sort)
1964 if (new_parent == GTK_CTREE_ROW (child)->parent)
1968 new_sibling = GTK_CTREE_ROW (new_parent)->children;
1970 new_sibling = clist->row_list;
1972 while (new_sibling &&
1973 ctree->node_compare (ctree, child, new_sibling) > 0)
1974 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
1977 if (new_parent == GTK_CTREE_ROW (child)->parent &&
1978 new_sibling == GTK_CTREE_ROW (child)->sibling)
1981 if (!GTK_CLIST_FROZEN (clist))
1983 gtk_clist_freeze (clist);
1986 gtk_ctree_unlink (ctree, child);
1987 gtk_ctree_link (ctree, child, new_parent, new_sibling);
1990 gtk_clist_thaw (clist);
1994 real_tree_expand (GtkCTree *ctree,
2000 if (!list || GTK_CTREE_ROW (list)->expanded)
2003 GTK_CTREE_ROW (list)->expanded = TRUE;
2004 level = GTK_CTREE_ROW (list)->level;
2006 if (GTK_CTREE_ROW (list)->pixmap_opened)
2009 (GTK_CTREE_ROW (list)->row.cell[ctree->tree_column])->pixmap =
2010 GTK_CTREE_ROW (list)->pixmap_opened;
2012 (GTK_CTREE_ROW (list)->row.cell[ctree->tree_column])->mask =
2013 GTK_CTREE_ROW (list)->mask_opened;
2016 work = GTK_CTREE_ROW (list)->children;
2027 work->next = list->next;
2030 list->next->prev = work;
2032 GTK_CLIST (ctree)->row_list_end = work;
2034 list->next = GTK_CTREE_ROW (list)->children;
2036 if (gtk_ctree_is_visible (ctree, list))
2038 GTK_CLIST (ctree)->rows += tmp + 1;
2039 if (!GTK_CLIST_FROZEN (ctree))
2040 gtk_clist_thaw (GTK_CLIST (ctree));
2046 real_tree_collapse (GtkCTree *ctree,
2052 if (!list || !GTK_CTREE_ROW (list)->expanded)
2055 GTK_CTREE_ROW (list)->expanded = FALSE;
2056 level = GTK_CTREE_ROW (list)->level;
2058 if (GTK_CTREE_ROW (list)->pixmap_closed)
2061 (GTK_CTREE_ROW (list)->row.cell[ctree->tree_column])->pixmap =
2062 GTK_CTREE_ROW (list)->pixmap_closed;
2064 (GTK_CTREE_ROW (list)->row.cell[ctree->tree_column])->mask =
2065 GTK_CTREE_ROW (list)->mask_closed;
2068 work = GTK_CTREE_ROW (list)->children;
2073 while (work && GTK_CTREE_ROW (work)->level > level)
2082 work->prev->next = NULL;
2088 GTK_CLIST (ctree)->row_list_end = list;
2091 if (gtk_ctree_is_visible (ctree, list))
2093 GTK_CLIST (ctree)->rows -= tmp;
2094 if (!GTK_CLIST_FROZEN (ctree))
2095 gtk_clist_thaw (GTK_CLIST (ctree));
2101 cell_set_text (GtkCList *clist,
2102 GtkCListRow *clist_row,
2106 cell_empty (clist, clist_row, column);
2110 clist_row->cell[column].type = GTK_CELL_TEXT;
2111 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2116 cell_set_pixmap (GtkCList *clist,
2117 GtkCListRow *clist_row,
2122 cell_empty (clist, clist_row, column);
2126 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2127 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2128 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2133 cell_set_pixtext (GtkCList *clist,
2134 GtkCListRow *clist_row,
2141 cell_empty (clist, clist_row, column);
2145 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2146 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2147 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2148 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2149 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2154 set_node_info (GtkCTree *ctree,
2158 GdkPixmap *pixmap_closed,
2159 GdkBitmap *mask_closed,
2160 GdkPixmap *pixmap_opened,
2161 GdkBitmap *mask_opened,
2165 GtkCellPixText *tree_cell;
2167 if (GTK_CTREE_ROW (node)->pixmap_opened)
2169 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
2170 if (GTK_CTREE_ROW (node)->mask_opened)
2171 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
2173 if (GTK_CTREE_ROW (node)->pixmap_closed)
2175 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
2176 if (GTK_CTREE_ROW (node)->mask_closed)
2177 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
2180 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
2181 GTK_CTREE_ROW (node)->mask_opened = NULL;
2182 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
2183 GTK_CTREE_ROW (node)->mask_closed = NULL;
2187 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
2189 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
2193 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
2195 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
2198 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
2199 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
2201 GTK_CTREE_ROW (node)->row.cell[ctree->tree_column].type = GTK_CELL_PIXTEXT;
2203 tree_cell = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
2204 (node)->row.cell[ctree->tree_column]);
2206 if (tree_cell->text)
2207 g_free (tree_cell->text);
2209 tree_cell->text = g_strdup (text);
2210 tree_cell->spacing = spacing;
2214 tree_cell->pixmap = pixmap_opened;
2215 tree_cell->mask = mask_opened;
2219 tree_cell->pixmap = pixmap_closed;
2220 tree_cell->mask = mask_closed;
2225 tree_delete (GtkCTree *ctree,
2231 clist = GTK_CLIST (ctree);
2233 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
2237 work = g_list_find (clist->selection, node);
2240 if (ctree->selection_last && ctree->selection_last == work)
2241 ctree->selection_last = ctree->selection_last->prev;
2242 clist->selection = g_list_remove (clist->selection, node);
2246 row_delete (ctree, GTK_CTREE_ROW (node));
2247 g_list_free_1 (node);
2251 tree_delete_raw (GtkCTree *ctree,
2255 row_delete (ctree, GTK_CTREE_ROW (node));
2256 g_list_free_1 (node);
2260 tree_update_level (GtkCTree *ctree,
2267 if (GTK_CTREE_ROW (node)->parent)
2268 GTK_CTREE_ROW (node)->level =
2269 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
2271 GTK_CTREE_ROW (node)->level = 1;
2275 tree_select (GtkCTree *ctree,
2279 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], node,
2284 tree_unselect (GtkCTree *ctree,
2288 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], node,
2293 tree_expand (GtkCTree *ctree,
2297 if (node && !GTK_CTREE_ROW (node)->expanded)
2298 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node,
2303 tree_collapse (GtkCTree *ctree,
2307 if (node && GTK_CTREE_ROW (node)->expanded)
2308 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node,
2312 static GtkCTreeRow *
2313 row_new (GtkCTree *ctree)
2316 GtkCTreeRow *ctree_row;
2319 clist = GTK_CLIST (ctree);
2320 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
2321 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
2323 for (i = 0; i < clist->columns; i++)
2325 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
2326 ctree_row->row.cell[i].vertical = 0;
2327 ctree_row->row.cell[i].horizontal = 0;
2330 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
2332 ctree_row->row.fg_set = FALSE;
2333 ctree_row->row.bg_set = FALSE;
2334 ctree_row->row.state = GTK_STATE_NORMAL;
2335 ctree_row->row.data = NULL;
2336 ctree_row->row.destroy = NULL;
2338 ctree_row->level = 0;
2339 ctree_row->expanded = FALSE;
2340 ctree_row->parent = NULL;
2341 ctree_row->sibling = NULL;
2342 ctree_row->children = NULL;
2343 ctree_row->pixmap_closed = NULL;
2344 ctree_row->mask_closed = NULL;
2345 ctree_row->pixmap_opened = NULL;
2346 ctree_row->mask_opened = NULL;
2352 row_delete (GtkCTree *ctree,
2353 GtkCTreeRow *ctree_row)
2358 clist = GTK_CLIST (ctree);
2360 for (i = 0; i < clist->columns; i++)
2361 cell_empty (clist, &(ctree_row->row), i);
2363 if (ctree_row->pixmap_closed)
2365 gdk_pixmap_unref (ctree_row->pixmap_closed);
2366 if (ctree_row->mask_closed)
2367 gdk_bitmap_unref (ctree_row->mask_closed);
2370 if (ctree_row->pixmap_opened)
2372 gdk_pixmap_unref (ctree_row->pixmap_opened);
2373 if (ctree_row->mask_opened)
2374 gdk_bitmap_unref (ctree_row->mask_opened);
2377 if (ctree_row->row.destroy)
2378 ctree_row->row.destroy (ctree_row->row.data);
2380 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
2381 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
2385 cell_empty (GtkCList *clist,
2386 GtkCListRow *clist_row,
2389 switch (clist_row->cell[column].type)
2391 case GTK_CELL_EMPTY:
2395 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2398 case GTK_CELL_PIXMAP:
2399 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2400 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
2401 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2404 case GTK_CELL_PIXTEXT:
2405 if (GTK_CTREE (clist)->tree_column == column)
2407 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
2408 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2411 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2412 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2413 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
2414 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2417 case GTK_CELL_WIDGET:
2425 clist_row->cell[column].type = GTK_CELL_EMPTY;
2429 real_select_row (GtkCTree *ctree,
2436 g_return_if_fail (ctree != NULL);
2441 clist = GTK_CLIST (ctree);
2443 if (GTK_CTREE_ROW (row)->row.state == GTK_STATE_SELECTED)
2446 if (clist->selection_mode == GTK_SELECTION_SINGLE ||
2447 clist->selection_mode == GTK_SELECTION_BROWSE)
2452 list = clist->selection;
2456 sel_row = list->data;
2459 if (row != sel_row &&
2460 GTK_CTREE_ROW (sel_row)->row.state == GTK_STATE_SELECTED)
2461 gtk_signal_emit (GTK_OBJECT (ctree),
2462 ctree_signals[TREE_UNSELECT_ROW], sel_row,
2467 GTK_CTREE_ROW (row)->row.state = GTK_STATE_SELECTED;
2468 selection = g_list_alloc ();
2469 selection->data = row;
2471 if (ctree->selection_last)
2473 ctree->selection_last->next = selection;
2474 selection->prev = ctree->selection_last;
2477 clist->selection = selection;
2479 ctree->selection_last = selection;
2481 tree_draw_row (ctree, row);
2485 real_unselect_row (GtkCTree *ctree,
2491 g_return_if_fail (ctree != NULL);
2496 if (GTK_CTREE_ROW (row)->row.state != GTK_STATE_SELECTED)
2499 clist = GTK_CLIST (ctree);
2501 if (ctree->selection_last && ctree->selection_last->data == row)
2502 ctree->selection_last = ctree->selection_last->prev;
2504 clist->selection = g_list_remove (clist->selection, row);
2505 GTK_CTREE_ROW (row)->row.state = GTK_STATE_NORMAL;
2507 tree_draw_row (ctree, row);
2511 tree_toggle_row (GtkCTree *ctree,
2515 switch (GTK_CLIST (ctree)->selection_mode)
2517 case GTK_SELECTION_SINGLE:
2518 case GTK_SELECTION_MULTIPLE:
2519 if (row && GTK_CTREE_ROW (row)->row.state == GTK_STATE_SELECTED)
2520 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
2523 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
2527 case GTK_SELECTION_BROWSE:
2528 if (row && GTK_CTREE_ROW (row)->row.state == GTK_STATE_NORMAL)
2529 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
2533 case GTK_SELECTION_EXTENDED:
2542 ctree_is_hot_spot (GtkCTree *ctree,
2548 GtkCTreeRow *tree_row;
2550 GtkCellPixText *cell;
2554 g_return_val_if_fail (ctree != NULL, FALSE);
2555 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
2556 g_return_val_if_fail (node != NULL, FALSE);
2558 tree_row = GTK_CTREE_ROW (node);
2559 clist = GTK_CLIST (ctree);
2561 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
2563 yu = ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2;
2565 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
2567 xl = clist->column[ctree->tree_column].area.x
2568 + clist->column[ctree->tree_column].area.width + clist->hoffset
2569 /*+ cell->horizontal +*/
2570 - (tree_row->level - 1) * ctree->tree_indent
2571 - (ctree->tree_indent - PM_SIZE) / 2
2576 xl = clist->column[ctree->tree_column].area.x + clist->hoffset
2577 + cell->horizontal + (tree_row->level - 1) * ctree->tree_indent
2578 + (ctree->tree_indent - PM_SIZE) / 2;
2581 if (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE)
2588 default_compare (GtkCTree *ctree,
2595 text1 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
2596 (list1)->row.cell[ctree->tree_column])->text;
2597 text2 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
2598 (list2)->row.cell[ctree->tree_column])->text;
2599 return strcmp (text1, text2);
2603 /***********************************************************
2604 ***********************************************************
2605 *** Public interface ***
2606 ***********************************************************
2607 ***********************************************************/
2610 /***********************************************************
2611 * Creation, insertion, deletion *
2612 ***********************************************************/
2615 gtk_ctree_construct (GtkCTree *ctree,
2622 g_return_if_fail (ctree != NULL);
2623 g_return_if_fail (GTK_IS_CTREE (ctree));
2624 g_return_if_fail (GTK_CLIST_CONSTRUCTED (ctree) == FALSE);
2626 clist = GTK_CLIST (ctree);
2628 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
2629 sizeof (GtkCTreeRow),
2630 sizeof (GtkCTreeRow)
2631 * CLIST_OPTIMUM_SIZE,
2634 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
2635 sizeof (GtkCell) * columns,
2636 sizeof (GtkCell) * columns
2637 * CLIST_OPTIMUM_SIZE,
2640 ctree->tree_column = tree_column;
2642 gtk_clist_construct (clist, columns, titles);
2646 gtk_ctree_new_with_titles (gint columns,
2652 g_return_val_if_fail (columns > 0, NULL);
2653 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
2655 widget = gtk_type_new (gtk_ctree_get_type ());
2656 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
2661 gtk_ctree_new (gint columns,
2664 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
2668 gtk_ctree_insert (GtkCTree *ctree,
2673 GdkPixmap *pixmap_closed,
2674 GdkBitmap *mask_closed,
2675 GdkPixmap *pixmap_opened,
2676 GdkBitmap *mask_opened,
2681 GtkCTreeRow *new_row;
2685 g_return_val_if_fail (ctree != NULL, NULL);
2686 g_return_val_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent,
2689 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
2692 clist = GTK_CLIST (ctree);
2694 /* create the row */
2695 new_row = row_new (ctree);
2696 node = g_list_alloc ();
2697 node->data = new_row;
2700 for (i = 0; i < clist->columns; i++)
2701 if (text[i] && i != ctree->tree_column)
2702 cell_set_text (clist, &(new_row->row), i, text[i]);
2704 set_node_info (ctree, node, text[ctree->tree_column], spacing, pixmap_closed,
2705 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
2707 if (ctree->auto_sort)
2710 sibling = GTK_CTREE_ROW (parent)->children;
2712 sibling = clist->row_list;
2714 while (sibling && ctree->node_compare (ctree, node, sibling) > 0)
2715 sibling = GTK_CTREE_ROW (sibling)->sibling;
2718 gtk_ctree_link (ctree, node, parent, sibling);
2724 gtk_ctree_remove (GtkCTree *ctree,
2728 gboolean thaw = FALSE;
2730 g_return_if_fail (ctree != NULL);
2731 g_return_if_fail (GTK_IS_CTREE (ctree));
2733 clist = GTK_CLIST (ctree);
2735 if (!GTK_CLIST_FROZEN (clist))
2737 gtk_clist_freeze (clist);
2743 gtk_ctree_unlink (ctree, node);
2744 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
2752 work = clist->row_list;
2753 clist->row_list = NULL;
2754 clist->row_list_end = NULL;
2760 work = GTK_CTREE_ROW (work)->sibling;
2761 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete),
2767 gtk_clist_thaw (clist);
2771 gtk_ctree_clear (GtkCTree *ctree)
2777 g_return_if_fail (ctree != NULL);
2778 g_return_if_fail (GTK_IS_CTREE (ctree));
2780 clist = GTK_CLIST (ctree);
2783 /* free up the selection list */
2784 g_list_free (clist->selection);
2785 clist->selection = NULL;
2786 ctree->selection_last = NULL;
2788 /* remove all the rows */
2790 work = clist->row_list;
2791 clist->row_list = NULL;
2792 clist->row_list_end = NULL;
2798 work = GTK_CTREE_ROW (work)->sibling;
2799 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_raw),
2806 ctree->drag_row = -1;
2807 ctree->drag_rect = FALSE;
2808 ctree->in_drag = FALSE;
2809 ctree->drag_source = NULL;
2810 ctree->drag_target = NULL;
2811 ctree->drag_icon = NULL;
2813 /* zero-out the scrollbars */
2814 if (clist->vscrollbar)
2816 GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
2817 gtk_signal_emit_by_name
2818 (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
2820 if (!GTK_CLIST_FROZEN (clist))
2821 gtk_clist_thaw (clist);
2825 /***********************************************************
2826 * Generic recursive functions, querying / finding tree *
2828 ***********************************************************/
2832 gtk_ctree_post_recursive (GtkCTree *ctree,
2841 work = GTK_CTREE_ROW (node)->children;
2843 work = GTK_CLIST (ctree)->row_list;
2847 tmp = GTK_CTREE_ROW (work)->sibling;
2848 gtk_ctree_post_recursive (ctree, work, func, data);
2852 (* func) (ctree, node, data);
2856 gtk_ctree_pre_recursive (GtkCTree *ctree,
2864 (* func) (ctree, node, data);
2867 work = GTK_CTREE_ROW (node)->children;
2869 work = GTK_CLIST (ctree)->row_list;
2873 tmp = GTK_CTREE_ROW (work)->sibling;
2874 gtk_ctree_pre_recursive (ctree, work, func, data);
2880 gtk_ctree_is_visible (GtkCTree *ctree,
2885 work = GTK_CTREE_ROW (node);
2887 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
2888 work = GTK_CTREE_ROW (work->parent);
2897 gtk_ctree_last (GtkCTree *ctree,
2903 while (GTK_CTREE_ROW (node)->sibling)
2904 node = GTK_CTREE_ROW (node)->sibling;
2906 if (GTK_CTREE_ROW (node)->children)
2907 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
2913 gtk_ctree_find (GtkCTree *ctree,
2921 if (GTK_CTREE_ROW (node)->children)
2923 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
2926 node = GTK_CTREE_ROW (node)->sibling;
2932 gtk_ctree_is_ancestor (GtkCTree *ctree,
2936 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
2940 gtk_ctree_find_by_row_data (GtkCTree *ctree,
2948 if (GTK_CTREE_ROW (node)->row.data == data)
2950 if (GTK_CTREE_ROW (node)->children &&
2951 (work = gtk_ctree_find_by_row_data
2952 (ctree, GTK_CTREE_ROW (node)->children, data)))
2954 node = GTK_CTREE_ROW (node)->sibling;
2960 gtk_ctree_is_hot_spot (GtkCTree *ctree,
2968 g_return_val_if_fail (ctree != NULL, FALSE);
2969 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
2971 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
2972 if ((node = g_list_nth (GTK_CLIST (ctree)->row_list, row)))
2973 return ctree_is_hot_spot (ctree, node, row, x, y);
2979 /***********************************************************
2980 * Tree signals : move, expand, collapse, (un)select *
2981 ***********************************************************/
2985 gtk_ctree_move (GtkCTree *ctree,
2990 g_return_if_fail (ctree != NULL);
2991 g_return_if_fail (child != NULL);
2993 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], child,
2994 new_parent, new_sibling);
2998 gtk_ctree_expand (GtkCTree *ctree,
3001 g_return_if_fail (ctree != NULL);
3002 g_return_if_fail (node != NULL);
3004 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3008 gtk_ctree_expand_recursive (GtkCTree *ctree,
3012 gboolean thaw = FALSE;
3014 g_return_if_fail (ctree != NULL);
3016 clist = GTK_CLIST (ctree);
3018 if (node && !GTK_CTREE_ROW (node)->children)
3021 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
3022 !GTK_CLIST_FROZEN (clist))
3024 gtk_clist_freeze (clist);
3028 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
3031 gtk_clist_thaw (clist);
3035 gtk_ctree_collapse (GtkCTree *ctree,
3038 g_return_if_fail (ctree != NULL);
3039 g_return_if_fail (node != NULL);
3041 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3045 gtk_ctree_collapse_recursive (GtkCTree *ctree,
3049 gboolean thaw = FALSE;
3051 g_return_if_fail (ctree != NULL);
3053 clist = GTK_CLIST (ctree);
3055 if (node && !GTK_CTREE_ROW (node)->children)
3058 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
3059 !GTK_CLIST_FROZEN (clist))
3061 gtk_clist_freeze (clist);
3065 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
3068 gtk_clist_thaw (clist);
3072 gtk_ctree_select (GtkCTree *ctree,
3075 g_return_if_fail (ctree != NULL);
3076 g_return_if_fail (node != NULL);
3078 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], node);
3082 gtk_ctree_unselect (GtkCTree *ctree,
3085 g_return_if_fail (ctree != NULL);
3086 g_return_if_fail (node != NULL);
3088 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], node);
3092 gtk_ctree_select_recursive (GtkCTree *ctree,
3095 gtk_ctree_real_select_recursive (ctree, node, TRUE);
3099 gtk_ctree_unselect_recursive (GtkCTree *ctree,
3102 gtk_ctree_real_select_recursive (ctree, node, FALSE);
3106 gtk_ctree_real_select_recursive (GtkCTree *ctree,
3111 gboolean thaw = FALSE;
3113 g_return_if_fail (ctree != NULL);
3115 clist = GTK_CLIST (ctree);
3117 if (clist->selection_mode == GTK_SELECTION_EXTENDED ||
3118 (state && clist->selection_mode != GTK_SELECTION_MULTIPLE) ||
3119 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
3122 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
3123 !GTK_CLIST_FROZEN (clist))
3125 gtk_clist_freeze (clist);
3130 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_select), NULL);
3132 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_unselect), NULL);
3135 gtk_clist_thaw (clist);
3139 /***********************************************************
3140 * Analogons of GtkCList functions *
3141 ***********************************************************/
3145 gtk_ctree_set_text (GtkCTree *ctree,
3150 g_return_if_fail (ctree != NULL);
3151 g_return_if_fail (GTK_IS_CTREE (ctree));
3152 g_return_if_fail (node != NULL);
3153 g_return_if_fail (ctree->tree_column != column);
3155 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3158 cell_set_text (GTK_CLIST (ctree), &(GTK_CTREE_ROW(node)->row), column, text);
3159 tree_draw_row (ctree, node);
3163 gtk_ctree_set_pixmap (GtkCTree *ctree,
3169 g_return_if_fail (ctree != NULL);
3170 g_return_if_fail (GTK_IS_CTREE (ctree));
3171 g_return_if_fail (child != NULL);
3172 g_return_if_fail (pixmap != NULL);
3173 g_return_if_fail (ctree->tree_column != column);
3175 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3178 gdk_pixmap_ref (pixmap);
3180 gdk_pixmap_ref (mask);
3182 cell_set_pixmap (GTK_CLIST (ctree), &(GTK_CTREE_ROW (child)->row), column,
3184 tree_draw_row (ctree, child);
3188 gtk_ctree_set_pixtext (GtkCTree *ctree,
3196 g_return_if_fail (ctree != NULL);
3197 g_return_if_fail (GTK_IS_CTREE (ctree));
3198 g_return_if_fail (child != NULL);
3199 g_return_if_fail (pixmap != NULL);
3200 g_return_if_fail (ctree->tree_column != column);
3202 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3205 gdk_pixmap_ref (pixmap);
3207 gdk_pixmap_ref (mask);
3209 cell_set_pixtext (GTK_CLIST (ctree), &(GTK_CTREE_ROW (child)->row), column,
3210 text, spacing, pixmap, mask);
3211 tree_draw_row (ctree, child);
3215 gtk_ctree_set_node_info (GtkCTree *ctree,
3219 GdkPixmap *pixmap_closed,
3220 GdkBitmap *mask_closed,
3221 GdkPixmap *pixmap_opened,
3222 GdkBitmap *mask_opened,
3227 gboolean old_expanded;
3229 g_return_if_fail (ctree != NULL);
3230 g_return_if_fail (GTK_IS_CTREE (ctree));
3231 g_return_if_fail (node != NULL);
3234 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
3235 old_expanded = GTK_CTREE_ROW (node)->expanded;
3237 if (is_leaf && GTK_CTREE_ROW (node)->children)
3242 work = GTK_CTREE_ROW (node)->children;
3246 work = GTK_CTREE_ROW(work)->sibling;
3247 gtk_ctree_remove (ctree, ptr);
3251 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
3252 pixmap_opened, mask_opened, is_leaf, old_expanded);
3254 if (!is_leaf && !old_leaf)
3256 if (expanded && !old_expanded)
3257 gtk_ctree_expand (ctree, node);
3258 else if (!expanded && old_expanded)
3259 gtk_ctree_collapse (ctree, node);
3262 GTK_CTREE_ROW (node)->expanded = expanded;
3264 tree_draw_row (ctree, node);
3268 gtk_ctree_set_shift (GtkCTree *ctree,
3274 g_return_if_fail (ctree != NULL);
3275 g_return_if_fail (GTK_IS_CTREE (ctree));
3276 g_return_if_fail (row != NULL);
3278 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3281 GTK_CTREE_ROW (row)->row.cell[column].vertical = vertical;
3282 GTK_CTREE_ROW (row)->row.cell[column].horizontal = horizontal;
3284 tree_draw_row (ctree, row);
3288 gtk_ctree_get_cell_type (GtkCTree *ctree,
3292 g_return_val_if_fail (ctree != NULL, -1);
3293 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
3294 g_return_val_if_fail (row != NULL, -1);
3296 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3299 return GTK_CTREE_ROW (row)->row.cell[column].type;
3303 gtk_ctree_get_text (GtkCTree *ctree,
3308 g_return_val_if_fail (ctree != NULL, 0);
3309 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
3310 g_return_val_if_fail (row != NULL, 0);
3312 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3315 if (GTK_CTREE_ROW (row)->row.cell[column].type != GTK_CELL_TEXT)
3319 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (row)->row.cell[column])->text;
3325 gtk_ctree_get_pixmap (GtkCTree *ctree,
3331 g_return_val_if_fail (ctree != NULL, 0);
3332 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
3333 g_return_val_if_fail (row != NULL, 0);
3335 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3338 if (GTK_CTREE_ROW (row)->row.cell[column].type != GTK_CELL_PIXMAP)
3343 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(row)->row.cell[column])->pixmap;
3344 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (row)->row.cell[column])->mask;
3351 gtk_ctree_get_pixtext (GtkCTree *ctree,
3359 g_return_val_if_fail (ctree != NULL, 0);
3360 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
3361 g_return_val_if_fail (row != NULL, 0);
3363 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
3366 if (GTK_CTREE_ROW (row)->row.cell[column].type != GTK_CELL_PIXTEXT)
3370 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (row)->row.cell[column])->text;
3373 GTK_CELL_PIXTEXT (GTK_CTREE_ROW (row)->row.cell[column])->spacing;
3375 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (row)->row.cell[column])->pixmap;
3377 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (row)->row.cell[column])->mask;
3383 gtk_ctree_set_foreground (GtkCTree *ctree,
3387 g_return_if_fail (ctree != NULL);
3388 g_return_if_fail (GTK_IS_CTREE (ctree));
3389 g_return_if_fail (row != NULL);
3393 GTK_CTREE_ROW (row)->row.foreground = *color;
3394 GTK_CTREE_ROW (row)->row.fg_set = TRUE;
3397 GTK_CTREE_ROW (row)->row.fg_set = FALSE;
3399 tree_draw_row (ctree, row);
3403 gtk_ctree_set_background (GtkCTree *ctree,
3407 g_return_if_fail (ctree != NULL);
3408 g_return_if_fail (GTK_IS_CTREE (ctree));
3409 g_return_if_fail (row != NULL);
3413 GTK_CTREE_ROW (row)->row.background = *color;
3414 GTK_CTREE_ROW (row)->row.bg_set = TRUE;
3417 GTK_CTREE_ROW (row)->row.bg_set = FALSE;
3419 tree_draw_row (ctree, row);
3423 gtk_ctree_set_selection_mode (GtkCTree *ctree,
3424 GtkSelectionMode mode)
3429 gboolean thaw = FALSE;
3431 g_return_if_fail (ctree != NULL);
3432 g_return_if_fail (GTK_IS_CTREE (ctree));
3434 clist = GTK_CLIST (ctree);
3436 if (mode == clist->selection_mode)
3439 clist->selection_mode = mode;
3441 if (mode == GTK_SELECTION_MULTIPLE)
3444 selection = clist->selection;
3445 if (selection && mode == GTK_SELECTION_BROWSE)
3446 selection = selection->next;
3451 if (!GTK_CLIST_FROZEN (clist))
3453 gtk_clist_freeze (clist);
3459 work = selection->data;
3460 selection = selection->next;
3461 gtk_signal_emit (GTK_OBJECT (ctree),
3462 ctree_signals[TREE_UNSELECT_ROW], work);
3466 gtk_clist_thaw (clist);
3470 gtk_ctree_set_row_data (GtkCTree *ctree,
3474 gtk_ctree_set_row_data_full (ctree, list, data, NULL);
3478 gtk_ctree_set_row_data_full (GtkCTree *ctree,
3481 GtkDestroyNotify destroy)
3483 g_return_if_fail (ctree != NULL);
3484 g_return_if_fail (GTK_IS_CTREE (ctree));
3486 GTK_CTREE_ROW (list)->row.data = data;
3487 GTK_CTREE_ROW (list)->row.destroy = destroy;
3491 gtk_ctree_get_row_data (GtkCTree *ctree,
3494 g_return_val_if_fail (ctree != NULL, NULL);
3495 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3496 g_return_val_if_fail (list != NULL, NULL);
3498 return GTK_CTREE_ROW (list)->row.data;
3502 /***********************************************************
3503 * GtkCTree specific functions *
3504 ***********************************************************/
3508 gtk_ctree_set_indent (GtkCTree *ctree,
3511 g_return_if_fail (ctree != NULL);
3512 g_return_if_fail (GTK_IS_CTREE (ctree));
3514 if (indent != ctree->tree_indent)
3516 ctree->tree_indent = indent;
3517 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (ctree)))
3518 gtk_widget_queue_resize (GTK_WIDGET (ctree));
3523 gtk_ctree_set_reorderable (GtkCTree *ctree,
3524 gboolean reorderable)
3526 g_return_if_fail (ctree != NULL);
3527 g_return_if_fail (GTK_IS_CTREE (ctree));
3529 if (ctree->reorderable == (reorderable != 0))
3532 ctree->reorderable = (reorderable != 0);
3534 if (GTK_WIDGET_REALIZED (ctree))
3536 if (ctree->reorderable)
3537 create_xor_gc (ctree);
3539 gdk_gc_destroy (ctree->xor_gc);
3544 gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
3547 g_return_if_fail (ctree != NULL);
3548 g_return_if_fail (GTK_IS_CTREE (ctree));
3550 if (ctree->use_icons == (use_icons != 0))
3553 ctree->use_icons = (use_icons != 0);
3557 gtk_ctree_set_line_style (GtkCTree *ctree,
3558 GtkCTreeLineStyle line_style)
3560 GdkGCPrivate *private;
3562 g_return_if_fail (ctree != NULL);
3563 g_return_if_fail (GTK_IS_CTREE (ctree));
3565 if (line_style != ctree->line_style)
3567 ctree->line_style = line_style;
3569 if (!GTK_WIDGET_REALIZED (ctree))
3574 case GTK_CTREE_LINES_SOLID:
3575 ctree->draw_lines = TRUE;
3576 if (GTK_WIDGET_REALIZED (ctree))
3577 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
3580 case GTK_CTREE_LINES_DOTTED:
3581 ctree->draw_lines = TRUE;
3582 if (GTK_WIDGET_REALIZED (ctree))
3583 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
3584 GDK_LINE_ON_OFF_DASH, None, None);
3585 private = (GdkGCPrivate *) ctree->lines_gc;
3586 XSetDashes (private->xdisplay, private->xgc, 0, "\1\1", 2);
3588 case GTK_CTREE_LINES_NONE:
3589 ctree->draw_lines = FALSE;
3594 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (ctree)))
3595 gtk_widget_queue_resize (GTK_WIDGET (ctree));
3600 /***********************************************************
3601 * Tree sorting functions *
3602 ***********************************************************/
3606 gtk_ctree_set_auto_sort (GtkCTree *ctree,
3609 g_return_if_fail (ctree != NULL);
3610 g_return_if_fail (GTK_IS_CTREE (ctree));
3612 if (ctree->auto_sort == (auto_sort != 0))
3615 ctree->auto_sort = (auto_sort != 0);
3618 gtk_ctree_sort_recursive (ctree, NULL);
3622 gtk_ctree_set_compare_func (GtkCTree *ctree,
3623 GtkCTreeCompareFunc cmp_func)
3625 g_return_if_fail (ctree != NULL);
3626 g_return_if_fail (GTK_IS_CTREE (ctree));
3628 if (cmp_func == NULL)
3629 ctree->node_compare = default_compare;
3631 ctree->node_compare = cmp_func;
3635 tree_sort (GtkCTree *ctree,
3645 list_start = GTK_CTREE_ROW (node)->children;
3647 list_start = GTK_CLIST (ctree)->row_list;
3649 list_end = list_start;
3654 work = GTK_CTREE_ROW (max)->sibling;
3657 if (ctree->node_compare (ctree, work, max) > 0)
3659 work = GTK_CTREE_ROW (work)->sibling;
3661 if (max == list_start)
3662 list_start = GTK_CTREE_ROW (max)->sibling;
3663 if (max != list_end)
3665 gtk_ctree_unlink (ctree,max);
3666 gtk_ctree_link (ctree, max, node, list_end);
3673 gtk_ctree_sort_recursive (GtkCTree *ctree,
3677 gboolean thaw = FALSE;
3679 g_return_if_fail (ctree != NULL);
3680 g_return_if_fail (GTK_IS_CTREE (ctree));
3682 clist = GTK_CLIST (ctree);
3684 if (!GTK_CLIST_FROZEN (clist))
3686 gtk_clist_freeze (clist);
3690 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
3693 gtk_clist_thaw (clist);
3697 gtk_ctree_sort (GtkCTree *ctree,
3701 gboolean thaw = FALSE;
3703 g_return_if_fail (ctree != NULL);
3704 g_return_if_fail (GTK_IS_CTREE (ctree));
3706 clist = GTK_CLIST (ctree);
3708 if (!GTK_CLIST_FROZEN (clist))
3710 gtk_clist_freeze (clist);
3714 tree_sort (ctree, node, NULL);
3717 gtk_clist_thaw (clist);