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.
26 #include "gtkbindings.h"
29 #include <gdk/gdkkeysyms.h>
32 #define TAB_SIZE (PM_SIZE + 6)
33 #define CELL_SPACING 1
34 #define CLIST_OPTIMUM_SIZE 512
35 #define COLUMN_INSET 3
38 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
39 (((row) + 1) * CELL_SPACING) + \
41 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
42 ((clist)->row_height + CELL_SPACING))
43 #define COLUMN_LEFT_XPIXEL(clist, col) ((clist)->column[(col)].area.x \
45 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
47 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (GTK_OBJECT (_widget_)->klass)
50 static void gtk_ctree_class_init (GtkCTreeClass *klass);
51 static void gtk_ctree_init (GtkCTree *ctree);
52 static void gtk_ctree_destroy (GtkObject *object);
54 static void gtk_ctree_realize (GtkWidget *widget);
55 static void gtk_ctree_unrealize (GtkWidget *widget);
56 static gint gtk_ctree_button_press (GtkWidget *widget,
57 GdkEventButton *event);
58 static gint gtk_ctree_button_release (GtkWidget *widget,
59 GdkEventButton *event);
60 static gint gtk_ctree_button_motion (GtkWidget *widget,
61 GdkEventMotion *event);
62 static void draw_row (GtkCList *clist,
65 GtkCListRow *clist_row);
66 static void create_xor_gc (GtkCTree *ctree);
67 static void draw_xor_line (GtkCTree *ctree);
68 static void draw_xor_rect (GtkCTree *ctree);
69 static void create_drag_icon (GtkCTree *ctree,
71 static void tree_draw_node (GtkCTree *ctree,
73 static void set_cell_contents (GtkCList *clist,
74 GtkCListRow *clist_row,
81 static void set_node_info (GtkCTree *ctree,
85 GdkPixmap *pixmap_closed,
86 GdkBitmap *mask_closed,
87 GdkPixmap *pixmap_opened,
88 GdkBitmap *mask_opened,
91 static GtkCTreeRow *row_new (GtkCTree *ctree);
92 static void row_delete (GtkCTree *ctree,
93 GtkCTreeRow *ctree_row);
94 static void tree_delete (GtkCTree *ctree,
97 static void tree_delete_row (GtkCTree *ctree,
100 static void real_clear (GtkCList *clist);
101 static void tree_update_level (GtkCTree *ctree,
104 static void tree_select (GtkCTree *ctree,
107 static void tree_unselect (GtkCTree *ctree,
110 static void real_select_all (GtkCList *clist);
111 static void real_unselect_all (GtkCList *clist);
112 static void tree_expand (GtkCTree *ctree,
115 static void tree_collapse (GtkCTree *ctree,
118 static void tree_collapse_to_depth (GtkCTree *ctree,
121 static void tree_toggle_expansion (GtkCTree *ctree,
124 static void change_focus_row_expansion (GtkCTree *ctree,
125 GtkCTreeExpansionType expansion);
126 static void real_select_row (GtkCList *clist,
130 static void real_unselect_row (GtkCList *clist,
134 static void real_tree_select (GtkCTree *ctree,
137 static void real_tree_unselect (GtkCTree *ctree,
140 static void tree_toggle_selection (GtkCTree *ctree,
143 static void real_tree_expand (GtkCTree *ctree,
145 static void real_tree_collapse (GtkCTree *ctree,
147 static void real_tree_move (GtkCTree *ctree,
149 GtkCTreeNode *new_parent,
150 GtkCTreeNode *new_sibling);
151 static void gtk_ctree_link (GtkCTree *ctree,
153 GtkCTreeNode *parent,
154 GtkCTreeNode *sibling,
155 gboolean update_focus_row);
156 static void gtk_ctree_unlink (GtkCTree *ctree,
158 gboolean update_focus_row);
159 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
161 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
166 static void tree_sort (GtkCTree *ctree,
169 static void fake_unselect_all (GtkCList *clist,
171 static GList * selection_find (GtkCList *clist,
173 GList *row_list_element);
174 static void resync_selection (GtkCList *clist,
176 static void real_undo_selection (GtkCList *clist);
177 static void select_row_recursive (GtkCTree *ctree,
180 static gint real_insert_row (GtkCList *clist,
183 static void real_remove_row (GtkCList *clist,
185 static void real_sort_list (GtkCList *clist);
186 static void set_mouse_cursor (GtkCTree *ctree,
188 static void check_cursor (GtkCTree *ctree);
198 CHANGE_FOCUS_ROW_EXPANSION,
202 typedef void (*GtkCTreeSignal1) (GtkObject *object,
207 typedef void (*GtkCTreeSignal2) (GtkObject *object,
213 typedef void (*GtkCTreeSignal3) (GtkObject *object,
217 typedef void (*GtkCTreeSignal4) (GtkObject *object,
218 GtkCTreeExpansionType arg1,
222 static GtkCListClass *parent_class = NULL;
223 static GtkContainerClass *container_class = NULL;
224 static guint ctree_signals[LAST_SIGNAL] = {0};
228 gtk_ctree_get_type (void)
230 static GtkType ctree_type = 0;
234 GtkTypeInfo ctree_info =
238 sizeof (GtkCTreeClass),
239 (GtkClassInitFunc) gtk_ctree_class_init,
240 (GtkObjectInitFunc) gtk_ctree_init,
241 /* reserved_1 */ NULL,
242 /* reserved_2 */ NULL,
243 (GtkClassInitFunc) NULL,
246 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
253 gtk_ctree_class_init (GtkCTreeClass *klass)
255 GtkObjectClass *object_class;
256 GtkWidgetClass *widget_class;
257 GtkCListClass *clist_class;
259 object_class = (GtkObjectClass *) klass;
260 widget_class = (GtkWidgetClass *) klass;
261 container_class = (GtkContainerClass *) klass;
262 clist_class = (GtkCListClass *) klass;
264 parent_class = gtk_type_class (GTK_TYPE_CLIST);
265 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
267 ctree_signals[TREE_SELECT_ROW] =
268 gtk_signal_new ("tree_select_row",
271 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
272 gtk_marshal_NONE__POINTER_INT,
273 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
274 ctree_signals[TREE_UNSELECT_ROW] =
275 gtk_signal_new ("tree_unselect_row",
278 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
279 gtk_marshal_NONE__POINTER_INT,
280 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
281 ctree_signals[TREE_EXPAND] =
282 gtk_signal_new ("tree_expand",
285 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
286 gtk_marshal_NONE__POINTER,
287 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
288 ctree_signals[TREE_COLLAPSE] =
289 gtk_signal_new ("tree_collapse",
292 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
293 gtk_marshal_NONE__POINTER,
294 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
295 ctree_signals[TREE_MOVE] =
296 gtk_signal_new ("tree_move",
299 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
300 gtk_marshal_NONE__POINTER_POINTER_POINTER,
301 GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER,
303 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
304 gtk_signal_new ("change_focus_row_expansion",
305 GTK_RUN_LAST | GTK_RUN_ACTION,
307 GTK_SIGNAL_OFFSET (GtkCTreeClass,
308 change_focus_row_expansion),
309 gtk_marshal_NONE__ENUM,
310 GTK_TYPE_NONE, 1, GTK_TYPE_C_TREE_EXPANSION_TYPE);
312 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
314 object_class->destroy = gtk_ctree_destroy;
316 widget_class->realize = gtk_ctree_realize;
317 widget_class->unrealize = gtk_ctree_unrealize;
318 widget_class->button_press_event = gtk_ctree_button_press;
319 widget_class->button_release_event = gtk_ctree_button_release;
320 widget_class->motion_notify_event = gtk_ctree_button_motion;
322 clist_class->select_row = real_select_row;
323 clist_class->unselect_row = real_unselect_row;
324 clist_class->undo_selection = real_undo_selection;
325 clist_class->resync_selection = resync_selection;
326 clist_class->selection_find = selection_find;
327 clist_class->click_column = NULL;
328 clist_class->draw_row = draw_row;
329 clist_class->clear = real_clear;
330 clist_class->select_all = real_select_all;
331 clist_class->unselect_all = real_unselect_all;
332 clist_class->fake_unselect_all = fake_unselect_all;
333 clist_class->insert_row = real_insert_row;
334 clist_class->remove_row = real_remove_row;
335 clist_class->sort_list = real_sort_list;
336 clist_class->set_cell_contents = set_cell_contents;
338 klass->tree_select_row = real_tree_select;
339 klass->tree_unselect_row = real_tree_unselect;
340 klass->tree_expand = real_tree_expand;
341 klass->tree_collapse = real_tree_collapse;
342 klass->tree_move = real_tree_move;
343 klass->change_focus_row_expansion = change_focus_row_expansion;
346 GtkBindingSet *binding_set;
348 binding_set = gtk_binding_set_by_class (klass);
349 gtk_binding_entry_add_signal (binding_set,
351 "change_focus_row_expansion", 1,
352 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
353 gtk_binding_entry_add_signal (binding_set,
355 "change_focus_row_expansion", 1,
356 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
357 gtk_binding_entry_add_signal (binding_set,
358 GDK_KP_Add, GDK_CONTROL_MASK,
359 "change_focus_row_expansion", 1,
361 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
362 gtk_binding_entry_add_signal (binding_set,
364 "change_focus_row_expansion", 1,
365 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
366 gtk_binding_entry_add_signal (binding_set,
368 "change_focus_row_expansion", 1,
369 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
370 gtk_binding_entry_add_signal (binding_set,
371 GDK_KP_Subtract, GDK_CONTROL_MASK,
372 "change_focus_row_expansion", 1,
374 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
375 gtk_binding_entry_add_signal (binding_set,
377 "change_focus_row_expansion", 1,
378 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
379 gtk_binding_entry_add_signal (binding_set,
381 "change_focus_row_expansion", 1,
382 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
383 gtk_binding_entry_add_signal (binding_set,
384 GDK_KP_Multiply, GDK_CONTROL_MASK,
385 "change_focus_row_expansion", 1,
387 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
393 gtk_ctree_init (GtkCTree *ctree)
395 ctree->xor_gc = NULL;
396 ctree->drag_icon = NULL;
397 ctree->tree_indent = 20;
398 ctree->tree_column = 0;
399 ctree->drag_row = -1;
400 ctree->drag_source = NULL;
401 ctree->drag_target = NULL;
402 ctree->insert_pos = GTK_CTREE_POS_AS_CHILD;
403 ctree->reorderable = FALSE;
404 ctree->use_icons = TRUE;
405 ctree->in_drag = FALSE;
406 ctree->drag_rect = FALSE;
407 ctree->line_style = GTK_CTREE_LINES_SOLID;
408 ctree->drag_compare = NULL;
409 ctree->show_stub = TRUE;
413 gtk_ctree_destroy (GtkObject *object)
418 g_return_if_fail (object != NULL);
419 g_return_if_fail (GTK_IS_CTREE (object));
421 clist = GTK_CLIST (object);
423 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
425 gtk_clist_clear (GTK_CLIST (object));
427 if (clist->vscrollbar)
429 gtk_widget_unparent (clist->vscrollbar);
430 clist->vscrollbar = NULL;
432 if (clist->hscrollbar)
434 gtk_widget_unparent (clist->hscrollbar);
435 clist->hscrollbar = NULL;
438 for (i = 0; i < clist->columns; i++)
439 if (clist->column[i].button)
441 gtk_widget_unparent (clist->column[i].button);
442 clist->column[i].button = NULL;
445 if (GTK_OBJECT_CLASS (container_class)->destroy)
446 (*GTK_OBJECT_CLASS (container_class)->destroy) (object);
450 gtk_ctree_realize (GtkWidget *widget)
455 g_return_if_fail (widget != NULL);
456 g_return_if_fail (GTK_IS_CTREE (widget));
458 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
460 ctree = GTK_CTREE (widget);
462 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
463 values.background = widget->style->bg[GTK_STATE_NORMAL];
464 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
465 values.line_style = GDK_LINE_SOLID;
466 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
473 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
475 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
476 GDK_LINE_ON_OFF_DASH, None, None);
477 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
480 if (ctree->reorderable)
481 create_xor_gc (ctree);
485 gtk_ctree_unrealize (GtkWidget *widget)
489 g_return_if_fail (widget != NULL);
490 g_return_if_fail (GTK_IS_CTREE (widget));
492 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
494 ctree = GTK_CTREE (widget);
496 gdk_gc_destroy (ctree->lines_gc);
498 if (ctree->reorderable)
499 gdk_gc_destroy (ctree->xor_gc);
503 gtk_ctree_button_press (GtkWidget *widget,
504 GdkEventButton *event)
509 g_return_val_if_fail (widget != NULL, FALSE);
510 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
511 g_return_val_if_fail (event != NULL, FALSE);
513 ctree = GTK_CTREE (widget);
514 clist = GTK_CLIST (widget);
516 if (event->window == clist->clist_window)
518 gboolean collapse_expand = FALSE;
528 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
531 if (event->button == 2)
532 ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
534 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
536 if (ctree->reorderable && event->button == 2 && !ctree->in_drag &&
539 gdk_pointer_grab (event->window, FALSE,
540 GDK_POINTER_MOTION_HINT_MASK |
541 GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
542 NULL, NULL, event->time);
543 gtk_grab_add (widget);
544 ctree->in_drag = TRUE;
545 ctree->drag_source = work;
546 ctree->drag_target = NULL;
549 else if (event->button == 1 &&
550 (GTK_CTREE_ROW (work)->children &&
551 (event->type == GDK_2BUTTON_PRESS ||
552 ctree_is_hot_spot (ctree, work, row, x, y))))
554 if (GTK_CTREE_ROW (work)->expanded)
555 gtk_ctree_collapse (ctree, work);
557 gtk_ctree_expand (ctree, work);
559 collapse_expand = TRUE;
561 if (event->button == 1)
563 gint old_row = clist->focus_row;
564 gboolean no_focus_row = FALSE;
566 switch (clist->selection_mode)
568 case GTK_SELECTION_MULTIPLE:
569 case GTK_SELECTION_SINGLE:
570 if (!collapse_expand)
573 if (clist->focus_row == -1)
579 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
580 gdk_pointer_grab (clist->clist_window, FALSE,
581 GDK_POINTER_MOTION_HINT_MASK |
582 GDK_BUTTON1_MOTION_MASK |
583 GDK_BUTTON_RELEASE_MASK,
584 NULL, NULL, event->time);
585 gtk_grab_add (widget);
587 if (GTK_CLIST_ADD_MODE (clist))
589 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
590 if (GTK_WIDGET_HAS_FOCUS (widget))
592 gtk_widget_draw_focus (widget);
593 gdk_gc_set_line_attributes (clist->xor_gc, 1,
594 GDK_LINE_SOLID, 0, 0);
595 clist->focus_row = row;
596 gtk_widget_draw_focus (widget);
600 gdk_gc_set_line_attributes (clist->xor_gc, 1,
601 GDK_LINE_SOLID, 0, 0);
602 clist->focus_row = row;
605 else if (row != clist->focus_row)
607 if (GTK_WIDGET_HAS_FOCUS (widget))
609 gtk_widget_draw_focus (widget);
610 clist->focus_row = row;
611 gtk_widget_draw_focus (widget);
614 clist->focus_row = row;
617 if (!GTK_WIDGET_HAS_FOCUS (widget))
618 gtk_widget_grab_focus (widget);
627 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
631 gtk_ctree_button_motion (GtkWidget *widget,
632 GdkEventMotion *event)
639 gint insert_pos = GTK_CTREE_POS_AS_CHILD;
641 g_return_val_if_fail (widget != NULL, FALSE);
642 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
643 g_return_val_if_fail (event != NULL, FALSE);
645 ctree = GTK_CTREE (widget);
646 clist = GTK_CLIST (widget);
648 if (GTK_CLIST_IN_DRAG (clist))
649 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
652 if (event->window == clist->clist_window &&
653 ctree->in_drag && ctree->reorderable)
655 GdkModifierType modmask;
662 gdk_window_get_pointer (event->window, &x, &y, NULL);
664 /* delayed drag start */
665 if (!ctree->drag_target &&
666 y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
667 y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
669 GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
671 if (ctree->use_icons)
673 if (!ctree->drag_icon)
674 create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
677 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
678 gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
679 root_y - ctree->icon_height);
683 /* out of bounds check */
684 if (x < 0 || y < -3 || x > clist->clist_window_width ||
685 y > clist->clist_window_height + 3 ||
686 y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
688 if (ctree->drag_row >= 0)
690 if (ctree->drag_rect)
692 draw_xor_rect (ctree);
693 ctree->drag_rect = FALSE;
696 draw_xor_line (ctree);
697 ctree->drag_row = -1;
700 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
704 row = ROW_FROM_YPIXEL (clist, y);
706 /* re-calculate target (mouse left the window) */
707 if (ctree->drag_target && ctree->drag_row == -1)
708 ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row));
710 if (y < 0 || y > clist->clist_window_height ||
711 ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
712 || row >= clist->rows)
713 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
716 if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
717 insert_pos = GTK_CTREE_POS_BEFORE;
718 else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y
719 < clist->row_height / 4)
720 insert_pos = GTK_CTREE_POS_AFTER;
722 if (row != ctree->drag_row ||
723 (row == ctree->drag_row && ctree->insert_pos != insert_pos))
725 if (insert_pos != GTK_CTREE_POS_AS_CHILD)
727 if (ctree->drag_row >= 0)
729 if (ctree->drag_rect)
731 draw_xor_rect (ctree);
732 ctree->drag_rect = FALSE;
735 draw_xor_line (ctree);
737 ctree->insert_pos = insert_pos;
739 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
740 ctree->drag_row = row;
741 draw_xor_line (ctree);
744 else if (ctree->drag_target &&
745 !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
747 if (ctree->drag_row >= 0)
749 if (ctree->drag_rect)
750 draw_xor_rect (ctree);
752 draw_xor_line (ctree);
754 ctree->drag_rect = TRUE;
755 ctree->insert_pos = insert_pos;
757 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
758 ctree->drag_row = row;
759 draw_xor_rect (ctree);
764 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
768 gtk_ctree_button_release (GtkWidget *widget,
769 GdkEventButton *event)
774 g_return_val_if_fail (widget != NULL, FALSE);
775 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
776 g_return_val_if_fail (event != NULL, FALSE);
778 ctree = GTK_CTREE (widget);
779 clist = GTK_CLIST (widget);
781 if (event->button == 2 && clist->anchor == -1)
783 gtk_grab_remove (widget);
784 gdk_pointer_ungrab (event->time);
786 ctree->in_drag = FALSE;
788 set_mouse_cursor(ctree, TRUE);
790 if (ctree->use_icons && ctree->drag_icon)
792 gdk_window_destroy (ctree->drag_icon);
793 ctree->drag_icon = NULL;
796 if (ctree->drag_row >= 0)
798 if (ctree->drag_rect)
800 draw_xor_rect (ctree);
801 ctree->drag_rect = FALSE;
804 draw_xor_line (ctree);
805 ctree->drag_row = -1;
808 /* nop if out of bounds / source == target */
809 if (event->x < 0 || event->y < -3 ||
810 event->x > clist->clist_window_width ||
811 event->y > clist->clist_window_height + 3 ||
812 ctree->drag_target == ctree->drag_source ||
814 return GTK_WIDGET_CLASS (parent_class)->button_release_event
817 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
818 !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
821 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
823 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
825 if (!ctree->drag_compare ||
826 ctree->drag_compare (ctree,
828 GTK_CTREE_ROW (ctree->drag_target)->parent,
829 GTK_CTREE_ROW (ctree->drag_target)->sibling))
830 gtk_signal_emit (GTK_OBJECT (ctree),
831 ctree_signals[TREE_MOVE],
833 GTK_CTREE_ROW (ctree->drag_target)->parent,
834 GTK_CTREE_ROW (ctree->drag_target)->sibling);
836 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
838 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
840 if (!ctree->drag_compare ||
841 ctree->drag_compare (ctree,
843 GTK_CTREE_ROW (ctree->drag_target)->parent,
845 gtk_signal_emit (GTK_OBJECT (ctree),
846 ctree_signals[TREE_MOVE],
848 GTK_CTREE_ROW (ctree->drag_target)->parent,
851 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
853 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
855 if (!ctree->drag_compare ||
856 ctree->drag_compare (ctree,
859 GTK_CTREE_ROW (ctree->drag_target)->children))
860 gtk_signal_emit (GTK_OBJECT (ctree),
861 ctree_signals[TREE_MOVE],
864 GTK_CTREE_ROW (ctree->drag_target)->children);
867 ctree->drag_source = NULL;
868 ctree->drag_target = NULL;
870 else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) &&
871 (clist->selection_mode == GTK_SELECTION_SINGLE ||
872 clist->selection_mode == GTK_SELECTION_MULTIPLE))
878 if (gtk_clist_get_selection_info
879 (clist, event->x, event->y, &row, &column))
881 if (clist->anchor == clist->focus_row &&
882 (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row))))
883 tree_toggle_selection (ctree, work, column);
887 return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
891 create_drag_icon (GtkCTree *ctree,
896 GdkWindow *window = NULL;
897 GdkWindowAttr attributes;
898 gint attributes_mask;
901 GdkModifierType modmask;
905 clist = GTK_CLIST (ctree);
906 widget = GTK_WIDGET (ctree);
908 if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap))
910 mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
912 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
913 gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
915 attributes.window_type = GDK_WINDOW_TEMP;
916 attributes.x = root_x - ctree->icon_width / 2;
917 attributes.y = root_y - ctree->icon_height;
918 attributes.width = ctree->icon_width;
919 attributes.height = ctree->icon_height;
920 attributes.wclass = GDK_INPUT_OUTPUT;
921 attributes.visual = gtk_widget_get_visual (widget);
922 attributes.colormap = gtk_widget_get_colormap (widget);
923 attributes.event_mask = gtk_widget_get_events (widget);
925 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
927 window = gdk_window_new (widget->window, &attributes, attributes_mask);
928 gdk_window_set_back_pixmap (window, pixmap, FALSE);
930 gdk_window_shape_combine_mask (window, mask, 0, 0);
931 gdk_window_show (window);
933 ctree->drag_icon = window;
937 create_xor_gc (GtkCTree *ctree)
942 clist = GTK_CLIST (ctree);
944 values.foreground = GTK_WIDGET (clist)->style->bg[GTK_STATE_NORMAL];
945 values.function = GDK_XOR;
946 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
947 ctree->xor_gc = gdk_gc_new_with_values (clist->clist_window, &values,
951 gdk_gc_set_line_attributes (ctree->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
953 gdk_gc_set_dashes (ctree->xor_gc, 0, "\2\2", 2);
957 draw_xor_line (GtkCTree *ctree)
963 clist = GTK_CLIST (ctree);
965 level = GTK_CTREE_ROW (ctree->drag_target)->level;
967 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
968 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
970 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
972 switch (clist->column[ctree->tree_column].justification)
974 case GTK_JUSTIFY_CENTER:
975 case GTK_JUSTIFY_FILL:
976 case GTK_JUSTIFY_LEFT:
977 if (ctree->tree_column > 0)
978 gdk_draw_line (clist->clist_window, ctree->xor_gc,
979 COLUMN_LEFT_XPIXEL(clist, 0), y,
980 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
981 clist->column[ctree->tree_column - 1].area.width, y);
983 gdk_draw_line (clist->clist_window, ctree->xor_gc,
984 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
985 ctree->tree_indent * level -
986 (ctree->tree_indent - PM_SIZE) / 2, y,
987 GTK_WIDGET (ctree)->allocation.width, y);
989 case GTK_JUSTIFY_RIGHT:
990 if (ctree->tree_column < clist->columns - 1)
991 gdk_draw_line (clist->clist_window, ctree->xor_gc,
992 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
993 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
994 clist->column[clist->columns - 1].area.width, y);
996 gdk_draw_line (clist->clist_window, ctree->xor_gc,
997 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
998 + clist->column[ctree->tree_column].area.width
999 - ctree->tree_indent * level +
1000 (ctree->tree_indent - PM_SIZE) / 2, y);
1006 draw_xor_rect (GtkCTree *ctree)
1014 clist = GTK_CLIST (ctree);
1016 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1018 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1020 switch (clist->column[ctree->tree_column].justification)
1022 case GTK_JUSTIFY_CENTER:
1023 case GTK_JUSTIFY_FILL:
1024 case GTK_JUSTIFY_LEFT:
1025 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1026 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
1028 points[3].x = points[0].x;
1029 points[3].y = y - clist->row_height - 1;
1030 points[1].x = clist->clist_window_width - 1;
1031 points[1].y = points[0].y;
1032 points[2].x = points[1].x;
1033 points[2].y = points[3].y;
1035 for (i = 0; i < 3; i++)
1036 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1037 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
1039 if (ctree->tree_column > 0)
1041 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1042 clist->column[ctree->tree_column - 1].area.width ;
1044 points[3].x = points[0].x;
1045 points[3].y = y - clist->row_height - 1;
1047 points[1].y = points[0].y;
1049 points[2].y = points[3].y;
1051 for (i = 0; i < 3; i++)
1052 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1053 points[i].x, points[i].y, points[i+1].x,
1057 case GTK_JUSTIFY_RIGHT:
1058 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
1059 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
1060 clist->column[ctree->tree_column].area.width;
1062 points[3].x = points[0].x;
1063 points[3].y = y - clist->row_height - 1;
1065 points[1].y = points[0].y;
1067 points[2].y = points[3].y;
1069 for (i = 0; i < 3; i++)
1070 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1071 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
1073 if (ctree->tree_column < clist->columns - 1)
1075 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
1077 points[3].x = points[0].x;
1078 points[3].y = y - clist->row_height - 1;
1079 points[1].x = clist->clist_window_width - 1;
1080 points[1].y = points[0].y;
1081 points[2].x = points[1].x;
1082 points[2].y = points[3].y;
1084 for (i = 0; i < 3; i++)
1085 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1086 points[i].x, points[i].y, points[i+1].x,
1094 draw_row (GtkCList *clist,
1097 GtkCListRow *clist_row)
1103 GdkRectangle row_rectangle;
1104 GdkRectangle cell_rectangle;
1105 GdkRectangle clip_rectangle;
1106 GdkRectangle intersect_rectangle;
1109 gint i, offset = 0, width, height, pixmap_width = 0, string_width = 0;
1110 gint xsrc, ysrc, xdest = 0, ydest;
1111 gboolean need_redraw = TRUE;
1112 gboolean draw_pixmap = FALSE;
1114 g_return_if_fail (clist != NULL);
1116 /* bail now if we arn't drawable yet */
1117 if (!GTK_WIDGET_DRAWABLE (clist))
1120 if (row < 0 || row >= clist->rows)
1123 widget = GTK_WIDGET (clist);
1124 ctree = GTK_CTREE (clist);
1126 /* if the function is passed the pointer to the row instead of null,
1127 * it avoids this expensive lookup */
1129 clist_row = (g_list_nth (clist->row_list, row))->data;
1131 /* rectangle of the entire row */
1132 row_rectangle.x = 0;
1133 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1134 row_rectangle.width = clist->clist_window_width;
1135 row_rectangle.height = clist->row_height;
1137 /* rectangle of the cell spacing above the row */
1138 cell_rectangle.x = 0;
1139 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1140 cell_rectangle.width = row_rectangle.width;
1141 cell_rectangle.height = CELL_SPACING;
1143 /* rectangle used to clip drawing operations, it's y and height
1144 * positions only need to be set once, so we set them once here.
1145 * the x and width are set withing the drawing loop below once per
1147 clip_rectangle.y = row_rectangle.y;
1148 clip_rectangle.height = row_rectangle.height;
1150 /* select GC for background rectangle */
1151 if (clist_row->state == GTK_STATE_SELECTED)
1153 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
1154 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
1158 if (clist_row->fg_set)
1160 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1161 fg_gc = clist->fg_gc;
1164 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
1166 if (clist_row->bg_set)
1168 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1169 bg_gc = clist->bg_gc;
1172 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1176 /* draw the cell borders and background */
1179 if (gdk_rectangle_intersect (area, &cell_rectangle,
1180 &intersect_rectangle))
1181 gdk_draw_rectangle (clist->clist_window,
1182 widget->style->base_gc[GTK_STATE_NORMAL],
1184 intersect_rectangle.x,
1185 intersect_rectangle.y,
1186 intersect_rectangle.width,
1187 intersect_rectangle.height);
1189 /* the last row has to clear it's bottom cell spacing too */
1190 if (clist_row == clist->row_list_end->data)
1192 cell_rectangle.y += clist->row_height + CELL_SPACING;
1194 if (gdk_rectangle_intersect (area, &cell_rectangle,
1195 &intersect_rectangle))
1196 gdk_draw_rectangle (clist->clist_window,
1197 widget->style->base_gc[GTK_STATE_NORMAL],
1199 intersect_rectangle.x,
1200 intersect_rectangle.y,
1201 intersect_rectangle.width,
1202 intersect_rectangle.height);
1205 if (gdk_rectangle_intersect
1206 (area, &row_rectangle, &intersect_rectangle))
1208 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
1209 gdk_draw_rectangle (clist->clist_window,
1212 intersect_rectangle.x,
1213 intersect_rectangle.y,
1214 intersect_rectangle.width,
1215 intersect_rectangle.height);
1217 gdk_window_clear_area (clist->clist_window,
1218 intersect_rectangle.x,
1219 intersect_rectangle.y,
1220 intersect_rectangle.width,
1221 intersect_rectangle.height);
1224 need_redraw = FALSE;
1228 gdk_draw_rectangle (clist->clist_window,
1229 widget->style->base_gc[GTK_STATE_NORMAL],
1233 cell_rectangle.width,
1234 cell_rectangle.height);
1236 /* the last row has to clear it's bottom cell spacing too */
1237 if (clist_row == clist->row_list_end->data)
1239 cell_rectangle.y += clist->row_height + CELL_SPACING;
1241 gdk_draw_rectangle (clist->clist_window,
1242 widget->style->base_gc[GTK_STATE_NORMAL],
1246 cell_rectangle.width,
1247 cell_rectangle.height);
1250 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
1251 gdk_draw_rectangle (clist->clist_window,
1256 row_rectangle.width,
1257 row_rectangle.height);
1259 gdk_window_clear_area (clist->clist_window,
1262 row_rectangle.width,
1263 row_rectangle.height);
1266 /* iterate and draw all the columns (row cells) and draw their contents */
1267 for (i = 0; i < clist->columns; i++)
1270 if (!need_redraw && ctree->tree_column != i)
1273 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1274 clip_rectangle.width = clist->column[i].area.width;
1276 /* calculate clipping region */
1277 if (i == ctree->tree_column)
1279 clip_rectangle.y -= CELL_SPACING;
1280 clip_rectangle.height += CELL_SPACING;
1283 if (i == ctree->tree_column)
1286 if (clist_row->state == GTK_STATE_SELECTED)
1288 gdk_gc_set_foreground (ctree->lines_gc,
1289 >K_WIDGET (ctree)->style->
1290 fg[GTK_STATE_SELECTED]);
1291 gdk_gc_set_background (ctree->lines_gc,
1292 >K_WIDGET (ctree)->style->
1293 bg[GTK_STATE_SELECTED]);
1297 gdk_gc_set_foreground (ctree->lines_gc,
1298 >K_WIDGET (ctree)->style->
1299 fg[GTK_STATE_NORMAL]);
1300 if (clist_row->bg_set)
1301 gdk_gc_set_background (ctree->lines_gc,
1302 &clist_row->background);
1305 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1307 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1309 xdest = clip_rectangle.x + clip_rectangle.width - 1 -
1310 (((GtkCTreeRow *) clist_row)->level - 1) *
1313 gdk_draw_line (clist->clist_window,
1316 row_rectangle.y - 1,
1317 MAX (xdest - TAB_SIZE, clip_rectangle.x - 1),
1318 row_rectangle.y - 1);
1320 if (clist_row == clist->row_list_end->data)
1322 (clist->clist_window,
1325 row_rectangle.y + clist->row_height,
1326 MAX (clip_rectangle.x + clip_rectangle.width -
1328 (((GtkCTreeRow *) clist_row)->level > 1) *
1329 MIN (ctree->tree_indent / 2, TAB_SIZE),
1330 clip_rectangle.x - 1),
1331 row_rectangle.y + clist->row_height);
1333 if (clist_row->state != GTK_STATE_SELECTED)
1335 (clist->clist_window,
1336 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1338 clip_rectangle.x + clip_rectangle.width,
1340 CELL_SPACING + COLUMN_INSET,
1341 row_rectangle.height);
1345 xdest = clip_rectangle.x +
1346 (((GtkCTreeRow *) clist_row)->level - 1) *
1349 gdk_draw_line (clist->clist_window,
1351 MIN (xdest + TAB_SIZE,
1352 clip_rectangle.x + clip_rectangle.width),
1353 row_rectangle.y - 1,
1354 clist->clist_window_width,
1355 row_rectangle.y - 1);
1357 if (clist_row == clist->row_list_end->data)
1359 (clist->clist_window, ctree->lines_gc,
1360 MIN (clip_rectangle.x + TAB_SIZE +
1361 (((GtkCTreeRow *) clist_row)->level > 1) *
1362 MIN (ctree->tree_indent / 2, TAB_SIZE),
1363 clip_rectangle.x + clip_rectangle.width),
1364 row_rectangle.y + clist->row_height,
1365 clist->clist_window_width,
1366 row_rectangle.y + clist->row_height);
1368 if (clist_row->state != GTK_STATE_SELECTED)
1370 (clist->clist_window,
1371 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1373 clip_rectangle.x - CELL_SPACING - COLUMN_INSET,
1375 CELL_SPACING + COLUMN_INSET,
1376 row_rectangle.height);
1383 rect = &clip_rectangle;
1388 if (!gdk_rectangle_intersect (area, &clip_rectangle,
1389 &intersect_rectangle))
1391 rect = &intersect_rectangle;
1394 /* calculate real width for column justification */
1395 switch (clist_row->cell[i].type)
1397 case GTK_CELL_EMPTY:
1402 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1403 GTK_CELL_TEXT (clist_row->cell[i])->text);
1406 case GTK_CELL_PIXMAP:
1407 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1409 pixmap_width = width;
1412 case GTK_CELL_PIXTEXT:
1413 if (i == ctree->tree_column)
1418 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1419 gdk_window_get_size (GTK_CELL_PIXTEXT
1420 (clist_row->cell[i])->pixmap,
1423 pixmap_width = width;
1424 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1426 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
1427 string_width += gdk_string_width
1428 (GTK_WIDGET (clist)->style->font,
1429 GTK_CELL_PIXTEXT(clist_row->cell[i])->text);
1431 width += string_width +
1432 ((GtkCTreeRow *)clist_row)->level * ctree->tree_indent;
1436 gdk_window_get_size (GTK_CELL_PIXTEXT
1437 (clist_row->cell[i])->pixmap,
1439 pixmap_width = width;
1440 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1441 width += gdk_string_width (GTK_WIDGET (clist)->style->font,
1443 (clist_row->cell[i])->text);
1447 case GTK_CELL_WIDGET:
1457 switch (clist->column[i].justification)
1459 case GTK_JUSTIFY_LEFT:
1460 offset = clip_rectangle.x;
1463 case GTK_JUSTIFY_RIGHT:
1464 offset = (clip_rectangle.x + clip_rectangle.width) - width;
1467 case GTK_JUSTIFY_CENTER:
1468 offset = (clip_rectangle.x + (clip_rectangle.width / 2))
1472 case GTK_JUSTIFY_FILL:
1473 offset = (clip_rectangle.x + (clip_rectangle.width / 2))
1482 if (i == ctree->tree_column)
1488 GtkCTreeNode *work2;
1502 yoffset = (clip_rectangle.height - PM_SIZE) / 2;
1503 xoffset = (ctree->tree_indent - PM_SIZE) / 2;
1504 ycenter = clip_rectangle.y + (clip_rectangle.height / 2);
1505 ydest = ycenter - height / 2 + clist_row->cell[i].vertical;
1507 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1508 gdk_gc_set_clip_rectangle (fg_gc, rect);
1509 if (ctree->line_style != GTK_CTREE_LINES_NONE)
1511 gdk_gc_set_clip_origin (ctree->lines_gc, 0, 0);
1512 gdk_gc_set_clip_rectangle (ctree->lines_gc, rect);
1515 switch (clist->column[i].justification)
1517 case GTK_JUSTIFY_CENTER:
1518 case GTK_JUSTIFY_FILL:
1519 offset = clip_rectangle.x;
1520 case GTK_JUSTIFY_LEFT:
1522 xdest = clip_rectangle.x - xoffset +
1523 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1524 xcenter = xdest + (ctree->tree_indent / 2);
1526 switch (ctree->line_style)
1528 case GTK_CTREE_LINES_NONE:
1530 case GTK_CTREE_LINES_TABBED:
1531 xdest = clip_rectangle.x +
1532 (((GtkCTreeRow *) clist_row)->level - 1) *
1534 xcenter = xdest + TAB_SIZE;
1536 gdk_gc_set_clip_origin (clist->bg_gc, 0, 0);
1537 gdk_gc_set_clip_rectangle (clist->bg_gc, rect);
1539 gdk_gc_set_clip_origin
1540 (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0);
1541 gdk_gc_set_clip_rectangle
1542 (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect);
1544 work = ((GtkCTreeRow *)clist_row)->parent;
1545 next_level = ((GtkCTreeRow *)clist_row)->level;
1547 if (!(((GtkCTreeRow *)clist_row)->sibling ||
1548 (((GtkCTreeRow *)clist_row)->children &&
1549 ((GtkCTreeRow *)clist_row)->expanded)))
1551 work2 = gtk_ctree_find_node_ptr
1552 (ctree, (GtkCTreeRow *) clist_row);
1554 if (GTK_CTREE_NODE_NEXT (work2))
1556 GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level;
1563 xcenter -= ctree->tree_indent;
1565 if (GTK_CTREE_ROW(work)->row.bg_set)
1567 gdk_gc_set_foreground
1569 &(GTK_CTREE_ROW(work)->row.background));
1570 mbg_gc = clist->bg_gc;
1573 mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1575 if (clist_row->state != GTK_STATE_SELECTED)
1576 gdk_draw_rectangle (clist->clist_window, mbg_gc, TRUE,
1578 ctree->tree_indent, rect->height);
1580 if (next_level > GTK_CTREE_ROW (work)->level)
1582 (clist->clist_window, ctree->lines_gc,
1584 xcenter, rect->y + rect->height);
1587 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1588 xcenter, clip_rectangle.y,
1591 in = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1593 if (clist_row->state != GTK_STATE_SELECTED)
1595 work2 = GTK_CTREE_ROW (work)->parent;
1597 if (work2 && GTK_CTREE_ROW (work2)->row.bg_set)
1599 gdk_gc_set_foreground
1601 &(GTK_CTREE_ROW (work2)->row.background));
1604 (clist->clist_window, clist->bg_gc, TRUE,
1608 row_rectangle.height / 2 + 1);
1610 if (GTK_CTREE_ROW (work)->row.bg_set)
1611 gdk_gc_set_foreground
1613 &(GTK_CTREE_ROW (work)->row.background));
1617 (clist->clist_window,
1618 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1623 row_rectangle.height / 2 + 1);
1625 gdk_draw_arc (clist->clist_window, mbg_gc,
1627 xcenter, clip_rectangle.y,
1628 in, clist->row_height,
1632 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1634 xcenter, clip_rectangle.y,
1635 in, clist->row_height,
1638 work = GTK_CTREE_ROW (work)->parent;
1641 if (clist_row->state != GTK_STATE_SELECTED)
1643 (clist->clist_window,
1644 widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
1645 clip_rectangle.x, row_rectangle.y,
1646 TAB_SIZE, row_rectangle.height);
1648 xcenter = xdest + (ctree->tree_indent / 2);
1650 if (clist_row->bg_set)
1651 gdk_gc_set_foreground
1652 (clist->bg_gc, &clist_row->background);
1654 if (((GtkCTreeRow *)clist_row)->is_leaf)
1656 points[0].x = xdest + TAB_SIZE;
1657 points[0].y = row_rectangle.y - 1;
1659 points[1].x = points[0].x - 4;
1660 points[1].y = points[0].y;
1662 points[2].x = points[1].x - 2;
1663 points[2].y = points[1].y + 3;
1665 points[3].x = points[2].x;
1666 points[3].y = points[2].y + clist->row_height - 5;
1668 points[4].x = points[3].x + 2;
1669 points[4].y = points[3].y + 3;
1671 points[5].x = points[4].x + 4;
1672 points[5].y = points[4].y;
1674 if (clist_row->state != GTK_STATE_SELECTED)
1675 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE,
1678 gdk_draw_lines (clist->clist_window, ctree->lines_gc,
1683 if (clist_row->state != GTK_STATE_SELECTED)
1684 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1685 xdest, row_rectangle.y - 1,
1686 2 * TAB_SIZE, clist->row_height,
1689 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1691 xdest, row_rectangle.y - 1,
1692 2 * TAB_SIZE, clist->row_height,
1697 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1698 gdk_gc_set_clip_rectangle (clist->bg_gc, NULL);
1699 gdk_gc_set_clip_rectangle
1700 (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL);
1704 xcenter = xdest + (ctree->tree_indent / 2);
1705 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1707 offset_x += abs ((clip_rectangle.x + clist->hoffset) %
1709 offset_y = abs ((clip_rectangle.y + clist->voffset) % 2);
1712 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1714 (ctree->show_stub ||
1715 clist->row_list->data != clist_row) ?
1716 clip_rectangle.y + offset_y : ycenter,
1718 (((GtkCTreeRow *)clist_row)->sibling) ?
1719 rect->y + rect->height : ycenter);
1721 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1722 xcenter + offset_x, ycenter,
1723 xcenter + PM_SIZE / 2 + 2, ycenter);
1725 work = ((GtkCTreeRow *)clist_row)->parent;
1728 xcenter -= ctree->tree_indent;
1729 if (GTK_CTREE_ROW (work)->sibling)
1730 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1731 xcenter, clip_rectangle.y + offset_y,
1732 xcenter, rect->y + rect->height);
1733 work = GTK_CTREE_ROW (work)->parent;
1735 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1739 if (((GtkCTreeRow *)clist_row)->children)
1741 if (clist_row->state == GTK_STATE_SELECTED)
1743 if (clist_row->fg_set)
1746 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
1752 (clist)->style->fg_gc[GTK_STATE_SELECTED];
1756 gdk_gc_set_clip_rectangle (cgc, rect);
1758 switch (ctree->line_style)
1760 case GTK_CTREE_LINES_NONE:
1761 if (!((GtkCTreeRow *)clist_row)->expanded)
1763 points[0].x = xdest + xoffset + (PM_SIZE+2) / 6 + 2;
1764 points[0].y = clip_rectangle.y + yoffset - 1;
1765 points[1].x = points[0].x;
1766 points[1].y = points[0].y + (PM_SIZE+2);
1767 points[2].x = points[0].x + 2 * (PM_SIZE+2) / 3 - 1;
1768 points[2].y = points[0].y + (PM_SIZE+2) / 2;
1772 points[0].x = xdest + xoffset;
1773 points[0].y = clip_rectangle.y + yoffset
1775 points[1].x = points[0].x + (PM_SIZE+2);
1776 points[1].y = points[0].y;
1777 points[2].x = points[0].x + (PM_SIZE+2) / 2;
1778 points[2].y = clip_rectangle.y + yoffset +
1779 2 * (PM_SIZE+2) / 3;
1782 gdk_draw_polygon (clist->clist_window,
1783 GTK_WIDGET (clist)->style->
1784 fg_gc[GTK_STATE_SELECTED],
1786 gdk_draw_polygon (clist->clist_window, tgc, FALSE,
1789 case GTK_CTREE_LINES_TABBED:
1790 xcenter = xdest + PM_SIZE + 2;
1791 gdk_draw_arc (clist->clist_window,
1792 GTK_WIDGET (clist)->style->
1793 fg_gc[GTK_STATE_SELECTED],
1795 xcenter - PM_SIZE/2,
1796 ycenter - PM_SIZE/2,
1797 PM_SIZE, PM_SIZE, 0, 360 * 64);
1799 gdk_draw_line (clist->clist_window, tgc,
1805 if (!((GtkCTreeRow *)clist_row)->expanded)
1806 gdk_draw_line (clist->clist_window, tgc,
1807 xcenter, clip_rectangle.y + yoffset + 2,
1809 clip_rectangle.y + yoffset + PM_SIZE-2);
1813 (clist->clist_window,
1814 GTK_WIDGET (clist)->style->fg_gc[GTK_STATE_SELECTED],
1817 clip_rectangle.y + yoffset,
1820 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
1822 clip_rectangle.y + yoffset,
1825 gdk_draw_line (clist->clist_window, tgc,
1826 xdest + xoffset + 2, ycenter,
1827 xdest + xoffset + PM_SIZE - 2, ycenter);
1829 if (!((GtkCTreeRow *)clist_row)->expanded)
1831 xcenter = xdest + (ctree->tree_indent / 2);
1832 gdk_draw_line (clist->clist_window, tgc,
1834 clip_rectangle.y + yoffset + 2,
1836 clip_rectangle.y + yoffset +
1842 gdk_gc_set_clip_rectangle (cgc, NULL);
1845 xdest += offset - clip_rectangle.x + ctree->tree_indent +
1846 clist_row->cell[i].horizontal;
1848 if (pixmap_width && xdest + pixmap_width >= rect->x &&
1849 xdest <= rect->x + rect->width)
1854 case GTK_JUSTIFY_RIGHT:
1857 xdest = clip_rectangle.x + clip_rectangle.width + xoffset - 1 -
1858 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1860 switch (ctree->line_style)
1862 case GTK_CTREE_LINES_NONE:
1864 case GTK_CTREE_LINES_TABBED:
1865 xdest = clip_rectangle.x + clip_rectangle.width - 1
1866 - (((GtkCTreeRow *) clist_row)->level - 1)
1867 * ctree->tree_indent;
1868 xcenter = xdest - TAB_SIZE;
1870 gdk_gc_set_clip_origin (clist->bg_gc, 0, 0);
1871 gdk_gc_set_clip_rectangle (clist->bg_gc, rect);
1873 gdk_gc_set_clip_origin
1874 (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0);
1875 gdk_gc_set_clip_rectangle
1876 (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect);
1878 work = ((GtkCTreeRow *)clist_row)->parent;
1879 next_level = ((GtkCTreeRow *)clist_row)->level;
1881 if (!(((GtkCTreeRow *)clist_row)->sibling ||
1882 (((GtkCTreeRow *)clist_row)->children &&
1883 ((GtkCTreeRow *)clist_row)->expanded)))
1885 work2 = gtk_ctree_find_node_ptr
1886 (ctree, (GtkCTreeRow *) clist_row);
1888 if (GTK_CTREE_NODE_NEXT (work2))
1890 GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level;
1897 xcenter += ctree->tree_indent;
1899 if (GTK_CTREE_ROW(work)->row.bg_set)
1901 gdk_gc_set_foreground
1903 &(GTK_CTREE_ROW (work)->row.background));
1904 mbg_gc = clist->bg_gc;
1907 mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1909 if (clist_row->state != GTK_STATE_SELECTED)
1910 gdk_draw_rectangle (clist->clist_window,
1912 xcenter - ctree->tree_indent + 1,
1917 if (next_level > GTK_CTREE_ROW (work)->level)
1919 (clist->clist_window, ctree->lines_gc,
1921 xcenter, rect->y + rect->height);
1924 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1925 xcenter, clip_rectangle.y,
1928 in = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1930 if (clist_row->state != GTK_STATE_SELECTED)
1932 work2 = GTK_CTREE_ROW (work)->parent;
1934 if (work2 && GTK_CTREE_ROW (work2)->row.bg_set)
1936 gdk_gc_set_foreground
1938 &(GTK_CTREE_ROW (work2)->row.background));
1941 (clist->clist_window, clist->bg_gc, TRUE,
1942 xcenter + 1 - in / 2 - in % 2,
1945 row_rectangle.height / 2 + 1);
1947 if (GTK_CTREE_ROW (work)->row.bg_set)
1948 gdk_gc_set_foreground
1950 &(GTK_CTREE_ROW(work)->row.background));
1954 (clist->clist_window,
1955 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1957 xcenter + 1 - in / 2 - in % 2,
1960 row_rectangle.height / 2 + 1);
1962 gdk_draw_arc (clist->clist_window, mbg_gc, TRUE,
1963 xcenter - in, clip_rectangle.y,
1964 in, clist->row_height,
1968 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1970 xcenter - in, clip_rectangle.y,
1971 in, clist->row_height,
1975 work = GTK_CTREE_ROW (work)->parent;
1978 if (clist_row->state != GTK_STATE_SELECTED)
1980 (clist->clist_window,
1981 widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
1982 xcenter + 1, row_rectangle.y,
1983 TAB_SIZE, row_rectangle.height);
1985 xcenter = xdest - (ctree->tree_indent / 2);
1987 if (clist_row->bg_set)
1988 gdk_gc_set_foreground
1989 (clist->bg_gc, &clist_row->background);
1991 if (((GtkCTreeRow *)clist_row)->is_leaf)
1993 points[0].x = xdest - TAB_SIZE;
1994 points[0].y = row_rectangle.y - 1;
1996 points[1].x = points[0].x + 4;
1997 points[1].y = points[0].y;
1999 points[2].x = points[1].x + 2;
2000 points[2].y = points[1].y + 3;
2002 points[3].x = points[2].x;
2003 points[3].y = points[2].y + clist->row_height - 5;
2005 points[4].x = points[3].x - 2;
2006 points[4].y = points[3].y + 3;
2008 points[5].x = points[4].x - 4;
2009 points[5].y = points[4].y;
2011 if (clist_row->state != GTK_STATE_SELECTED)
2012 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE,
2015 gdk_draw_lines (clist->clist_window, ctree->lines_gc,
2020 if (clist_row->state != GTK_STATE_SELECTED)
2021 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
2022 xdest - 2 * TAB_SIZE,
2023 row_rectangle.y - 1,
2024 2 * TAB_SIZE, clist->row_height,
2025 270 * 64, 180 * 64);
2027 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
2029 xdest - 2 * TAB_SIZE,
2030 row_rectangle.y - 1,
2031 2 * TAB_SIZE, clist->row_height,
2032 270 * 64, 180 * 64);
2035 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
2036 gdk_gc_set_clip_rectangle (clist->bg_gc, NULL);
2037 gdk_gc_set_clip_rectangle
2038 (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL);
2042 xcenter = xdest - (ctree->tree_indent / 2);
2043 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
2045 offset_x += abs ((clip_rectangle.x + clist->hoffset) %
2047 offset_y = abs ((clip_rectangle.y + clist->voffset) % 2);
2050 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2051 xcenter, clip_rectangle.y + offset_y,
2053 (((GtkCTreeRow *)clist_row)->sibling) ?
2054 rect->y + rect->height : ycenter);
2056 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2057 xcenter - offset_x, ycenter,
2058 xcenter - PM_SIZE / 2 - 2, ycenter);
2060 work = ((GtkCTreeRow *)clist_row)->parent;
2063 xcenter += ctree->tree_indent;
2064 if (GTK_CTREE_ROW (work)->sibling)
2065 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2066 xcenter, clip_rectangle.y - offset_y,
2067 xcenter, rect->y + rect->height);
2068 work = GTK_CTREE_ROW (work)->parent;
2070 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
2074 if (((GtkCTreeRow *)clist_row)->children)
2076 if (clist_row->state == GTK_STATE_SELECTED)
2078 if (clist_row->fg_set)
2081 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
2087 GTK_WIDGET(clist)->style->fg_gc[GTK_STATE_SELECTED];
2091 gdk_gc_set_clip_rectangle (cgc, rect);
2093 switch (ctree->line_style)
2095 case GTK_CTREE_LINES_NONE:
2096 if (!((GtkCTreeRow *)clist_row)->expanded)
2098 points[0].x = xdest - xoffset - (PM_SIZE+2) / 6 - 2;
2099 points[0].y = clip_rectangle.y + yoffset - 1;
2100 points[1].x = points[0].x;
2101 points[1].y = points[0].y + (PM_SIZE+2);
2102 points[2].x = points[0].x - 2 * (PM_SIZE+2) / 3 + 1;
2103 points[2].y = points[0].y + (PM_SIZE+2) / 2;
2107 points[0].x = xdest - xoffset;
2108 points[0].y = clip_rectangle.y + yoffset +
2110 points[1].x = points[0].x - (PM_SIZE+2);
2111 points[1].y = points[0].y;
2112 points[2].x = points[0].x - (PM_SIZE+2) / 2;
2113 points[2].y = clip_rectangle.y + yoffset +
2114 2 * (PM_SIZE+2) / 3;
2117 gdk_draw_polygon (clist->clist_window,
2118 GTK_WIDGET (clist)->style->
2119 fg_gc[GTK_STATE_SELECTED],
2121 gdk_draw_polygon (clist->clist_window, tgc, FALSE,
2124 case GTK_CTREE_LINES_TABBED:
2125 xcenter = xdest - PM_SIZE - 2;
2127 gdk_draw_arc (clist->clist_window,
2128 GTK_WIDGET (clist)->style->
2129 fg_gc[GTK_STATE_SELECTED],
2131 xcenter - PM_SIZE/2,
2132 ycenter - PM_SIZE/2,
2133 PM_SIZE, PM_SIZE, 0, 360 * 64);
2135 gdk_draw_line (clist->clist_window, tgc,
2141 if (!((GtkCTreeRow *)clist_row)->expanded)
2143 gdk_draw_line (clist->clist_window, tgc, xcenter,
2144 clip_rectangle.y + yoffset + 2,
2145 xcenter, clip_rectangle.y + yoffset
2150 gdk_draw_rectangle (clist->clist_window,
2151 GTK_WIDGET(clist)->style->
2152 fg_gc[GTK_STATE_SELECTED], TRUE,
2153 xdest - xoffset - PM_SIZE,
2154 clip_rectangle.y + yoffset,
2157 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
2158 xdest - xoffset - PM_SIZE,
2159 clip_rectangle.y + yoffset,
2162 gdk_draw_line (clist->clist_window, tgc,
2163 xdest - xoffset - 2, ycenter,
2164 xdest - xoffset - PM_SIZE + 2, ycenter);
2166 if (!((GtkCTreeRow *)clist_row)->expanded)
2168 xcenter = xdest - (ctree->tree_indent / 2);
2169 gdk_draw_line (clist->clist_window, tgc, xcenter,
2170 clip_rectangle.y + yoffset + 2,
2171 xcenter, clip_rectangle.y + yoffset
2175 gdk_gc_set_clip_rectangle (cgc, NULL);
2178 xdest -= (ctree->tree_indent + pixmap_width
2179 + clist_row->cell[i].horizontal);
2181 if (pixmap_width && xdest + pixmap_width >= rect->x &&
2182 xdest <= rect->x + rect->width)
2191 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2193 gdk_gc_set_clip_mask
2194 (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
2195 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2198 if (xdest < clip_rectangle.x)
2200 xsrc = clip_rectangle.x - xdest;
2201 pixmap_width -= xsrc;
2202 xdest = clip_rectangle.x;
2205 if (xdest + pixmap_width >
2206 clip_rectangle.x + clip_rectangle.width)
2208 (clip_rectangle.x + clip_rectangle.width) - xdest;
2210 if (ydest < clip_rectangle.y)
2212 ysrc = clip_rectangle.y - ydest;
2214 ydest = clip_rectangle.y;
2217 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2218 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2220 gdk_draw_pixmap (clist->clist_window, fg_gc,
2222 (clist_row->cell[i])->pixmap,
2223 xsrc, ysrc, xdest, ydest,
2224 pixmap_width, height);
2231 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2232 xdest -= (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
2235 xdest += (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
2238 delta = CELL_SPACING - (rect->y - clip_rectangle.y);
2242 rect->height -= delta;
2245 gdk_gc_set_clip_rectangle (fg_gc, rect);
2248 (clist->clist_window, widget->style->font, fg_gc, xdest,
2249 row_rectangle.y + clist->row_center_offset +
2250 clist_row->cell[i].vertical,
2251 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2253 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2257 switch (clist_row->cell[i].type)
2259 case GTK_CELL_EMPTY:
2264 gdk_gc_set_clip_rectangle (fg_gc, rect);
2266 gdk_draw_string (clist->clist_window,
2267 widget->style->font,
2269 offset + clist_row->cell[i].horizontal,
2270 row_rectangle.y + clist->row_center_offset +
2271 clist_row->cell[i].vertical,
2272 GTK_CELL_TEXT (clist_row->cell[i])->text);
2274 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2277 case GTK_CELL_PIXMAP:
2280 xdest = offset + clist_row->cell[i].horizontal;
2281 ydest = (clip_rectangle.y + (clip_rectangle.height / 2))
2282 - height / 2 + clist_row->cell[i].vertical;
2284 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2286 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP
2287 (clist_row->cell[i])->mask);
2288 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2291 if (xdest < clip_rectangle.x)
2293 xsrc = clip_rectangle.x - xdest;
2294 pixmap_width -= xsrc;
2295 xdest = clip_rectangle.x;
2298 if (xdest + pixmap_width >
2299 clip_rectangle.x + clip_rectangle.width)
2300 pixmap_width = (clip_rectangle.x + clip_rectangle.width) -
2303 if (ydest < clip_rectangle.y)
2305 ysrc = clip_rectangle.y - ydest;
2307 ydest = clip_rectangle.y;
2310 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2311 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2313 gdk_draw_pixmap (clist->clist_window, fg_gc,
2314 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2315 xsrc, ysrc, xdest, ydest, pixmap_width, height);
2317 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2319 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2320 gdk_gc_set_clip_mask (fg_gc, NULL);
2324 case GTK_CELL_PIXTEXT:
2325 /* draw the pixmap */
2328 xdest = offset + clist_row->cell[i].horizontal;
2329 ydest = (clip_rectangle.y + (clip_rectangle.height / 2))
2330 - height / 2 + clist_row->cell[i].vertical;
2332 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2334 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT
2335 (clist_row->cell[i])->mask);
2336 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2339 if (xdest < clip_rectangle.x)
2341 xsrc = clip_rectangle.x - xdest;
2342 pixmap_width -= xsrc;
2343 xdest = clip_rectangle.x;
2346 if (xdest + pixmap_width >
2347 clip_rectangle.x + clip_rectangle.width)
2348 pixmap_width = (clip_rectangle.x + clip_rectangle.width)
2351 if (ydest < clip_rectangle.y)
2353 ysrc = clip_rectangle.y - ydest;
2355 ydest = clip_rectangle.y;
2358 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2359 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2361 gdk_draw_pixmap (clist->clist_window, fg_gc,
2362 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2363 xsrc, ysrc, xdest, ydest, pixmap_width, height);
2365 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2367 xdest += pixmap_width + GTK_CELL_PIXTEXT
2368 (clist_row->cell[i])->spacing;
2370 /* draw the string */
2371 gdk_gc_set_clip_rectangle (fg_gc, rect);
2373 gdk_draw_string (clist->clist_window, widget->style->font, fg_gc,
2375 row_rectangle.y + clist->row_center_offset +
2376 clist_row->cell[i].vertical,
2377 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2379 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2383 case GTK_CELL_WIDGET:
2394 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
2398 if (gdk_rectangle_intersect (area, &row_rectangle,
2399 &intersect_rectangle))
2401 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
2402 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2403 row_rectangle.x, row_rectangle.y,
2404 row_rectangle.width - 1,
2405 row_rectangle.height - 1);
2406 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
2410 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2411 row_rectangle.x, row_rectangle.y,
2412 row_rectangle.width - 1, row_rectangle.height - 1);
2417 tree_draw_node (GtkCTree *ctree,
2422 clist = GTK_CLIST (ctree);
2424 if (!GTK_CLIST_FROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
2429 work = GTK_CTREE_NODE (clist->row_list);
2430 while (work && work != node)
2432 work = GTK_CTREE_NODE_NEXT (work);
2435 if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
2436 GTK_CLIST_CLASS_FW (clist)->draw_row
2437 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2441 static GtkCTreeNode *
2442 gtk_ctree_last_visible (GtkCTree *ctree,
2450 work = GTK_CTREE_ROW (node)->children;
2452 if (!work || !GTK_CTREE_ROW (node)->expanded)
2455 while (GTK_CTREE_ROW (work)->sibling)
2456 work = GTK_CTREE_ROW (work)->sibling;
2458 return gtk_ctree_last_visible (ctree, work);
2462 gtk_ctree_link (GtkCTree *ctree,
2464 GtkCTreeNode *parent,
2465 GtkCTreeNode *sibling,
2466 gboolean update_focus_row)
2469 GtkCTreeNode *list_end;
2470 gboolean visible = FALSE;
2474 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
2475 g_return_if_fail (node != NULL);
2476 g_return_if_fail (node != sibling);
2477 g_return_if_fail (node != parent);
2479 clist = GTK_CLIST (ctree);
2481 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2483 if (clist->anchor != -1)
2484 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2486 g_list_free (clist->undo_selection);
2487 g_list_free (clist->undo_unselection);
2488 clist->undo_selection = NULL;
2489 clist->undo_unselection = NULL;
2492 for (rows = 1, list_end = node; GTK_CTREE_NODE_NEXT (list_end);
2493 list_end = GTK_CTREE_NODE_NEXT (list_end))
2496 GTK_CTREE_ROW (node)->parent = parent;
2497 GTK_CTREE_ROW (node)->sibling = sibling;
2499 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
2500 GTK_CTREE_ROW (parent)->expanded)))
2503 clist->rows += rows;
2512 work = GTK_CTREE_ROW (parent)->children;
2514 work = GTK_CTREE_NODE (clist->row_list);
2515 if (work != sibling)
2517 while (GTK_CTREE_ROW (work)->sibling != sibling)
2518 work = GTK_CTREE_ROW (work)->sibling;
2519 GTK_CTREE_ROW (work)->sibling = node;
2522 if (sibling == GTK_CTREE_NODE (clist->row_list))
2523 clist->row_list = (GList *) node;
2524 if (GTK_CTREE_NODE_PREV (sibling) &&
2525 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2526 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) = node;
2528 GTK_CTREE_NODE_PREV (node) = GTK_CTREE_NODE_PREV (sibling);
2529 GTK_CTREE_NODE_NEXT (list_end) = sibling;
2530 GTK_CTREE_NODE_PREV (sibling) = list_end;
2531 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2532 GTK_CTREE_ROW (parent)->children = node;
2539 work = GTK_CTREE_ROW (parent)->children;
2541 work = GTK_CTREE_NODE (clist->row_list);
2546 while (GTK_CTREE_ROW (work)->sibling)
2547 work = GTK_CTREE_ROW (work)->sibling;
2548 GTK_CTREE_ROW (work)->sibling = node;
2550 /* find last visible child of sibling */
2551 work = gtk_ctree_last_visible (ctree, work);
2553 GTK_CTREE_NODE_NEXT (list_end) = GTK_CTREE_NODE_NEXT (work);
2554 if (GTK_CTREE_NODE_NEXT (work))
2555 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (work)) = list_end;
2556 GTK_CTREE_NODE_NEXT (work) = node;
2557 GTK_CTREE_NODE_PREV (node) = work;
2563 GTK_CTREE_ROW (parent)->children = node;
2564 GTK_CTREE_NODE_PREV (node) = parent;
2565 if (GTK_CTREE_ROW (parent)->expanded)
2567 GTK_CTREE_NODE_NEXT (list_end)= GTK_CTREE_NODE_NEXT (parent);
2568 if (GTK_CTREE_NODE_NEXT(parent))
2569 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (parent)) =
2571 GTK_CTREE_NODE_NEXT (parent) = node;
2574 GTK_CTREE_NODE_NEXT (list_end) = NULL;
2578 clist->row_list = (GList *)node;
2579 GTK_CTREE_NODE_PREV (node) = NULL;
2580 GTK_CTREE_NODE_NEXT (list_end) = NULL;
2585 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2587 if (clist->row_list_end == NULL ||
2588 clist->row_list_end->next == (GList *)node)
2589 GTK_CTREE_NODE (clist->row_list_end) = list_end;
2591 if (visible && update_focus_row)
2595 pos = g_list_position (clist->row_list, (GList *)node);
2597 if (pos <= clist->focus_row)
2599 clist->focus_row += rows;
2600 clist->undo_anchor = clist->focus_row;
2606 gtk_ctree_unlink (GtkCTree *ctree,
2608 gboolean update_focus_row)
2615 GtkCTreeNode *parent;
2617 g_return_if_fail (ctree != NULL);
2618 g_return_if_fail (GTK_IS_CTREE (ctree));
2619 g_return_if_fail (node != NULL);
2621 clist = GTK_CLIST (ctree);
2623 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2625 if (clist->anchor != -1)
2626 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2628 g_list_free (clist->undo_selection);
2629 g_list_free (clist->undo_unselection);
2630 clist->undo_selection = NULL;
2631 clist->undo_unselection = NULL;
2634 visible = gtk_ctree_is_viewable (ctree, node);
2636 /* clist->row_list_end unlinked ? */
2638 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2639 (GTK_CTREE_ROW (node)->children &&
2640 gtk_ctree_is_ancestor (ctree, node,
2641 GTK_CTREE_NODE (clist->row_list_end)))))
2642 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
2646 level = GTK_CTREE_ROW (node)->level;
2647 work = GTK_CTREE_NODE_NEXT (node);
2648 while (work && GTK_CTREE_ROW (work)->level > level)
2650 work = GTK_CTREE_NODE_NEXT (work);
2656 clist->rows -= (rows + 1);
2658 if (update_focus_row)
2662 pos = g_list_position (clist->row_list, (GList *)node);
2663 if (pos + rows + 1 < clist->focus_row)
2664 clist->focus_row -= (rows + 1);
2665 else if (pos <= clist->focus_row)
2666 clist->focus_row = pos - 1;
2667 clist->undo_anchor = clist->focus_row;
2673 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL;
2674 GTK_CTREE_NODE_PREV (work) = GTK_CTREE_NODE_PREV (node);
2677 if (GTK_CTREE_NODE_PREV (node) &&
2678 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2679 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) = work;
2682 parent = GTK_CTREE_ROW (node)->parent;
2685 if (GTK_CTREE_ROW (parent)->children == node)
2687 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2688 if (!GTK_CTREE_ROW (parent)->children)
2689 gtk_ctree_collapse (ctree, parent);
2693 GtkCTreeNode *sibling;
2695 sibling = GTK_CTREE_ROW (parent)->children;
2696 while (GTK_CTREE_ROW (sibling)->sibling != node)
2697 sibling = GTK_CTREE_ROW (sibling)->sibling;
2698 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2703 if (clist->row_list == (GList *)node)
2704 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
2707 GtkCTreeNode *sibling;
2709 sibling = GTK_CTREE_NODE (clist->row_list);
2710 while (GTK_CTREE_ROW (sibling)->sibling != node)
2711 sibling = GTK_CTREE_ROW (sibling)->sibling;
2712 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2718 real_tree_move (GtkCTree *ctree,
2720 GtkCTreeNode *new_parent,
2721 GtkCTreeNode *new_sibling)
2725 gboolean thaw = FALSE;
2727 g_return_if_fail (ctree != NULL);
2728 g_return_if_fail (node != NULL);
2729 g_return_if_fail (!new_sibling ||
2730 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2732 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2735 /* new_parent != child of child */
2736 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2740 clist = GTK_CLIST (ctree);
2742 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2744 if (clist->anchor != -1)
2745 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2747 g_list_free (clist->undo_selection);
2748 g_list_free (clist->undo_unselection);
2749 clist->undo_selection = NULL;
2750 clist->undo_unselection = NULL;
2753 if (GTK_CLIST_AUTO_SORT (clist))
2755 if (new_parent == GTK_CTREE_ROW (node)->parent)
2759 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2761 new_sibling = GTK_CTREE_NODE (clist->row_list);
2763 while (new_sibling && clist->compare
2764 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
2765 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2768 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2769 new_sibling == GTK_CTREE_ROW (node)->sibling)
2772 if (!GTK_CLIST_FROZEN (clist))
2774 gtk_clist_freeze (clist);
2779 if (gtk_ctree_is_viewable (ctree, node) ||
2780 gtk_ctree_is_viewable (ctree, new_sibling))
2781 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2783 gtk_ctree_unlink (ctree, node, FALSE);
2784 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2788 while (work && !gtk_ctree_is_viewable (ctree, work))
2789 work = GTK_CTREE_ROW (work)->parent;
2790 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2791 clist->undo_anchor = clist->focus_row;
2795 gtk_clist_thaw (clist);
2799 change_focus_row_expansion (GtkCTree *ctree,
2800 GtkCTreeExpansionType action)
2805 g_return_if_fail (ctree != NULL);
2806 g_return_if_fail (GTK_IS_CTREE (ctree));
2808 clist = GTK_CLIST (ctree);
2810 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2814 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2815 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2820 case GTK_CTREE_EXPANSION_EXPAND:
2821 gtk_ctree_expand (ctree, node);
2823 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2824 gtk_ctree_expand_recursive (ctree, node);
2826 case GTK_CTREE_EXPANSION_COLLAPSE:
2827 gtk_ctree_collapse (ctree, node);
2829 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2830 gtk_ctree_collapse_recursive (ctree, node);
2832 case GTK_CTREE_EXPANSION_TOGGLE:
2833 gtk_ctree_toggle_expansion (ctree, node);
2835 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2836 gtk_ctree_toggle_expansion_recursive (ctree, node);
2842 real_tree_expand (GtkCTree *ctree,
2849 g_return_if_fail (ctree != NULL);
2850 g_return_if_fail (GTK_IS_CTREE (ctree));
2852 if (!node || GTK_CTREE_ROW (node)->expanded)
2855 clist = GTK_CLIST (ctree);
2857 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2858 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2860 GTK_CTREE_ROW (node)->expanded = TRUE;
2861 level = GTK_CTREE_ROW (node)->level;
2863 if (GTK_CELL_PIXTEXT
2864 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2868 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2871 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2873 if (GTK_CELL_PIXTEXT
2874 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2878 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2880 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2884 if (GTK_CTREE_ROW (node)->pixmap_opened)
2887 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2888 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
2890 if (GTK_CTREE_ROW (node)->mask_opened)
2892 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2893 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
2896 work = GTK_CTREE_ROW (node)->children;
2902 while (GTK_CTREE_NODE_NEXT (work))
2904 work = GTK_CTREE_NODE_NEXT (work);
2908 GTK_CTREE_NODE_NEXT (work) = GTK_CTREE_NODE_NEXT (node);
2910 if (GTK_CTREE_NODE_NEXT (node))
2911 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (node)) = work;
2913 clist->row_list_end = (GList *)work;
2915 GTK_CTREE_NODE_NEXT (node) = GTK_CTREE_ROW (node)->children;
2917 if (gtk_ctree_is_viewable (ctree, node))
2919 row = g_list_position (clist->row_list, (GList *)node);
2920 if (row < clist->focus_row)
2921 clist->focus_row += tmp + 1;
2922 clist->rows += tmp + 1;
2923 if (!GTK_CLIST_FROZEN (ctree))
2924 gtk_clist_thaw (clist);
2930 real_tree_collapse (GtkCTree *ctree,
2937 g_return_if_fail (ctree != NULL);
2938 g_return_if_fail (GTK_IS_CTREE (ctree));
2940 if (!node || !GTK_CTREE_ROW (node)->expanded)
2943 clist = GTK_CLIST (ctree);
2945 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2946 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2948 GTK_CTREE_ROW (node)->expanded = FALSE;
2949 level = GTK_CTREE_ROW (node)->level;
2951 if (GTK_CELL_PIXTEXT
2952 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2956 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2959 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2961 if (GTK_CELL_PIXTEXT
2962 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2966 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2968 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2972 if (GTK_CTREE_ROW (node)->pixmap_closed)
2975 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2976 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed);
2978 if (GTK_CTREE_ROW (node)->mask_closed)
2980 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2981 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed);
2984 work = GTK_CTREE_ROW (node)->children;
2990 while (work && GTK_CTREE_ROW (work)->level > level)
2992 work = GTK_CTREE_NODE_NEXT (work);
2998 GTK_CTREE_NODE_NEXT (node) = work;
2999 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL;
3000 GTK_CTREE_NODE_PREV (work) = node;
3004 GTK_CTREE_NODE_NEXT (node) = NULL;
3005 clist->row_list_end = (GList *)node;
3008 if (gtk_ctree_is_viewable (ctree, node))
3010 row = g_list_position (clist->row_list, (GList *)node);
3011 if (row < clist->focus_row)
3012 clist->focus_row -= tmp;
3014 if (!GTK_CLIST_FROZEN (ctree))
3015 gtk_clist_thaw (clist);
3021 set_cell_contents (GtkCList *clist,
3022 GtkCListRow *clist_row,
3032 g_return_if_fail (clist != NULL);
3033 g_return_if_fail (GTK_IS_CTREE (clist));
3034 g_return_if_fail (clist_row != NULL);
3036 ctree = GTK_CTREE (clist);
3038 switch (clist_row->cell[column].type)
3040 case GTK_CELL_EMPTY:
3044 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3047 case GTK_CELL_PIXMAP:
3048 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3049 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3050 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3053 case GTK_CELL_PIXTEXT:
3054 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
3055 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3056 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
3059 (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3060 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3062 (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3066 case GTK_CELL_WIDGET:
3074 clist_row->cell[column].type = GTK_CELL_EMPTY;
3075 if (column == ctree->tree_column && type != GTK_CELL_EMPTY)
3076 type = GTK_CELL_PIXTEXT;
3083 clist_row->cell[column].type = GTK_CELL_TEXT;
3084 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3088 case GTK_CELL_PIXMAP:
3091 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3092 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3093 /* We set the mask even if it is NULL */
3094 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3098 case GTK_CELL_PIXTEXT:
3099 if (column == ctree->tree_column)
3101 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3102 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3104 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3106 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL;
3109 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3110 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3114 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
3115 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
3118 else if (text && pixmap)
3120 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3121 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3122 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3123 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3124 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3134 set_node_info (GtkCTree *ctree,
3138 GdkPixmap *pixmap_closed,
3139 GdkBitmap *mask_closed,
3140 GdkPixmap *pixmap_opened,
3141 GdkBitmap *mask_opened,
3145 if (GTK_CTREE_ROW (node)->pixmap_opened)
3147 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3148 if (GTK_CTREE_ROW (node)->mask_opened)
3149 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3151 if (GTK_CTREE_ROW (node)->pixmap_closed)
3153 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3154 if (GTK_CTREE_ROW (node)->mask_closed)
3155 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3158 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3159 GTK_CTREE_ROW (node)->mask_opened = NULL;
3160 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3161 GTK_CTREE_ROW (node)->mask_closed = NULL;
3165 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3167 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3171 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3173 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3176 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3177 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3179 if (GTK_CTREE_ROW (node)->expanded)
3180 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3181 text, spacing, pixmap_opened, mask_opened);
3183 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3184 text, spacing, pixmap_closed, mask_closed);
3188 tree_delete (GtkCTree *ctree,
3194 clist = GTK_CLIST (ctree);
3196 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3200 work = g_list_find (clist->selection, node);
3203 if (clist->selection_end && clist->selection_end == work)
3204 clist->selection_end = clist->selection_end->prev;
3205 clist->selection = g_list_remove (clist->selection, node);
3209 row_delete (ctree, GTK_CTREE_ROW (node));
3210 g_list_free_1 ((GList *)node);
3214 tree_delete_row (GtkCTree *ctree,
3218 row_delete (ctree, GTK_CTREE_ROW (node));
3219 g_list_free_1 ((GList *)node);
3223 tree_update_level (GtkCTree *ctree,
3230 if (GTK_CTREE_ROW (node)->parent)
3231 GTK_CTREE_ROW (node)->level =
3232 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3234 GTK_CTREE_ROW (node)->level = 1;
3238 tree_select (GtkCTree *ctree,
3242 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
3243 GTK_CTREE_ROW (node)->row.selectable)
3244 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3249 tree_unselect (GtkCTree *ctree,
3253 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3254 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3259 tree_expand (GtkCTree *ctree,
3263 if (node && !GTK_CTREE_ROW (node)->expanded)
3264 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3268 tree_collapse (GtkCTree *ctree,
3272 if (node && GTK_CTREE_ROW (node)->expanded)
3273 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3277 tree_collapse_to_depth (GtkCTree *ctree,
3281 if (node && GTK_CTREE_ROW (node)->level == depth)
3282 gtk_ctree_collapse_recursive (ctree, node);
3286 tree_toggle_expansion (GtkCTree *ctree,
3293 if (GTK_CTREE_ROW (node)->expanded)
3294 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3296 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3299 static GtkCTreeRow *
3300 row_new (GtkCTree *ctree)
3303 GtkCTreeRow *ctree_row;
3306 clist = GTK_CLIST (ctree);
3307 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3308 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3310 for (i = 0; i < clist->columns; i++)
3312 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3313 ctree_row->row.cell[i].vertical = 0;
3314 ctree_row->row.cell[i].horizontal = 0;
3317 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3319 ctree_row->row.fg_set = FALSE;
3320 ctree_row->row.bg_set = FALSE;
3321 ctree_row->row.selectable = TRUE;
3322 ctree_row->row.state = GTK_STATE_NORMAL;
3323 ctree_row->row.data = NULL;
3324 ctree_row->row.destroy = NULL;
3326 ctree_row->level = 0;
3327 ctree_row->expanded = FALSE;
3328 ctree_row->parent = NULL;
3329 ctree_row->sibling = NULL;
3330 ctree_row->children = NULL;
3331 ctree_row->pixmap_closed = NULL;
3332 ctree_row->mask_closed = NULL;
3333 ctree_row->pixmap_opened = NULL;
3334 ctree_row->mask_opened = NULL;
3340 row_delete (GtkCTree *ctree,
3341 GtkCTreeRow *ctree_row)
3346 clist = GTK_CLIST (ctree);
3348 for (i = 0; i < clist->columns; i++)
3349 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3350 (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
3352 if (ctree_row->pixmap_closed)
3354 gdk_pixmap_unref (ctree_row->pixmap_closed);
3355 if (ctree_row->mask_closed)
3356 gdk_bitmap_unref (ctree_row->mask_closed);
3359 if (ctree_row->pixmap_opened)
3361 gdk_pixmap_unref (ctree_row->pixmap_opened);
3362 if (ctree_row->mask_opened)
3363 gdk_bitmap_unref (ctree_row->mask_opened);
3366 if (ctree_row->row.destroy)
3367 ctree_row->row.destroy (ctree_row->row.data);
3369 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3370 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3374 real_select_row (GtkCList *clist,
3381 g_return_if_fail (clist != NULL);
3382 g_return_if_fail (GTK_IS_CTREE (clist));
3384 if ((node = g_list_nth (clist->row_list, row)) &&
3385 GTK_CTREE_ROW (node)->row.selectable)
3386 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3391 real_unselect_row (GtkCList *clist,
3398 g_return_if_fail (clist != NULL);
3399 g_return_if_fail (GTK_IS_CTREE (clist));
3401 if ((node = g_list_nth (clist->row_list, row)))
3402 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3407 real_tree_select (GtkCTree *ctree,
3413 GtkCTreeNode *sel_row;
3414 gboolean node_selected;
3416 g_return_if_fail (ctree != NULL);
3417 g_return_if_fail (GTK_IS_CTREE (ctree));
3419 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3420 !GTK_CTREE_ROW (node)->row.selectable)
3423 clist = GTK_CLIST (ctree);
3425 switch (clist->selection_mode)
3427 case GTK_SELECTION_SINGLE:
3428 case GTK_SELECTION_BROWSE:
3430 node_selected = FALSE;
3431 list = clist->selection;
3435 sel_row = list->data;
3438 if (node == sel_row)
3439 node_selected = TRUE;
3441 gtk_signal_emit (GTK_OBJECT (ctree),
3442 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3452 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3454 if (!clist->selection)
3456 clist->selection = g_list_append (clist->selection, node);
3457 clist->selection_end = clist->selection;
3460 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3462 tree_draw_node (ctree, node);
3466 real_tree_unselect (GtkCTree *ctree,
3472 g_return_if_fail (ctree != NULL);
3473 g_return_if_fail (GTK_IS_CTREE (ctree));
3475 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3478 clist = GTK_CLIST (ctree);
3480 if (clist->selection_end && clist->selection_end->data == node)
3481 clist->selection_end = clist->selection_end->prev;
3483 clist->selection = g_list_remove (clist->selection, node);
3485 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3487 tree_draw_node (ctree, node);
3491 tree_toggle_selection (GtkCTree *ctree,
3497 g_return_if_fail (ctree != NULL);
3498 g_return_if_fail (GTK_IS_CTREE (ctree));
3500 clist = GTK_CLIST (ctree);
3502 switch (clist->selection_mode)
3504 case GTK_SELECTION_SINGLE:
3505 case GTK_SELECTION_MULTIPLE:
3506 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3507 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3509 else if (node && GTK_CTREE_ROW (node)->row.selectable)
3510 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3514 case GTK_SELECTION_BROWSE:
3515 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL &&
3516 GTK_CTREE_ROW (node)->row.selectable)
3517 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3521 case GTK_SELECTION_EXTENDED:
3527 select_row_recursive (GtkCTree *ctree,
3531 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3532 !GTK_CTREE_ROW (node)->row.selectable)
3535 GTK_CLIST (ctree)->undo_unselection =
3536 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3537 gtk_ctree_select (ctree, node);
3541 real_select_all (GtkCList *clist)
3545 gboolean thaw = FALSE;
3547 g_return_if_fail (clist != NULL);
3548 g_return_if_fail (GTK_IS_CTREE (clist));
3550 ctree = GTK_CTREE (clist);
3552 switch (clist->selection_mode)
3554 case GTK_SELECTION_SINGLE:
3555 case GTK_SELECTION_BROWSE:
3558 case GTK_SELECTION_EXTENDED:
3560 if (!GTK_CLIST_FROZEN (clist))
3562 gtk_clist_freeze (clist);
3566 g_list_free (clist->undo_selection);
3567 g_list_free (clist->undo_unselection);
3568 clist->undo_selection = NULL;
3569 clist->undo_unselection = NULL;
3571 clist->anchor_state = GTK_STATE_SELECTED;
3573 clist->drag_pos = -1;
3574 clist->undo_anchor = clist->focus_row;
3576 for (node = GTK_CTREE_NODE (clist->row_list); node;
3577 node = GTK_CTREE_NODE_NEXT (node))
3578 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3581 gtk_clist_thaw (clist);
3584 case GTK_SELECTION_MULTIPLE:
3585 gtk_ctree_select_recursive (ctree, NULL);
3591 real_unselect_all (GtkCList *clist)
3597 g_return_if_fail (clist != NULL);
3598 g_return_if_fail (GTK_IS_CTREE (clist));
3600 ctree = GTK_CTREE (clist);
3602 switch (clist->selection_mode)
3604 case GTK_SELECTION_BROWSE:
3605 if (clist->focus_row >= 0)
3609 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3614 case GTK_SELECTION_EXTENDED:
3615 g_list_free (clist->undo_selection);
3616 g_list_free (clist->undo_unselection);
3617 clist->undo_selection = NULL;
3618 clist->undo_unselection = NULL;
3621 clist->drag_pos = -1;
3622 clist->undo_anchor = clist->focus_row;
3629 list = clist->selection;
3635 gtk_ctree_unselect (ctree, node);
3640 ctree_is_hot_spot (GtkCTree *ctree,
3646 GtkCTreeRow *tree_row;
3648 GtkCellPixText *cell;
3652 g_return_val_if_fail (ctree != NULL, FALSE);
3653 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3654 g_return_val_if_fail (node != NULL, FALSE);
3656 tree_row = GTK_CTREE_ROW (node);
3657 clist = GTK_CLIST (ctree);
3659 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3661 yu = ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2;
3663 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3665 xl = clist->column[ctree->tree_column].area.x
3666 + clist->column[ctree->tree_column].area.width + clist->hoffset
3667 /*+ cell->horizontal +*/
3668 - (tree_row->level - 1) * ctree->tree_indent
3670 (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 1);
3674 xl = clist->column[ctree->tree_column].area.x + clist->hoffset
3675 + cell->horizontal + (tree_row->level - 1) * ctree->tree_indent +
3676 (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 2);
3679 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3682 /***********************************************************
3683 ***********************************************************
3684 *** Public interface ***
3685 ***********************************************************
3686 ***********************************************************/
3689 /***********************************************************
3690 * Creation, insertion, deletion *
3691 ***********************************************************/
3694 gtk_ctree_construct (GtkCTree *ctree,
3701 g_return_if_fail (ctree != NULL);
3702 g_return_if_fail (GTK_IS_CTREE (ctree));
3703 g_return_if_fail (GTK_CLIST_CONSTRUCTED (ctree) == FALSE);
3705 clist = GTK_CLIST (ctree);
3707 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
3708 sizeof (GtkCTreeRow),
3709 sizeof (GtkCTreeRow)
3710 * CLIST_OPTIMUM_SIZE,
3713 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
3714 sizeof (GtkCell) * columns,
3715 sizeof (GtkCell) * columns
3716 * CLIST_OPTIMUM_SIZE,
3719 ctree->tree_column = tree_column;
3721 gtk_clist_construct (clist, columns, titles);
3725 gtk_ctree_new_with_titles (gint columns,
3731 g_return_val_if_fail (columns > 0, NULL);
3732 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3734 widget = gtk_type_new (GTK_TYPE_CTREE);
3735 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
3740 gtk_ctree_new (gint columns,
3743 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3747 real_insert_row (GtkCList *clist,
3751 GtkCTreeNode *parent = NULL;
3752 GtkCTreeNode *sibling;
3755 g_return_val_if_fail (clist != NULL, -1);
3756 g_return_val_if_fail (GTK_IS_CTREE (clist), -1);
3758 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3760 parent = GTK_CTREE_ROW (sibling)->parent;
3762 node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5,
3763 NULL, NULL, NULL, NULL, TRUE, FALSE);
3765 if (GTK_CLIST_AUTO_SORT (clist) || !sibling)
3766 return g_list_position (clist->row_list, (GList *) node);
3772 gtk_ctree_insert_node (GtkCTree *ctree,
3773 GtkCTreeNode *parent,
3774 GtkCTreeNode *sibling,
3777 GdkPixmap *pixmap_closed,
3778 GdkBitmap *mask_closed,
3779 GdkPixmap *pixmap_opened,
3780 GdkBitmap *mask_opened,
3785 GtkCTreeRow *new_row;
3790 g_return_val_if_fail (ctree != NULL, NULL);
3791 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3793 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3795 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
3798 clist = GTK_CLIST (ctree);
3800 /* create the row */
3801 new_row = row_new (ctree);
3802 list = g_list_alloc ();
3803 list->data = new_row;
3804 node = GTK_CTREE_NODE (list);
3807 for (i = 0; i < clist->columns; i++)
3808 if (text[i] && i != ctree->tree_column)
3809 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3810 (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
3812 set_node_info (ctree, node, text ? text[ctree->tree_column] : NULL, spacing, pixmap_closed,
3813 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
3815 /* sorted insertion */
3816 if (GTK_CLIST_AUTO_SORT (clist))
3819 sibling = GTK_CTREE_ROW (parent)->children;
3821 sibling = GTK_CTREE_NODE (clist->row_list);
3823 while (sibling && clist->compare
3824 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
3825 sibling = GTK_CTREE_ROW (sibling)->sibling;
3828 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
3830 if (!GTK_CLIST_FROZEN (clist))
3831 gtk_clist_thaw (clist);
3837 gtk_ctree_insert_gnode (GtkCTree *ctree,
3838 GtkCTreeNode *parent,
3839 GtkCTreeNode *sibling,
3841 GtkCTreeGNodeFunc func,
3845 GtkCTreeNode *cnode = NULL;
3846 GtkCTreeNode *child = NULL;
3847 GtkCTreeNode *new_child;
3848 GtkCTreeRow *new_row;
3853 g_return_val_if_fail (ctree != NULL, NULL);
3854 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3855 g_return_val_if_fail (gnode != NULL, NULL);
3856 g_return_val_if_fail (func != NULL, NULL);
3858 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3860 clist = GTK_CLIST (ctree);
3863 depth = GTK_CTREE_ROW (parent)->level + 1;
3865 new_row = row_new (ctree);
3866 cnode = GTK_CTREE_NODE (g_list_alloc ());
3867 GTK_CTREE_ROW (cnode) = new_row;
3869 thaw = !GTK_CLIST_FROZEN (clist);
3871 gtk_clist_freeze (clist);
3873 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
3875 if (!func (ctree, depth, gnode, cnode, data))
3877 tree_delete_row (ctree, cnode, NULL);
3881 if (GTK_CLIST_AUTO_SORT (clist))
3884 sibling = GTK_CTREE_ROW (parent)->children;
3886 sibling = GTK_CTREE_NODE (clist->row_list);
3888 while (sibling && clist->compare
3889 (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
3890 sibling = GTK_CTREE_ROW (sibling)->sibling;
3893 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
3895 for (work = g_node_last_child (gnode); work; work = work->prev)
3897 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
3904 gtk_clist_thaw (clist);
3910 gtk_ctree_export_to_gnode (GtkCTree *ctree,
3914 GtkCTreeGNodeFunc func,
3922 g_return_val_if_fail (ctree != NULL, NULL);
3923 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3924 g_return_val_if_fail (node != NULL, NULL);
3925 g_return_val_if_fail (func != NULL, NULL);
3928 g_return_val_if_fail (parent != NULL, NULL);
3929 g_return_val_if_fail (sibling->parent == parent, NULL);
3932 gnode = g_node_new (NULL);
3933 depth = g_node_depth (parent) + 1;
3935 if (!func (ctree, depth, gnode, node, data))
3937 g_node_destroy (gnode);
3942 g_node_insert_before (parent, sibling, gnode);
3944 for (work = GTK_CTREE_ROW (node)->children, new_sibling = NULL; work;
3945 work = GTK_CTREE_NODE_NEXT (work))
3947 sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling,
3950 new_sibling = sibling;
3952 g_node_reverse_children (gnode);
3958 real_remove_row (GtkCList *clist,
3963 g_return_if_fail (clist != NULL);
3964 g_return_if_fail (GTK_IS_CTREE (clist));
3966 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3969 gtk_ctree_remove_node (GTK_CTREE (clist), node);
3973 gtk_ctree_remove_node (GtkCTree *ctree,
3977 gboolean thaw = FALSE;
3979 g_return_if_fail (ctree != NULL);
3980 g_return_if_fail (GTK_IS_CTREE (ctree));
3982 clist = GTK_CLIST (ctree);
3984 if (!GTK_CLIST_FROZEN (clist))
3986 gtk_clist_freeze (clist);
3992 gtk_ctree_unlink (ctree, node, TRUE);
3993 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
3997 gtk_clist_clear (clist);
4000 gtk_clist_thaw (clist);
4004 real_clear (GtkCList *clist)
4010 g_return_if_fail (clist != NULL);
4011 g_return_if_fail (GTK_IS_CTREE (clist));
4013 ctree = GTK_CTREE (clist);
4015 ctree->drag_row = -1;
4016 ctree->drag_rect = FALSE;
4017 ctree->in_drag = FALSE;
4018 ctree->drag_source = NULL;
4019 ctree->drag_target = NULL;
4020 ctree->drag_icon = NULL;
4022 /* remove all the rows */
4023 work = GTK_CTREE_NODE (clist->row_list);
4024 clist->row_list = NULL;
4025 clist->row_list_end = NULL;
4030 work = GTK_CTREE_ROW (work)->sibling;
4031 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
4035 (parent_class->clear) (clist);
4039 /***********************************************************
4040 * Generic recursive functions, querying / finding tree *
4042 ***********************************************************/
4046 gtk_ctree_post_recursive (GtkCTree *ctree,
4054 g_return_if_fail (ctree != NULL);
4055 g_return_if_fail (GTK_IS_CTREE (ctree));
4056 g_return_if_fail (func != NULL);
4059 work = GTK_CTREE_ROW (node)->children;
4061 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4065 tmp = GTK_CTREE_ROW (work)->sibling;
4066 gtk_ctree_post_recursive (ctree, work, func, data);
4071 func (ctree, node, data);
4075 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
4084 g_return_if_fail (ctree != NULL);
4085 g_return_if_fail (GTK_IS_CTREE (ctree));
4086 g_return_if_fail (func != NULL);
4090 gtk_ctree_post_recursive (ctree, node, func, data);
4095 work = GTK_CTREE_ROW (node)->children;
4097 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4099 if (work && GTK_CTREE_ROW (work)->level <= depth)
4103 tmp = GTK_CTREE_ROW (work)->sibling;
4104 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
4109 if (node && GTK_CTREE_ROW (node)->level <= depth)
4110 func (ctree, node, data);
4114 gtk_ctree_pre_recursive (GtkCTree *ctree,
4122 g_return_if_fail (ctree != NULL);
4123 g_return_if_fail (GTK_IS_CTREE (ctree));
4124 g_return_if_fail (func != NULL);
4128 work = GTK_CTREE_ROW (node)->children;
4129 func (ctree, node, data);
4132 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4136 tmp = GTK_CTREE_ROW (work)->sibling;
4137 gtk_ctree_pre_recursive (ctree, work, func, data);
4143 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4152 g_return_if_fail (ctree != NULL);
4153 g_return_if_fail (GTK_IS_CTREE (ctree));
4154 g_return_if_fail (func != NULL);
4158 gtk_ctree_pre_recursive (ctree, node, func, data);
4164 work = GTK_CTREE_ROW (node)->children;
4165 if (GTK_CTREE_ROW (node)->level <= depth)
4166 func (ctree, node, data);
4169 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4171 if (work && GTK_CTREE_ROW (work)->level <= depth)
4175 tmp = GTK_CTREE_ROW (work)->sibling;
4176 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4183 gtk_ctree_is_viewable (GtkCTree *ctree,
4188 g_return_val_if_fail (ctree != NULL, FALSE);
4189 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4190 g_return_val_if_fail (node != NULL, FALSE);
4192 work = GTK_CTREE_ROW (node);
4194 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4195 work = GTK_CTREE_ROW (work->parent);
4204 gtk_ctree_last (GtkCTree *ctree,
4207 g_return_val_if_fail (ctree != NULL, NULL);
4208 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4213 while (GTK_CTREE_ROW (node)->sibling)
4214 node = GTK_CTREE_ROW (node)->sibling;
4216 if (GTK_CTREE_ROW (node)->children)
4217 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4223 gtk_ctree_find_node_ptr (GtkCTree *ctree,
4224 GtkCTreeRow *ctree_row)
4228 g_return_val_if_fail (ctree != NULL, FALSE);
4229 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4230 g_return_val_if_fail (ctree_row != NULL, FALSE);
4232 if (ctree_row->parent)
4233 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4235 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4237 while (GTK_CTREE_ROW (node) != ctree_row)
4238 node = GTK_CTREE_ROW (node)->sibling;
4244 gtk_ctree_find (GtkCTree *ctree,
4246 GtkCTreeNode *child)
4252 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4258 if (GTK_CTREE_ROW (node)->children)
4260 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4263 node = GTK_CTREE_ROW (node)->sibling;
4269 gtk_ctree_is_ancestor (GtkCTree *ctree,
4271 GtkCTreeNode *child)
4273 g_return_val_if_fail (node != NULL, FALSE);
4275 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4279 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4286 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4290 if (GTK_CTREE_ROW (node)->row.data == data)
4292 if (GTK_CTREE_ROW (node)->children &&
4293 (work = gtk_ctree_find_by_row_data
4294 (ctree, GTK_CTREE_ROW (node)->children, data)))
4296 node = GTK_CTREE_ROW (node)->sibling;
4302 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4309 g_return_val_if_fail (func != NULL, NULL);
4312 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4316 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4318 if (GTK_CTREE_ROW (node)->children &&
4319 (work = gtk_ctree_find_by_row_data_custom
4320 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4322 node = GTK_CTREE_ROW (node)->sibling;
4328 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4336 g_return_val_if_fail (ctree != NULL, FALSE);
4337 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4339 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4340 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4341 return ctree_is_hot_spot (ctree, node, row, x, y);
4347 /***********************************************************
4348 * Tree signals : move, expand, collapse, (un)select *
4349 ***********************************************************/
4353 gtk_ctree_move (GtkCTree *ctree,
4355 GtkCTreeNode *new_parent,
4356 GtkCTreeNode *new_sibling)
4358 g_return_if_fail (ctree != NULL);
4359 g_return_if_fail (GTK_IS_CTREE (ctree));
4360 g_return_if_fail (node != NULL);
4362 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4363 new_parent, new_sibling);
4367 gtk_ctree_expand (GtkCTree *ctree,
4370 g_return_if_fail (ctree != NULL);
4371 g_return_if_fail (GTK_IS_CTREE (ctree));
4372 g_return_if_fail (node != NULL);
4374 if (GTK_CTREE_ROW (node)->is_leaf)
4377 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4381 gtk_ctree_expand_recursive (GtkCTree *ctree,
4385 gboolean thaw = FALSE;
4387 g_return_if_fail (ctree != NULL);
4388 g_return_if_fail (GTK_IS_CTREE (ctree));
4390 clist = GTK_CLIST (ctree);
4392 if (node && GTK_CTREE_ROW (node)->is_leaf)
4395 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4396 !GTK_CLIST_FROZEN (clist))
4398 gtk_clist_freeze (clist);
4402 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4405 gtk_clist_thaw (clist);
4409 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4414 gboolean thaw = FALSE;
4416 g_return_if_fail (ctree != NULL);
4417 g_return_if_fail (GTK_IS_CTREE (ctree));
4419 clist = GTK_CLIST (ctree);
4421 if (node && GTK_CTREE_ROW (node)->is_leaf)
4424 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4425 !GTK_CLIST_FROZEN (clist))
4427 gtk_clist_freeze (clist);
4431 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4432 GTK_CTREE_FUNC (tree_expand), NULL);
4435 gtk_clist_thaw (clist);
4439 gtk_ctree_collapse (GtkCTree *ctree,
4442 g_return_if_fail (ctree != NULL);
4443 g_return_if_fail (GTK_IS_CTREE (ctree));
4444 g_return_if_fail (node != NULL);
4446 if (GTK_CTREE_ROW (node)->is_leaf)
4449 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4453 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4457 gboolean thaw = FALSE;
4459 g_return_if_fail (ctree != NULL);
4460 g_return_if_fail (GTK_IS_CTREE (ctree));
4462 if (node && GTK_CTREE_ROW (node)->is_leaf)
4465 clist = GTK_CLIST (ctree);
4467 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4468 !GTK_CLIST_FROZEN (clist))
4470 gtk_clist_freeze (clist);
4474 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4477 gtk_clist_thaw (clist);
4481 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4486 gboolean thaw = FALSE;
4488 g_return_if_fail (ctree != NULL);
4489 g_return_if_fail (GTK_IS_CTREE (ctree));
4491 if (node && GTK_CTREE_ROW (node)->is_leaf)
4494 clist = GTK_CLIST (ctree);
4496 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4497 !GTK_CLIST_FROZEN (clist))
4499 gtk_clist_freeze (clist);
4503 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4504 GTK_CTREE_FUNC (tree_collapse_to_depth),
4505 GINT_TO_POINTER (depth));
4508 gtk_clist_thaw (clist);
4512 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4515 g_return_if_fail (ctree != NULL);
4516 g_return_if_fail (GTK_IS_CTREE (ctree));
4517 g_return_if_fail (node != NULL);
4519 if (GTK_CTREE_ROW (node)->is_leaf)
4522 tree_toggle_expansion (ctree, node, NULL);
4526 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4530 gboolean thaw = FALSE;
4532 g_return_if_fail (ctree != NULL);
4533 g_return_if_fail (GTK_IS_CTREE (ctree));
4535 if (node && GTK_CTREE_ROW (node)->is_leaf)
4538 clist = GTK_CLIST (ctree);
4540 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4541 !GTK_CLIST_FROZEN (clist))
4543 gtk_clist_freeze (clist);
4547 gtk_ctree_post_recursive (ctree, node,
4548 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4551 gtk_clist_thaw (clist);
4555 gtk_ctree_select (GtkCTree *ctree,
4558 g_return_if_fail (ctree != NULL);
4559 g_return_if_fail (GTK_IS_CTREE (ctree));
4560 g_return_if_fail (node != NULL);
4562 if (GTK_CTREE_ROW (node)->row.selectable)
4563 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4568 gtk_ctree_unselect (GtkCTree *ctree,
4571 g_return_if_fail (ctree != NULL);
4572 g_return_if_fail (GTK_IS_CTREE (ctree));
4573 g_return_if_fail (node != NULL);
4575 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4580 gtk_ctree_select_recursive (GtkCTree *ctree,
4583 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4587 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4590 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4594 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4599 gboolean thaw = FALSE;
4601 g_return_if_fail (ctree != NULL);
4602 g_return_if_fail (GTK_IS_CTREE (ctree));
4604 clist = GTK_CLIST (ctree);
4607 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4608 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4609 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4612 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4613 !GTK_CLIST_FROZEN (clist))
4615 gtk_clist_freeze (clist);
4619 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4621 if (clist->anchor != -1)
4622 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4624 g_list_free (clist->undo_selection);
4625 g_list_free (clist->undo_unselection);
4626 clist->undo_selection = NULL;
4627 clist->undo_unselection = NULL;
4631 gtk_ctree_post_recursive (ctree, node,
4632 GTK_CTREE_FUNC (tree_select), NULL);
4634 gtk_ctree_post_recursive (ctree, node,
4635 GTK_CTREE_FUNC (tree_unselect), NULL);
4638 gtk_clist_thaw (clist);
4642 /***********************************************************
4643 * Analogons of GtkCList functions *
4644 ***********************************************************/
4648 gtk_ctree_node_set_text (GtkCTree *ctree,
4655 g_return_if_fail (ctree != NULL);
4656 g_return_if_fail (GTK_IS_CTREE (ctree));
4657 g_return_if_fail (node != NULL);
4659 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4662 clist = GTK_CLIST (ctree);
4664 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4665 (clist, &(GTK_CTREE_ROW(node)->row), column, GTK_CELL_TEXT,
4666 text, 0, NULL, NULL);
4668 tree_draw_node (ctree, node);
4672 gtk_ctree_node_set_pixmap (GtkCTree *ctree,
4680 g_return_if_fail (ctree != NULL);
4681 g_return_if_fail (GTK_IS_CTREE (ctree));
4682 g_return_if_fail (node != NULL);
4683 g_return_if_fail (pixmap != NULL);
4685 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4688 gdk_pixmap_ref (pixmap);
4690 gdk_pixmap_ref (mask);
4692 clist = GTK_CLIST (ctree);
4694 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4695 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP,
4696 NULL, 0, pixmap, mask);
4698 tree_draw_node (ctree, node);
4702 gtk_ctree_node_set_pixtext (GtkCTree *ctree,
4712 g_return_if_fail (ctree != NULL);
4713 g_return_if_fail (GTK_IS_CTREE (ctree));
4714 g_return_if_fail (node != NULL);
4715 if (column != ctree->tree_column)
4716 g_return_if_fail (pixmap != NULL);
4717 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4720 clist = GTK_CLIST (ctree);
4724 gdk_pixmap_ref (pixmap);
4726 gdk_pixmap_ref (mask);
4729 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4730 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT,
4731 text, spacing, pixmap, mask);
4733 tree_draw_node (ctree, node);
4737 gtk_ctree_set_node_info (GtkCTree *ctree,
4741 GdkPixmap *pixmap_closed,
4742 GdkBitmap *mask_closed,
4743 GdkPixmap *pixmap_opened,
4744 GdkBitmap *mask_opened,
4749 gboolean old_expanded;
4751 g_return_if_fail (ctree != NULL);
4752 g_return_if_fail (GTK_IS_CTREE (ctree));
4753 g_return_if_fail (node != NULL);
4755 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
4756 old_expanded = GTK_CTREE_ROW (node)->expanded;
4758 if (is_leaf && GTK_CTREE_ROW (node)->children)
4763 work = GTK_CTREE_ROW (node)->children;
4767 work = GTK_CTREE_ROW(work)->sibling;
4768 gtk_ctree_remove_node (ctree, ptr);
4772 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
4773 pixmap_opened, mask_opened, is_leaf, expanded);
4775 if (!is_leaf && !old_leaf)
4777 GTK_CTREE_ROW (node)->expanded = old_expanded;
4778 if (expanded && !old_expanded)
4779 gtk_ctree_expand (ctree, node);
4780 else if (!expanded && old_expanded)
4781 gtk_ctree_collapse (ctree, node);
4784 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
4786 tree_draw_node (ctree, node);
4790 gtk_ctree_node_set_shift (GtkCTree *ctree,
4796 g_return_if_fail (ctree != NULL);
4797 g_return_if_fail (GTK_IS_CTREE (ctree));
4798 g_return_if_fail (node != NULL);
4800 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4803 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
4804 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
4806 tree_draw_node (ctree, node);
4810 gtk_ctree_node_set_selectable (GtkCTree *ctree,
4812 gboolean selectable)
4814 g_return_if_fail (ctree != NULL);
4815 g_return_if_fail (GTK_IS_CTREE (ctree));
4816 g_return_if_fail (node != NULL);
4818 if (selectable == GTK_CTREE_ROW (node)->row.selectable)
4821 GTK_CTREE_ROW (node)->row.selectable = selectable;
4823 if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
4827 clist = GTK_CLIST (ctree);
4829 if (clist->anchor >= 0 &&
4830 clist->selection_mode == GTK_SELECTION_EXTENDED)
4832 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
4834 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
4835 gtk_grab_remove (GTK_WIDGET (clist));
4836 gdk_pointer_ungrab (GDK_CURRENT_TIME);
4839 gtk_timeout_remove (clist->htimer);
4844 gtk_timeout_remove (clist->vtimer);
4848 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4850 gtk_ctree_unselect (ctree, node);
4855 gtk_ctree_node_get_selectable (GtkCTree *ctree,
4858 g_return_val_if_fail (node != NULL, FALSE);
4860 return GTK_CTREE_ROW (node)->row.selectable;
4864 gtk_ctree_node_get_cell_type (GtkCTree *ctree,
4868 g_return_val_if_fail (ctree != NULL, -1);
4869 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
4870 g_return_val_if_fail (node != NULL, -1);
4872 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4875 return GTK_CTREE_ROW (node)->row.cell[column].type;
4879 gtk_ctree_node_get_text (GtkCTree *ctree,
4884 g_return_val_if_fail (ctree != NULL, 0);
4885 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4886 g_return_val_if_fail (node != NULL, 0);
4888 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4891 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
4895 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4901 gtk_ctree_node_get_pixmap (GtkCTree *ctree,
4907 g_return_val_if_fail (ctree != NULL, 0);
4908 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4909 g_return_val_if_fail (node != NULL, 0);
4911 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4914 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
4918 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
4920 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4926 gtk_ctree_node_get_pixtext (GtkCTree *ctree,
4934 g_return_val_if_fail (ctree != NULL, 0);
4935 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4936 g_return_val_if_fail (node != NULL, 0);
4938 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4941 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
4945 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4947 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4948 (node)->row.cell[column])->spacing;
4950 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4951 (node)->row.cell[column])->pixmap;
4953 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4959 gtk_ctree_get_node_info (GtkCTree *ctree,
4963 GdkPixmap **pixmap_closed,
4964 GdkBitmap **mask_closed,
4965 GdkPixmap **pixmap_opened,
4966 GdkBitmap **mask_opened,
4970 g_return_val_if_fail (ctree != NULL, 0);
4971 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4972 g_return_val_if_fail (node != NULL, 0);
4975 *text = GTK_CELL_PIXTEXT
4976 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
4978 *spacing = GTK_CELL_PIXTEXT
4979 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
4981 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
4983 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
4985 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
4987 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
4989 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
4991 *expanded = GTK_CTREE_ROW (node)->expanded;
4997 gtk_ctree_node_set_foreground (GtkCTree *ctree,
5001 g_return_if_fail (ctree != NULL);
5002 g_return_if_fail (GTK_IS_CTREE (ctree));
5003 g_return_if_fail (node != NULL);
5007 GTK_CTREE_ROW (node)->row.foreground = *color;
5008 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
5011 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
5013 tree_draw_node (ctree, node);
5017 gtk_ctree_node_set_background (GtkCTree *ctree,
5021 g_return_if_fail (ctree != NULL);
5022 g_return_if_fail (GTK_IS_CTREE (ctree));
5023 g_return_if_fail (node != NULL);
5027 GTK_CTREE_ROW (node)->row.background = *color;
5028 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
5031 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
5033 tree_draw_node (ctree, node);
5037 gtk_ctree_node_set_row_data (GtkCTree *ctree,
5041 gtk_ctree_node_set_row_data_full (ctree, node, data, NULL);
5045 gtk_ctree_node_set_row_data_full (GtkCTree *ctree,
5048 GtkDestroyNotify destroy)
5050 g_return_if_fail (ctree != NULL);
5051 g_return_if_fail (GTK_IS_CTREE (ctree));
5053 GTK_CTREE_ROW (node)->row.data = data;
5054 GTK_CTREE_ROW (node)->row.destroy = destroy;
5058 gtk_ctree_node_get_row_data (GtkCTree *ctree,
5061 g_return_val_if_fail (ctree != NULL, NULL);
5062 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5064 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
5068 gtk_ctree_node_moveto (GtkCTree *ctree,
5077 g_return_if_fail (ctree != NULL);
5078 g_return_if_fail (GTK_IS_CTREE (ctree));
5080 clist = GTK_CLIST (ctree);
5082 while (node && !gtk_ctree_is_viewable (ctree, node))
5083 node = GTK_CTREE_ROW (node)->parent;
5086 row = g_list_position (clist->row_list, (GList *)node);
5088 gtk_clist_moveto (clist, row, column, row_align, col_align);
5091 GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree,
5096 g_return_val_if_fail (ctree != NULL, 0);
5097 g_return_val_if_fail (node != NULL, 0);
5099 row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node);
5100 return gtk_clist_row_is_visible (GTK_CLIST (ctree), row);
5104 /***********************************************************
5105 * GtkCTree specific functions *
5106 ***********************************************************/
5110 gtk_ctree_set_indent (GtkCTree *ctree,
5113 g_return_if_fail (ctree != NULL);
5114 g_return_if_fail (GTK_IS_CTREE (ctree));
5115 g_return_if_fail (indent >= 0);
5117 if (indent != ctree->tree_indent)
5119 ctree->tree_indent = indent;
5120 if (!GTK_CLIST_FROZEN (ctree))
5121 gtk_clist_thaw (GTK_CLIST (ctree));
5126 gtk_ctree_show_stub (GtkCTree *ctree,
5129 g_return_if_fail (ctree != NULL);
5130 g_return_if_fail (GTK_IS_CTREE (ctree));
5132 show_stub = show_stub != FALSE;
5134 if (show_stub != ctree->show_stub)
5138 clist = GTK_CLIST (ctree);
5139 ctree->show_stub = show_stub;
5141 if (!GTK_CLIST_FROZEN (clist) && clist->rows &&
5142 gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
5143 GTK_CLIST_CLASS_FW (clist)->draw_row
5144 (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list));
5149 gtk_ctree_set_reorderable (GtkCTree *ctree,
5150 gboolean reorderable)
5152 g_return_if_fail (ctree != NULL);
5153 g_return_if_fail (GTK_IS_CTREE (ctree));
5155 reorderable = reorderable != FALSE;
5157 if (ctree->reorderable == reorderable)
5160 ctree->reorderable = reorderable;
5162 if (GTK_WIDGET_REALIZED (ctree))
5164 if (ctree->reorderable)
5165 create_xor_gc (ctree);
5167 gdk_gc_destroy (ctree->xor_gc);
5172 gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
5175 g_return_if_fail (ctree != NULL);
5176 g_return_if_fail (GTK_IS_CTREE (ctree));
5178 if (ctree->use_icons == (use_icons != 0))
5181 ctree->use_icons = (use_icons != 0);
5185 gtk_ctree_set_line_style (GtkCTree *ctree,
5186 GtkCTreeLineStyle line_style)
5188 g_return_if_fail (ctree != NULL);
5189 g_return_if_fail (GTK_IS_CTREE (ctree));
5191 if (line_style != ctree->line_style)
5193 ctree->line_style = line_style;
5195 if (!GTK_WIDGET_REALIZED (ctree))
5200 case GTK_CTREE_LINES_SOLID:
5201 if (GTK_WIDGET_REALIZED (ctree))
5202 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5205 case GTK_CTREE_LINES_DOTTED:
5206 if (GTK_WIDGET_REALIZED (ctree))
5207 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
5208 GDK_LINE_ON_OFF_DASH, None, None);
5209 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
5211 case GTK_CTREE_LINES_TABBED:
5212 if (GTK_WIDGET_REALIZED (ctree))
5213 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5216 case GTK_CTREE_LINES_NONE:
5221 if (!GTK_CLIST_FROZEN (ctree))
5222 gtk_clist_thaw (GTK_CLIST (ctree));
5227 /***********************************************************
5228 * Tree sorting functions *
5229 ***********************************************************/
5233 tree_sort (GtkCTree *ctree,
5237 GtkCTreeNode *list_start;
5242 clist = GTK_CLIST (ctree);
5245 list_start = GTK_CTREE_ROW (node)->children;
5247 list_start = GTK_CTREE_NODE (clist->row_list);
5252 work = GTK_CTREE_ROW (cmp)->sibling;
5255 if (clist->sort_type == GTK_SORT_ASCENDING)
5258 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0)
5264 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0)
5267 work = GTK_CTREE_ROW (work)->sibling;
5269 if (cmp == list_start)
5270 list_start = GTK_CTREE_ROW (cmp)->sibling;
5273 gtk_ctree_unlink (ctree, cmp, FALSE);
5274 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5280 gtk_ctree_sort_recursive (GtkCTree *ctree,
5284 GtkCTreeNode *focus_node = NULL;
5285 gboolean thaw = FALSE;
5287 g_return_if_fail (ctree != NULL);
5288 g_return_if_fail (GTK_IS_CTREE (ctree));
5290 clist = GTK_CLIST (ctree);
5292 if (!GTK_CLIST_FROZEN (clist))
5294 gtk_clist_freeze (clist);
5298 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5300 if (clist->anchor != -1)
5301 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5303 g_list_free (clist->undo_selection);
5304 g_list_free (clist->undo_unselection);
5305 clist->undo_selection = NULL;
5306 clist->undo_unselection = NULL;
5309 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5311 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5313 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5316 tree_sort (ctree, NULL, NULL);
5320 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5321 clist->undo_anchor = clist->focus_row;
5325 gtk_clist_thaw (clist);
5329 real_sort_list (GtkCList *clist)
5331 gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL);
5335 gtk_ctree_sort_node (GtkCTree *ctree,
5339 GtkCTreeNode *focus_node = NULL;
5340 gboolean thaw = FALSE;
5342 g_return_if_fail (ctree != NULL);
5343 g_return_if_fail (GTK_IS_CTREE (ctree));
5345 clist = GTK_CLIST (ctree);
5347 if (!GTK_CLIST_FROZEN (clist))
5349 gtk_clist_freeze (clist);
5353 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5355 if (clist->anchor != -1)
5356 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5358 g_list_free (clist->undo_selection);
5359 g_list_free (clist->undo_unselection);
5360 clist->undo_selection = NULL;
5361 clist->undo_unselection = NULL;
5364 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5365 focus_node = GTK_CTREE_NODE
5366 (g_list_nth (clist->row_list, clist->focus_row));
5368 tree_sort (ctree, node, NULL);
5372 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5373 clist->undo_anchor = clist->focus_row;
5377 gtk_clist_thaw (clist);
5380 /************************************************************************/
5383 fake_unselect_all (GtkCList *clist,
5387 GList *focus_node = NULL;
5389 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5391 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
5392 GTK_CTREE_ROW (focus_node)->row.selectable)
5394 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5396 if (!GTK_CLIST_FROZEN (clist) &&
5397 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5398 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5399 GTK_CLIST_ROW (focus_node));
5403 clist->undo_selection = clist->selection;
5404 clist->selection = NULL;
5405 clist->selection_end = NULL;
5407 for (list = clist->undo_selection; list; list = list->next)
5409 if (list->data == focus_node)
5412 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
5413 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
5418 selection_find (GtkCList *clist,
5420 GList *row_list_element)
5422 return g_list_find (clist->selection, row_list_element);
5426 resync_selection (GtkCList *clist, GdkEvent *event)
5434 gboolean thaw = FALSE;
5437 g_return_if_fail (clist != NULL);
5438 g_return_if_fail (GTK_IS_CTREE (clist));
5440 if (clist->anchor < 0)
5443 ctree = GTK_CTREE (clist);
5445 if (!GTK_CLIST_FROZEN (clist))
5447 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
5451 i = MIN (clist->anchor, clist->drag_pos);
5452 e = MAX (clist->anchor, clist->drag_pos);
5454 if (clist->undo_selection)
5456 list = clist->selection;
5457 clist->selection = clist->undo_selection;
5458 clist->selection_end = g_list_last (clist->selection);
5459 clist->undo_selection = list;
5460 list = clist->selection;
5469 if (gtk_ctree_is_viewable (ctree, node))
5471 row = g_list_position (clist->row_list, (GList *)node);
5472 if (row >= i && row <= e)
5475 if (unselect && GTK_CTREE_ROW (node)->row.selectable)
5477 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5478 gtk_ctree_unselect (ctree, node);
5479 clist->undo_selection = g_list_prepend (clist->undo_selection,
5486 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
5487 i++, node = GTK_CTREE_NODE_NEXT (node))
5488 if (GTK_CTREE_ROW (node)->row.selectable)
5490 if (g_list_find (clist->selection, node))
5492 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5494 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5495 gtk_ctree_unselect (ctree, node);
5496 clist->undo_selection = g_list_prepend (clist->undo_selection,
5500 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5502 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5503 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
5508 for (list = clist->undo_unselection; list; list = list->next)
5509 gtk_ctree_select (ctree, list->data);
5512 clist->drag_pos = -1;
5515 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
5519 real_undo_selection (GtkCList *clist)
5524 g_return_if_fail (clist != NULL);
5525 g_return_if_fail (GTK_IS_CTREE (clist));
5527 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
5530 if (!(clist->undo_selection || clist->undo_unselection))
5532 gtk_clist_unselect_all (clist);
5536 ctree = GTK_CTREE (clist);
5538 for (work = clist->undo_selection; work; work = work->next)
5539 if (GTK_CTREE_ROW (work->data)->row.selectable)
5540 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
5542 for (work = clist->undo_unselection; work; work = work->next)
5543 if (GTK_CTREE_ROW (work->data)->row.selectable)
5544 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
5546 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
5548 gtk_widget_draw_focus (GTK_WIDGET (clist));
5549 clist->focus_row = clist->undo_anchor;
5550 gtk_widget_draw_focus (GTK_WIDGET (clist));
5553 clist->focus_row = clist->undo_anchor;
5555 clist->undo_anchor = -1;
5557 g_list_free (clist->undo_selection);
5558 g_list_free (clist->undo_unselection);
5559 clist->undo_selection = NULL;
5560 clist->undo_unselection = NULL;
5562 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5563 clist->clist_window_height)
5564 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5565 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5566 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5571 gtk_ctree_set_drag_compare_func (GtkCTree *ctree,
5572 GtkCTreeCompareDragFunc cmp_func)
5574 g_return_if_fail (ctree != NULL);
5575 g_return_if_fail (GTK_IS_CTREE (ctree));
5577 ctree->drag_compare = cmp_func;
5581 set_mouse_cursor (GtkCTree *ctree,
5586 g_return_if_fail (ctree != NULL);
5587 g_return_if_fail (GTK_IS_CTREE (ctree));
5590 cursor = gdk_cursor_new (GDK_LEFT_PTR);
5592 cursor = gdk_cursor_new (GDK_CIRCLE);
5594 gdk_window_set_cursor (GTK_CLIST (ctree)->clist_window, cursor);
5595 gdk_cursor_destroy (cursor);
5599 check_cursor (GtkCTree *ctree)
5601 g_return_if_fail (ctree != NULL);
5602 g_return_if_fail (GTK_IS_CTREE (ctree));
5604 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
5605 !gtk_ctree_is_ancestor (ctree, ctree->drag_source, ctree->drag_target))
5607 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
5609 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
5613 (!ctree->drag_compare ||
5617 GTK_CTREE_ROW (ctree->drag_target)->parent,
5618 GTK_CTREE_ROW (ctree->drag_target)->sibling)));
5620 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
5622 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
5626 (!ctree->drag_compare ||
5630 GTK_CTREE_ROW (ctree->drag_target)->parent,
5631 ctree->drag_target)));
5633 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
5635 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
5639 (!ctree->drag_compare ||
5644 GTK_CTREE_ROW (ctree->drag_target)->children)));
5648 set_mouse_cursor(ctree, FALSE);