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 cell_empty (GtkCList *clist,
74 GtkCListRow *clist_row,
76 static void cell_set_text (GtkCList *clist,
77 GtkCListRow *clist_row,
80 static void cell_set_pixmap (GtkCList *clist,
81 GtkCListRow *clist_row,
85 static void cell_set_pixtext (GtkCList *clist,
86 GtkCListRow *clist_row,
92 static void set_node_info (GtkCTree *ctree,
96 GdkPixmap *pixmap_closed,
97 GdkBitmap *mask_closed,
98 GdkPixmap *pixmap_opened,
99 GdkBitmap *mask_opened,
102 static GtkCTreeRow *row_new (GtkCTree *ctree);
103 static void row_delete (GtkCTree *ctree,
104 GtkCTreeRow *ctree_row);
105 static void tree_delete (GtkCTree *ctree,
108 static void tree_delete_row (GtkCTree *ctree,
111 static void real_clear (GtkCList *clist);
112 static void tree_update_level (GtkCTree *ctree,
115 static void tree_select (GtkCTree *ctree,
118 static void tree_unselect (GtkCTree *ctree,
121 static void real_select_all (GtkCList *clist);
122 static void real_unselect_all (GtkCList *clist);
123 static void tree_expand (GtkCTree *ctree,
126 static void tree_collapse (GtkCTree *ctree,
129 static void tree_collapse_to_depth (GtkCTree *ctree,
132 static void tree_toggle_expansion (GtkCTree *ctree,
135 static void change_focus_row_expansion (GtkCTree *ctree,
136 GtkCTreeExpansionType expansion);
137 static void real_select_row (GtkCList *clist,
141 static void real_unselect_row (GtkCList *clist,
145 static void real_tree_select (GtkCTree *ctree,
148 static void real_tree_unselect (GtkCTree *ctree,
151 static void tree_toggle_selection (GtkCTree *ctree,
154 static void real_tree_expand (GtkCTree *ctree,
156 static void real_tree_collapse (GtkCTree *ctree,
158 static void real_tree_move (GtkCTree *ctree,
160 GtkCTreeNode *new_parent,
161 GtkCTreeNode *new_sibling);
162 static void gtk_ctree_link (GtkCTree *ctree,
164 GtkCTreeNode *parent,
165 GtkCTreeNode *sibling,
166 gboolean update_focus_row);
167 static void gtk_ctree_unlink (GtkCTree *ctree,
169 gboolean update_focus_row);
170 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
172 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
177 static void tree_sort (GtkCTree *ctree,
180 static gint default_compare (GtkCList *clist,
183 static void fake_unselect_all (GtkCList *clist,
185 static GList * selection_find (GtkCList *clist,
187 GList *row_list_element);
188 static void resync_selection (GtkCList *clist,
190 static void real_undo_selection (GtkCList *clist);
191 static void select_row_recursive (GtkCTree *ctree,
205 CHANGE_FOCUS_ROW_EXPANSION,
209 typedef void (*GtkCTreeSignal1) (GtkObject *object,
214 typedef void (*GtkCTreeSignal2) (GtkObject *object,
220 typedef void (*GtkCTreeSignal3) (GtkObject *object,
224 typedef void (*GtkCTreeSignal4) (GtkObject *object,
225 GtkCTreeExpansionType arg1,
229 static GtkCListClass *parent_class = NULL;
230 static GtkContainerClass *container_class = NULL;
231 static guint ctree_signals[LAST_SIGNAL] = {0};
235 gtk_ctree_get_type (void)
237 static GtkType ctree_type = 0;
241 GtkTypeInfo ctree_info =
245 sizeof (GtkCTreeClass),
246 (GtkClassInitFunc) gtk_ctree_class_init,
247 (GtkObjectInitFunc) gtk_ctree_init,
248 /* reserved_1 */ NULL,
249 /* reserved_2 */ NULL,
250 (GtkClassInitFunc) NULL,
253 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
260 gtk_ctree_class_init (GtkCTreeClass *klass)
262 GtkObjectClass *object_class;
263 GtkWidgetClass *widget_class;
264 GtkCListClass *clist_class;
266 object_class = (GtkObjectClass *) klass;
267 widget_class = (GtkWidgetClass *) klass;
268 container_class = (GtkContainerClass *) klass;
269 clist_class = (GtkCListClass *) klass;
271 parent_class = gtk_type_class (GTK_TYPE_CLIST);
272 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
274 ctree_signals[TREE_SELECT_ROW] =
275 gtk_signal_new ("tree_select_row",
278 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
279 gtk_marshal_NONE__POINTER_INT,
280 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
281 ctree_signals[TREE_UNSELECT_ROW] =
282 gtk_signal_new ("tree_unselect_row",
285 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
286 gtk_marshal_NONE__POINTER_INT,
287 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
288 ctree_signals[TREE_EXPAND] =
289 gtk_signal_new ("tree_expand",
292 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
293 gtk_marshal_NONE__POINTER,
294 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
295 ctree_signals[TREE_COLLAPSE] =
296 gtk_signal_new ("tree_collapse",
299 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
300 gtk_marshal_NONE__POINTER,
301 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
302 ctree_signals[TREE_MOVE] =
303 gtk_signal_new ("tree_move",
306 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
307 gtk_marshal_NONE__POINTER_POINTER_POINTER,
308 GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER,
310 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
311 gtk_signal_new ("change_focus_row_expansion",
312 GTK_RUN_LAST | GTK_RUN_ACTION,
314 GTK_SIGNAL_OFFSET (GtkCTreeClass,
315 change_focus_row_expansion),
316 gtk_marshal_NONE__ENUM,
317 GTK_TYPE_NONE, 1, GTK_TYPE_C_TREE_EXPANSION_TYPE);
319 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
321 object_class->destroy = gtk_ctree_destroy;
323 widget_class->realize = gtk_ctree_realize;
324 widget_class->unrealize = gtk_ctree_unrealize;
325 widget_class->button_press_event = gtk_ctree_button_press;
326 widget_class->button_release_event = gtk_ctree_button_release;
327 widget_class->motion_notify_event = gtk_ctree_button_motion;
329 clist_class->select_row = real_select_row;
330 clist_class->unselect_row = real_unselect_row;
331 clist_class->undo_selection = real_undo_selection;
332 clist_class->resync_selection = resync_selection;
333 clist_class->selection_find = selection_find;
334 clist_class->click_column = NULL;
335 clist_class->draw_row = draw_row;
336 clist_class->clear = real_clear;
337 clist_class->select_all = real_select_all;
338 clist_class->unselect_all = real_unselect_all;
339 clist_class->fake_unselect_all = fake_unselect_all;
341 klass->tree_select_row = real_tree_select;
342 klass->tree_unselect_row = real_tree_unselect;
343 klass->tree_expand = real_tree_expand;
344 klass->tree_collapse = real_tree_collapse;
345 klass->tree_move = real_tree_move;
346 klass->change_focus_row_expansion = change_focus_row_expansion;
349 GtkBindingSet *binding_set;
351 binding_set = gtk_binding_set_by_class (klass);
352 gtk_binding_entry_add_signal (binding_set,
354 "change_focus_row_expansion", 1,
355 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
356 gtk_binding_entry_add_signal (binding_set,
358 "change_focus_row_expansion", 1,
359 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
360 gtk_binding_entry_add_signal (binding_set,
361 GDK_KP_Add, GDK_CONTROL_MASK,
362 "change_focus_row_expansion", 1,
364 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
365 gtk_binding_entry_add_signal (binding_set,
367 "change_focus_row_expansion", 1,
368 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
369 gtk_binding_entry_add_signal (binding_set,
371 "change_focus_row_expansion", 1,
372 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
373 gtk_binding_entry_add_signal (binding_set,
374 GDK_KP_Subtract, GDK_CONTROL_MASK,
375 "change_focus_row_expansion", 1,
377 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
378 gtk_binding_entry_add_signal (binding_set,
380 "change_focus_row_expansion", 1,
381 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
382 gtk_binding_entry_add_signal (binding_set,
384 "change_focus_row_expansion", 1,
385 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
386 gtk_binding_entry_add_signal (binding_set,
387 GDK_KP_Multiply, GDK_CONTROL_MASK,
388 "change_focus_row_expansion", 1,
390 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
396 gtk_ctree_init (GtkCTree *ctree)
398 ctree->xor_gc = NULL;
399 ctree->drag_icon = NULL;
400 ctree->tree_indent = 20;
401 ctree->tree_column = 0;
402 ctree->drag_row = -1;
403 ctree->drag_source = NULL;
404 ctree->drag_target = NULL;
405 ctree->insert_pos = GTK_CTREE_POS_AS_CHILD;
406 GTK_CLIST (ctree)->compare = default_compare;
407 ctree->reorderable = FALSE;
408 ctree->use_icons = TRUE;
409 ctree->in_drag = FALSE;
410 ctree->drag_rect = FALSE;
411 ctree->line_style = GTK_CTREE_LINES_SOLID;
415 gtk_ctree_destroy (GtkObject *object)
420 g_return_if_fail (object != NULL);
421 g_return_if_fail (GTK_IS_CTREE (object));
423 clist = GTK_CLIST (object);
425 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
427 gtk_clist_clear (GTK_CLIST (object));
429 if (clist->vscrollbar)
431 gtk_widget_unparent (clist->vscrollbar);
432 clist->vscrollbar = NULL;
434 if (clist->hscrollbar)
436 gtk_widget_unparent (clist->hscrollbar);
437 clist->hscrollbar = NULL;
440 for (i = 0; i < clist->columns; i++)
441 if (clist->column[i].button)
443 gtk_widget_unparent (clist->column[i].button);
444 clist->column[i].button = NULL;
447 if (GTK_OBJECT_CLASS (container_class)->destroy)
448 (*GTK_OBJECT_CLASS (container_class)->destroy) (object);
452 gtk_ctree_realize (GtkWidget *widget)
457 g_return_if_fail (widget != NULL);
458 g_return_if_fail (GTK_IS_CTREE (widget));
460 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
462 ctree = GTK_CTREE (widget);
464 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
465 values.background = widget->style->bg[GTK_STATE_NORMAL];
466 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
467 values.line_style = GDK_LINE_SOLID;
468 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
475 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
477 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
478 GDK_LINE_ON_OFF_DASH, None, None);
479 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
482 if (ctree->reorderable)
483 create_xor_gc (ctree);
487 gtk_ctree_unrealize (GtkWidget *widget)
491 g_return_if_fail (widget != NULL);
492 g_return_if_fail (GTK_IS_CTREE (widget));
494 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
496 ctree = GTK_CTREE (widget);
498 gdk_gc_destroy (ctree->lines_gc);
500 if (ctree->reorderable)
501 gdk_gc_destroy (ctree->xor_gc);
505 gtk_ctree_button_press (GtkWidget *widget,
506 GdkEventButton *event)
511 g_return_val_if_fail (widget != NULL, FALSE);
512 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
513 g_return_val_if_fail (event != NULL, FALSE);
515 ctree = GTK_CTREE (widget);
516 clist = GTK_CLIST (widget);
518 if (event->window == clist->clist_window)
520 gboolean collapse_expand = FALSE;
530 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
533 if (event->button == 2)
534 ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
536 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
538 if (ctree->reorderable && event->button == 2 && !ctree->in_drag &&
541 gdk_pointer_grab (event->window, FALSE,
542 GDK_POINTER_MOTION_HINT_MASK |
543 GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
544 NULL, NULL, event->time);
545 gtk_grab_add (widget);
546 ctree->in_drag = TRUE;
547 ctree->drag_source = work;
548 ctree->drag_target = NULL;
551 else if (event->button == 1 &&
552 (GTK_CTREE_ROW (work)->children &&
553 (event->type == GDK_2BUTTON_PRESS ||
554 ctree_is_hot_spot (ctree, work, row, x, y))))
556 if (GTK_CTREE_ROW (work)->expanded)
557 gtk_ctree_collapse (ctree, work);
559 gtk_ctree_expand (ctree, work);
561 collapse_expand = TRUE;
563 if (event->button == 1)
565 gint old_row = clist->focus_row;
566 gboolean no_focus_row = FALSE;
568 switch (clist->selection_mode)
570 case GTK_SELECTION_MULTIPLE:
571 case GTK_SELECTION_SINGLE:
572 if (!collapse_expand)
575 if (clist->focus_row == -1)
581 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
582 gdk_pointer_grab (clist->clist_window, FALSE,
583 GDK_POINTER_MOTION_HINT_MASK |
584 GDK_BUTTON1_MOTION_MASK |
585 GDK_BUTTON_RELEASE_MASK,
586 NULL, NULL, event->time);
587 gtk_grab_add (widget);
589 if (GTK_CLIST_ADD_MODE (clist))
591 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
592 if (GTK_WIDGET_HAS_FOCUS (widget))
594 gtk_widget_draw_focus (widget);
595 gdk_gc_set_line_attributes (clist->xor_gc, 1,
596 GDK_LINE_SOLID, 0, 0);
597 clist->focus_row = row;
598 gtk_widget_draw_focus (widget);
602 gdk_gc_set_line_attributes (clist->xor_gc, 1,
603 GDK_LINE_SOLID, 0, 0);
604 clist->focus_row = row;
607 else if (row != clist->focus_row)
609 if (GTK_WIDGET_HAS_FOCUS (widget))
611 gtk_widget_draw_focus (widget);
612 clist->focus_row = row;
613 gtk_widget_draw_focus (widget);
616 clist->focus_row = row;
619 if (!GTK_WIDGET_HAS_FOCUS (widget))
620 gtk_widget_grab_focus (widget);
629 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
633 gtk_ctree_button_motion (GtkWidget *widget,
634 GdkEventMotion *event)
641 gint insert_pos = GTK_CTREE_POS_AS_CHILD;
643 g_return_val_if_fail (widget != NULL, FALSE);
644 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
645 g_return_val_if_fail (event != NULL, FALSE);
647 ctree = GTK_CTREE (widget);
648 clist = GTK_CLIST (widget);
650 if (GTK_CLIST_IN_DRAG (clist))
651 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
654 if (event->window == clist->clist_window &&
655 ctree->in_drag && ctree->reorderable)
657 GdkModifierType modmask;
664 gdk_window_get_pointer (event->window, &x, &y, NULL);
666 /* delayed drag start */
667 if (!ctree->drag_target &&
668 y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
669 y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
671 GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
673 if (ctree->use_icons)
675 if (!ctree->drag_icon)
676 create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
679 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
680 gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
681 root_y - ctree->icon_height);
685 /* out of bounds check */
686 if (x < 0 || y < -3 || x > clist->clist_window_width ||
687 y > clist->clist_window_height + 3 ||
688 y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
690 if (ctree->drag_row >= 0)
692 if (ctree->drag_rect)
694 draw_xor_rect (ctree);
695 ctree->drag_rect = FALSE;
698 draw_xor_line (ctree);
699 ctree->drag_row = -1;
702 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
706 row = ROW_FROM_YPIXEL (clist, y);
708 /* re-calculate target (mouse left the window) */
709 if (ctree->drag_target && ctree->drag_row == -1)
710 ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row));
712 if (y < 0 || y > clist->clist_window_height ||
713 ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
714 || row >= clist->rows)
715 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
718 if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
719 insert_pos = GTK_CTREE_POS_BEFORE;
720 else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y
721 < clist->row_height / 4)
722 insert_pos = GTK_CTREE_POS_AFTER;
724 if (row != ctree->drag_row ||
725 (row == ctree->drag_row && ctree->insert_pos != insert_pos))
727 if (insert_pos != GTK_CTREE_POS_AS_CHILD)
729 if (ctree->drag_row >= 0)
731 if (ctree->drag_rect)
733 draw_xor_rect (ctree);
734 ctree->drag_rect = FALSE;
737 draw_xor_line (ctree);
739 ctree->insert_pos = insert_pos;
741 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
742 ctree->drag_row = row;
743 draw_xor_line (ctree);
745 else if (ctree->drag_target &&
746 !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
748 if (ctree->drag_row >= 0)
750 if (ctree->drag_rect)
751 draw_xor_rect (ctree);
753 draw_xor_line (ctree);
755 ctree->drag_rect = TRUE;
756 ctree->insert_pos = insert_pos;
758 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
759 ctree->drag_row = row;
760 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 if (ctree->use_icons && ctree->drag_icon)
790 gdk_window_destroy (ctree->drag_icon);
791 ctree->drag_icon = NULL;
794 if (ctree->drag_row >= 0)
796 if (ctree->drag_rect)
798 draw_xor_rect (ctree);
799 ctree->drag_rect = FALSE;
802 draw_xor_line (ctree);
803 ctree->drag_row = -1;
806 /* nop if out of bounds / source == target */
807 if (event->x < 0 || event->y < -3 ||
808 event->x > clist->clist_window_width ||
809 event->y > clist->clist_window_height + 3 ||
810 ctree->drag_target == ctree->drag_source ||
812 return GTK_WIDGET_CLASS (parent_class)->button_release_event
815 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
816 !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
819 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
821 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
823 gtk_signal_emit (GTK_OBJECT (ctree),
824 ctree_signals[TREE_MOVE],
826 GTK_CTREE_ROW (ctree->drag_target)->parent,
827 GTK_CTREE_ROW (ctree->drag_target)->sibling);
829 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
831 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
833 gtk_signal_emit (GTK_OBJECT (ctree),
834 ctree_signals[TREE_MOVE],
836 GTK_CTREE_ROW (ctree->drag_target)->parent,
839 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
841 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
843 gtk_signal_emit (GTK_OBJECT (ctree),
844 ctree_signals[TREE_MOVE],
847 GTK_CTREE_ROW (ctree->drag_target)->children);
850 ctree->drag_source = NULL;
851 ctree->drag_target = NULL;
853 else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) &&
854 (clist->selection_mode == GTK_SELECTION_SINGLE ||
855 clist->selection_mode == GTK_SELECTION_MULTIPLE))
861 if (gtk_clist_get_selection_info
862 (clist, event->x, event->y, &row, &column))
864 if (clist->anchor == clist->focus_row &&
865 (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row))))
866 tree_toggle_selection (ctree, work, column);
870 return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
874 create_drag_icon (GtkCTree *ctree,
879 GdkWindow *window = NULL;
880 GdkWindowAttr attributes;
881 gint attributes_mask;
884 GdkModifierType modmask;
888 clist = GTK_CLIST (ctree);
889 widget = GTK_WIDGET (ctree);
891 if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap))
893 mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
895 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
896 gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
898 attributes.window_type = GDK_WINDOW_TEMP;
899 attributes.x = root_x - ctree->icon_width / 2;
900 attributes.y = root_y - ctree->icon_height;
901 attributes.width = ctree->icon_width;
902 attributes.height = ctree->icon_height;
903 attributes.wclass = GDK_INPUT_OUTPUT;
904 attributes.visual = gtk_widget_get_visual (widget);
905 attributes.colormap = gtk_widget_get_colormap (widget);
906 attributes.event_mask = gtk_widget_get_events (widget);
908 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
910 window = gdk_window_new (widget->window, &attributes, attributes_mask);
911 gdk_window_set_back_pixmap (window, pixmap, FALSE);
913 gdk_window_shape_combine_mask (window, mask, 0, 0);
914 gdk_window_show (window);
916 ctree->drag_icon = window;
920 create_xor_gc (GtkCTree *ctree)
925 clist = GTK_CLIST (ctree);
927 values.foreground = GTK_WIDGET (clist)->style->bg[GTK_STATE_NORMAL];
928 values.function = GDK_XOR;
929 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
930 ctree->xor_gc = gdk_gc_new_with_values (clist->clist_window, &values,
934 gdk_gc_set_line_attributes (ctree->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
936 gdk_gc_set_dashes (ctree->xor_gc, 0, "\2\2", 2);
940 draw_xor_line (GtkCTree *ctree)
946 clist = GTK_CLIST (ctree);
948 level = GTK_CTREE_ROW (ctree->drag_target)->level;
950 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
951 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
953 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
955 switch (clist->column[ctree->tree_column].justification)
957 case GTK_JUSTIFY_CENTER:
958 case GTK_JUSTIFY_FILL:
959 case GTK_JUSTIFY_LEFT:
960 if (ctree->tree_column > 0)
961 gdk_draw_line (clist->clist_window, ctree->xor_gc,
962 COLUMN_LEFT_XPIXEL(clist, 0), y,
963 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
964 clist->column[ctree->tree_column - 1].area.width, y);
966 gdk_draw_line (clist->clist_window, ctree->xor_gc,
967 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
968 ctree->tree_indent * level -
969 (ctree->tree_indent - PM_SIZE) / 2, y,
970 GTK_WIDGET (ctree)->allocation.width, y);
972 case GTK_JUSTIFY_RIGHT:
973 if (ctree->tree_column < clist->columns - 1)
974 gdk_draw_line (clist->clist_window, ctree->xor_gc,
975 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
976 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
977 clist->column[clist->columns - 1].area.width, y);
979 gdk_draw_line (clist->clist_window, ctree->xor_gc,
980 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
981 + clist->column[ctree->tree_column].area.width
982 - ctree->tree_indent * level +
983 (ctree->tree_indent - PM_SIZE) / 2, y);
989 draw_xor_rect (GtkCTree *ctree)
997 clist = GTK_CLIST (ctree);
999 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1001 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1003 switch (clist->column[ctree->tree_column].justification)
1005 case GTK_JUSTIFY_CENTER:
1006 case GTK_JUSTIFY_FILL:
1007 case GTK_JUSTIFY_LEFT:
1008 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1009 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
1011 points[3].x = points[0].x;
1012 points[3].y = y - clist->row_height - 1;
1013 points[1].x = clist->clist_window_width - 1;
1014 points[1].y = points[0].y;
1015 points[2].x = points[1].x;
1016 points[2].y = points[3].y;
1018 for (i = 0; i < 3; i++)
1019 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1020 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
1022 if (ctree->tree_column > 0)
1024 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1025 clist->column[ctree->tree_column - 1].area.width ;
1027 points[3].x = points[0].x;
1028 points[3].y = y - clist->row_height - 1;
1030 points[1].y = points[0].y;
1032 points[2].y = points[3].y;
1034 for (i = 0; i < 3; i++)
1035 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1036 points[i].x, points[i].y, points[i+1].x,
1040 case GTK_JUSTIFY_RIGHT:
1041 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
1042 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
1043 clist->column[ctree->tree_column].area.width;
1045 points[3].x = points[0].x;
1046 points[3].y = y - clist->row_height - 1;
1048 points[1].y = points[0].y;
1050 points[2].y = points[3].y;
1052 for (i = 0; i < 3; i++)
1053 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1054 points[i].x, points[i].y, points[i+1].x, points[i+1].y);
1056 if (ctree->tree_column < clist->columns - 1)
1058 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
1060 points[3].x = points[0].x;
1061 points[3].y = y - clist->row_height - 1;
1062 points[1].x = clist->clist_window_width - 1;
1063 points[1].y = points[0].y;
1064 points[2].x = points[1].x;
1065 points[2].y = points[3].y;
1067 for (i = 0; i < 3; i++)
1068 gdk_draw_line (clist->clist_window, ctree->xor_gc,
1069 points[i].x, points[i].y, points[i+1].x,
1077 draw_row (GtkCList *clist,
1080 GtkCListRow *clist_row)
1086 GdkRectangle row_rectangle;
1087 GdkRectangle cell_rectangle;
1088 GdkRectangle clip_rectangle;
1089 GdkRectangle intersect_rectangle;
1092 gint i, offset = 0, width, height, pixmap_width = 0, string_width = 0;
1093 gint xsrc, ysrc, xdest = 0, ydest;
1094 gboolean need_redraw = TRUE;
1095 gboolean draw_pixmap = FALSE;
1097 g_return_if_fail (clist != NULL);
1099 /* bail now if we arn't drawable yet */
1100 if (!GTK_WIDGET_DRAWABLE (clist))
1103 if (row < 0 || row >= clist->rows)
1106 widget = GTK_WIDGET (clist);
1107 ctree = GTK_CTREE (clist);
1109 /* if the function is passed the pointer to the row instead of null,
1110 * it avoids this expensive lookup */
1112 clist_row = (g_list_nth (clist->row_list, row))->data;
1114 /* rectangle of the entire row */
1115 row_rectangle.x = 0;
1116 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1117 row_rectangle.width = clist->clist_window_width;
1118 row_rectangle.height = clist->row_height;
1120 /* rectangle of the cell spacing above the row */
1121 cell_rectangle.x = 0;
1122 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1123 cell_rectangle.width = row_rectangle.width;
1124 cell_rectangle.height = CELL_SPACING;
1126 /* rectangle used to clip drawing operations, it's y and height
1127 * positions only need to be set once, so we set them once here.
1128 * the x and width are set withing the drawing loop below once per
1130 clip_rectangle.y = row_rectangle.y;
1131 clip_rectangle.height = row_rectangle.height;
1133 /* select GC for background rectangle */
1134 if (clist_row->state == GTK_STATE_SELECTED)
1136 fg_gc = widget->style->fg_gc[GTK_STATE_SELECTED];
1137 bg_gc = widget->style->bg_gc[GTK_STATE_SELECTED];
1141 if (clist_row->fg_set)
1143 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1144 fg_gc = clist->fg_gc;
1147 fg_gc = widget->style->fg_gc[GTK_STATE_NORMAL];
1149 if (clist_row->bg_set)
1151 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1152 bg_gc = clist->bg_gc;
1155 bg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1159 /* draw the cell borders and background */
1162 if (gdk_rectangle_intersect (area, &cell_rectangle,
1163 &intersect_rectangle))
1164 gdk_draw_rectangle (clist->clist_window,
1165 widget->style->base_gc[GTK_STATE_NORMAL],
1167 intersect_rectangle.x,
1168 intersect_rectangle.y,
1169 intersect_rectangle.width,
1170 intersect_rectangle.height);
1172 /* the last row has to clear it's bottom cell spacing too */
1173 if (clist_row == clist->row_list_end->data)
1175 cell_rectangle.y += clist->row_height + CELL_SPACING;
1177 if (gdk_rectangle_intersect (area, &cell_rectangle,
1178 &intersect_rectangle))
1179 gdk_draw_rectangle (clist->clist_window,
1180 widget->style->base_gc[GTK_STATE_NORMAL],
1182 intersect_rectangle.x,
1183 intersect_rectangle.y,
1184 intersect_rectangle.width,
1185 intersect_rectangle.height);
1188 if (gdk_rectangle_intersect
1189 (area, &row_rectangle, &intersect_rectangle))
1191 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
1192 gdk_draw_rectangle (clist->clist_window,
1195 intersect_rectangle.x,
1196 intersect_rectangle.y,
1197 intersect_rectangle.width,
1198 intersect_rectangle.height);
1200 gdk_window_clear_area (clist->clist_window,
1201 intersect_rectangle.x,
1202 intersect_rectangle.y,
1203 intersect_rectangle.width,
1204 intersect_rectangle.height);
1207 need_redraw = FALSE;
1211 gdk_draw_rectangle (clist->clist_window,
1212 widget->style->base_gc[GTK_STATE_NORMAL],
1216 cell_rectangle.width,
1217 cell_rectangle.height);
1219 /* the last row has to clear it's bottom cell spacing too */
1220 if (clist_row == clist->row_list_end->data)
1222 cell_rectangle.y += clist->row_height + CELL_SPACING;
1224 gdk_draw_rectangle (clist->clist_window,
1225 widget->style->base_gc[GTK_STATE_NORMAL],
1229 cell_rectangle.width,
1230 cell_rectangle.height);
1233 if (clist_row->state == GTK_STATE_SELECTED || clist_row->bg_set)
1234 gdk_draw_rectangle (clist->clist_window,
1239 row_rectangle.width,
1240 row_rectangle.height);
1242 gdk_window_clear_area (clist->clist_window,
1245 row_rectangle.width,
1246 row_rectangle.height);
1249 /* iterate and draw all the columns (row cells) and draw their contents */
1250 for (i = 0; i < clist->columns; i++)
1253 if (!need_redraw && ctree->tree_column != i)
1256 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1257 clip_rectangle.width = clist->column[i].area.width;
1259 /* calculate clipping region */
1260 if (i == ctree->tree_column)
1262 clip_rectangle.y -= CELL_SPACING;
1263 clip_rectangle.height += CELL_SPACING;
1266 if (i == ctree->tree_column)
1269 if (clist_row->state == GTK_STATE_SELECTED)
1271 gdk_gc_set_foreground (ctree->lines_gc,
1272 >K_WIDGET (ctree)->style->
1273 fg[GTK_STATE_SELECTED]);
1274 gdk_gc_set_background (ctree->lines_gc,
1275 >K_WIDGET (ctree)->style->
1276 bg[GTK_STATE_SELECTED]);
1280 gdk_gc_set_foreground (ctree->lines_gc,
1281 >K_WIDGET (ctree)->style->
1282 fg[GTK_STATE_NORMAL]);
1283 if (clist_row->bg_set)
1284 gdk_gc_set_background (ctree->lines_gc,
1285 &clist_row->background);
1288 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1290 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1292 xdest = clip_rectangle.x + clip_rectangle.width - 1 -
1293 (((GtkCTreeRow *) clist_row)->level - 1) *
1296 gdk_draw_line (clist->clist_window,
1299 row_rectangle.y - 1,
1300 MAX (xdest - TAB_SIZE, clip_rectangle.x - 1),
1301 row_rectangle.y - 1);
1303 if (clist_row == clist->row_list_end->data)
1305 (clist->clist_window,
1308 row_rectangle.y + clist->row_height,
1309 MAX (clip_rectangle.x + clip_rectangle.width -
1311 (((GtkCTreeRow *) clist_row)->level > 1) *
1312 MIN (ctree->tree_indent / 2, TAB_SIZE),
1313 clip_rectangle.x - 1),
1314 row_rectangle.y + clist->row_height);
1316 if (clist_row->state != GTK_STATE_SELECTED)
1318 (clist->clist_window,
1319 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1321 clip_rectangle.x + clip_rectangle.width,
1323 CELL_SPACING + COLUMN_INSET,
1324 row_rectangle.height);
1328 xdest = clip_rectangle.x +
1329 (((GtkCTreeRow *) clist_row)->level - 1) *
1332 gdk_draw_line (clist->clist_window,
1334 MIN (xdest + TAB_SIZE,
1335 clip_rectangle.x + clip_rectangle.width),
1336 row_rectangle.y - 1,
1337 clist->clist_window_width,
1338 row_rectangle.y - 1);
1340 if (clist_row == clist->row_list_end->data)
1342 (clist->clist_window, ctree->lines_gc,
1343 MIN (clip_rectangle.x + TAB_SIZE +
1344 (((GtkCTreeRow *) clist_row)->level > 1) *
1345 MIN (ctree->tree_indent / 2, TAB_SIZE),
1346 clip_rectangle.x + clip_rectangle.width),
1347 row_rectangle.y + clist->row_height,
1348 clist->clist_window_width,
1349 row_rectangle.y + clist->row_height);
1351 if (clist_row->state != GTK_STATE_SELECTED)
1353 (clist->clist_window,
1354 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1356 clip_rectangle.x - CELL_SPACING - COLUMN_INSET,
1358 CELL_SPACING + COLUMN_INSET,
1359 row_rectangle.height);
1366 rect = &clip_rectangle;
1371 if (!gdk_rectangle_intersect (area, &clip_rectangle,
1372 &intersect_rectangle))
1374 rect = &intersect_rectangle;
1377 /* calculate real width for column justification */
1378 switch (clist_row->cell[i].type)
1380 case GTK_CELL_EMPTY:
1385 width = gdk_string_width (GTK_WIDGET (clist)->style->font,
1386 GTK_CELL_TEXT (clist_row->cell[i])->text);
1389 case GTK_CELL_PIXMAP:
1390 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1392 pixmap_width = width;
1395 case GTK_CELL_PIXTEXT:
1396 if (i == ctree->tree_column)
1401 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1402 gdk_window_get_size (GTK_CELL_PIXTEXT
1403 (clist_row->cell[i])->pixmap,
1406 pixmap_width = width;
1407 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1409 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
1410 string_width += gdk_string_width
1411 (GTK_WIDGET (clist)->style->font,
1412 GTK_CELL_PIXTEXT(clist_row->cell[i])->text);
1414 width += string_width +
1415 ((GtkCTreeRow *)clist_row)->level * ctree->tree_indent;
1419 gdk_window_get_size (GTK_CELL_PIXTEXT
1420 (clist_row->cell[i])->pixmap,
1422 pixmap_width = width;
1423 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1424 width += gdk_string_width (GTK_WIDGET (clist)->style->font,
1426 (clist_row->cell[i])->text);
1430 case GTK_CELL_WIDGET:
1440 switch (clist->column[i].justification)
1442 case GTK_JUSTIFY_LEFT:
1443 offset = clip_rectangle.x;
1446 case GTK_JUSTIFY_RIGHT:
1447 offset = (clip_rectangle.x + clip_rectangle.width) - width;
1450 case GTK_JUSTIFY_CENTER:
1451 offset = (clip_rectangle.x + (clip_rectangle.width / 2))
1455 case GTK_JUSTIFY_FILL:
1456 offset = (clip_rectangle.x + (clip_rectangle.width / 2))
1465 if (i == ctree->tree_column)
1471 GtkCTreeNode *work2;
1485 yoffset = (clip_rectangle.height - PM_SIZE) / 2;
1486 xoffset = (ctree->tree_indent - PM_SIZE) / 2;
1487 ycenter = clip_rectangle.y + (clip_rectangle.height / 2);
1488 ydest = ycenter - height / 2 + clist_row->cell[i].vertical;
1490 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1491 gdk_gc_set_clip_rectangle (fg_gc, rect);
1492 if (ctree->line_style != GTK_CTREE_LINES_NONE)
1494 gdk_gc_set_clip_origin (ctree->lines_gc, 0, 0);
1495 gdk_gc_set_clip_rectangle (ctree->lines_gc, rect);
1498 switch (clist->column[i].justification)
1500 case GTK_JUSTIFY_CENTER:
1501 case GTK_JUSTIFY_FILL:
1502 offset = clip_rectangle.x;
1503 case GTK_JUSTIFY_LEFT:
1505 xdest = clip_rectangle.x - xoffset +
1506 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1507 xcenter = xdest + (ctree->tree_indent / 2);
1509 switch (ctree->line_style)
1511 case GTK_CTREE_LINES_NONE:
1513 case GTK_CTREE_LINES_TABBED:
1514 xdest = clip_rectangle.x +
1515 (((GtkCTreeRow *) clist_row)->level - 1) *
1517 xcenter = xdest + TAB_SIZE;
1519 gdk_gc_set_clip_origin (clist->bg_gc, 0, 0);
1520 gdk_gc_set_clip_rectangle (clist->bg_gc, rect);
1522 gdk_gc_set_clip_origin
1523 (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0);
1524 gdk_gc_set_clip_rectangle
1525 (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect);
1527 work = ((GtkCTreeRow *)clist_row)->parent;
1528 next_level = ((GtkCTreeRow *)clist_row)->level;
1530 if (!(((GtkCTreeRow *)clist_row)->sibling ||
1531 (((GtkCTreeRow *)clist_row)->children &&
1532 ((GtkCTreeRow *)clist_row)->expanded)))
1534 work2 = gtk_ctree_find_glist_ptr
1535 (ctree, (GtkCTreeRow *) clist_row);
1537 if (GTK_CTREE_NODE_NEXT (work2))
1539 GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level;
1546 xcenter -= ctree->tree_indent;
1548 if (GTK_CTREE_ROW(work)->row.bg_set)
1550 gdk_gc_set_foreground
1552 &(GTK_CTREE_ROW(work)->row.background));
1553 mbg_gc = clist->bg_gc;
1556 mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1558 if (clist_row->state != GTK_STATE_SELECTED)
1559 gdk_draw_rectangle (clist->clist_window, mbg_gc, TRUE,
1561 ctree->tree_indent, rect->height);
1563 if (next_level > GTK_CTREE_ROW (work)->level)
1565 (clist->clist_window, ctree->lines_gc,
1567 xcenter, rect->y + rect->height);
1570 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1571 xcenter, clip_rectangle.y,
1574 in = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1576 if (clist_row->state != GTK_STATE_SELECTED)
1578 work2 = GTK_CTREE_ROW (work)->parent;
1580 if (work2 && GTK_CTREE_ROW (work2)->row.bg_set)
1582 gdk_gc_set_foreground
1584 &(GTK_CTREE_ROW (work2)->row.background));
1587 (clist->clist_window, clist->bg_gc, TRUE,
1591 row_rectangle.height / 2 + 1);
1593 if (GTK_CTREE_ROW (work)->row.bg_set)
1594 gdk_gc_set_foreground
1596 &(GTK_CTREE_ROW (work)->row.background));
1600 (clist->clist_window,
1601 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1606 row_rectangle.height / 2 + 1);
1608 gdk_draw_arc (clist->clist_window, mbg_gc,
1610 xcenter, clip_rectangle.y,
1611 in, clist->row_height,
1615 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1617 xcenter, clip_rectangle.y,
1618 in, clist->row_height,
1621 work = GTK_CTREE_ROW (work)->parent;
1624 if (clist_row->state != GTK_STATE_SELECTED)
1626 (clist->clist_window,
1627 widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
1628 clip_rectangle.x, row_rectangle.y,
1629 TAB_SIZE, row_rectangle.height);
1631 xcenter = xdest + (ctree->tree_indent / 2);
1633 if (clist_row->bg_set)
1634 gdk_gc_set_foreground
1635 (clist->bg_gc, &clist_row->background);
1637 if (((GtkCTreeRow *)clist_row)->is_leaf)
1639 points[0].x = xdest + TAB_SIZE;
1640 points[0].y = row_rectangle.y - 1;
1642 points[1].x = points[0].x - 4;
1643 points[1].y = points[0].y;
1645 points[2].x = points[1].x - 2;
1646 points[2].y = points[1].y + 3;
1648 points[3].x = points[2].x;
1649 points[3].y = points[2].y + clist->row_height - 5;
1651 points[4].x = points[3].x + 2;
1652 points[4].y = points[3].y + 3;
1654 points[5].x = points[4].x + 4;
1655 points[5].y = points[4].y;
1657 if (clist_row->state != GTK_STATE_SELECTED)
1658 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE,
1661 gdk_draw_lines (clist->clist_window, ctree->lines_gc,
1666 if (clist_row->state != GTK_STATE_SELECTED)
1667 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1668 xdest, row_rectangle.y - 1,
1669 2 * TAB_SIZE, clist->row_height,
1672 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1674 xdest, row_rectangle.y - 1,
1675 2 * TAB_SIZE, clist->row_height,
1680 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1681 gdk_gc_set_clip_rectangle (clist->bg_gc, NULL);
1682 gdk_gc_set_clip_rectangle
1683 (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL);
1687 xcenter = xdest + (ctree->tree_indent / 2);
1688 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1690 offset_x += abs ((clip_rectangle.x + clist->hoffset) %
1692 offset_y = abs ((clip_rectangle.y + clist->voffset) % 2);
1695 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1696 xcenter, clip_rectangle.y + offset_y, xcenter,
1697 (((GtkCTreeRow *)clist_row)->sibling) ?
1698 rect->y + rect->height : ycenter);
1700 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1701 xcenter + offset_x, ycenter,
1702 xcenter + PM_SIZE / 2 + 2, ycenter);
1704 work = ((GtkCTreeRow *)clist_row)->parent;
1707 xcenter -= ctree->tree_indent;
1708 if (GTK_CTREE_ROW (work)->sibling)
1709 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1710 xcenter, clip_rectangle.y + offset_y,
1711 xcenter, rect->y + rect->height);
1712 work = GTK_CTREE_ROW (work)->parent;
1714 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1718 if (((GtkCTreeRow *)clist_row)->children)
1720 if (clist_row->state == GTK_STATE_SELECTED)
1722 if (clist_row->fg_set)
1725 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
1731 (clist)->style->fg_gc[GTK_STATE_SELECTED];
1735 gdk_gc_set_clip_rectangle (cgc, rect);
1737 switch (ctree->line_style)
1739 case GTK_CTREE_LINES_NONE:
1740 if (!((GtkCTreeRow *)clist_row)->expanded)
1742 points[0].x = xdest + xoffset + (PM_SIZE+2) / 6 + 2;
1743 points[0].y = clip_rectangle.y + yoffset - 1;
1744 points[1].x = points[0].x;
1745 points[1].y = points[0].y + (PM_SIZE+2);
1746 points[2].x = points[0].x + 2 * (PM_SIZE+2) / 3 - 1;
1747 points[2].y = points[0].y + (PM_SIZE+2) / 2;
1751 points[0].x = xdest + xoffset;
1752 points[0].y = clip_rectangle.y + yoffset
1754 points[1].x = points[0].x + (PM_SIZE+2);
1755 points[1].y = points[0].y;
1756 points[2].x = points[0].x + (PM_SIZE+2) / 2;
1757 points[2].y = clip_rectangle.y + yoffset +
1758 2 * (PM_SIZE+2) / 3;
1761 gdk_draw_polygon (clist->clist_window,
1762 GTK_WIDGET (clist)->style->
1763 fg_gc[GTK_STATE_SELECTED],
1765 gdk_draw_polygon (clist->clist_window, tgc, FALSE,
1768 case GTK_CTREE_LINES_TABBED:
1769 xcenter = xdest + PM_SIZE + 2;
1770 gdk_draw_arc (clist->clist_window,
1771 GTK_WIDGET (clist)->style->
1772 fg_gc[GTK_STATE_SELECTED],
1774 xcenter - PM_SIZE/2,
1775 ycenter - PM_SIZE/2,
1776 PM_SIZE, PM_SIZE, 0, 360 * 64);
1778 gdk_draw_line (clist->clist_window, tgc,
1784 if (!((GtkCTreeRow *)clist_row)->expanded)
1785 gdk_draw_line (clist->clist_window, tgc,
1786 xcenter, clip_rectangle.y + yoffset + 2,
1788 clip_rectangle.y + yoffset + PM_SIZE-2);
1792 (clist->clist_window,
1793 GTK_WIDGET (clist)->style->fg_gc[GTK_STATE_SELECTED],
1796 clip_rectangle.y + yoffset,
1799 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
1801 clip_rectangle.y + yoffset,
1804 gdk_draw_line (clist->clist_window, tgc,
1805 xdest + xoffset + 2, ycenter,
1806 xdest + xoffset + PM_SIZE - 2, ycenter);
1808 if (!((GtkCTreeRow *)clist_row)->expanded)
1810 xcenter = xdest + (ctree->tree_indent / 2);
1811 gdk_draw_line (clist->clist_window, tgc,
1813 clip_rectangle.y + yoffset + 2,
1815 clip_rectangle.y + yoffset +
1821 gdk_gc_set_clip_rectangle (cgc, NULL);
1824 xdest += offset - clip_rectangle.x + ctree->tree_indent +
1825 clist_row->cell[i].horizontal;
1827 if (pixmap_width && xdest + pixmap_width >= rect->x &&
1828 xdest <= rect->x + rect->width)
1833 case GTK_JUSTIFY_RIGHT:
1836 xdest = clip_rectangle.x + clip_rectangle.width + xoffset - 1 -
1837 (((GtkCTreeRow *) clist_row)->level - 1) * ctree->tree_indent;
1839 switch (ctree->line_style)
1841 case GTK_CTREE_LINES_NONE:
1843 case GTK_CTREE_LINES_TABBED:
1844 xdest = clip_rectangle.x + clip_rectangle.width - 1
1845 - (((GtkCTreeRow *) clist_row)->level - 1)
1846 * ctree->tree_indent;
1847 xcenter = xdest - TAB_SIZE;
1849 gdk_gc_set_clip_origin (clist->bg_gc, 0, 0);
1850 gdk_gc_set_clip_rectangle (clist->bg_gc, rect);
1852 gdk_gc_set_clip_origin
1853 (widget->style->bg_gc[GTK_STATE_PRELIGHT], 0, 0);
1854 gdk_gc_set_clip_rectangle
1855 (widget->style->bg_gc[GTK_STATE_PRELIGHT], rect);
1857 work = ((GtkCTreeRow *)clist_row)->parent;
1858 next_level = ((GtkCTreeRow *)clist_row)->level;
1860 if (!(((GtkCTreeRow *)clist_row)->sibling ||
1861 (((GtkCTreeRow *)clist_row)->children &&
1862 ((GtkCTreeRow *)clist_row)->expanded)))
1864 work2 = gtk_ctree_find_glist_ptr
1865 (ctree, (GtkCTreeRow *) clist_row);
1867 if (GTK_CTREE_NODE_NEXT (work2))
1869 GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (work2))->level;
1876 xcenter += ctree->tree_indent;
1878 if (GTK_CTREE_ROW(work)->row.bg_set)
1880 gdk_gc_set_foreground
1882 &(GTK_CTREE_ROW (work)->row.background));
1883 mbg_gc = clist->bg_gc;
1886 mbg_gc = widget->style->bg_gc[GTK_STATE_PRELIGHT];
1888 if (clist_row->state != GTK_STATE_SELECTED)
1889 gdk_draw_rectangle (clist->clist_window,
1891 xcenter - ctree->tree_indent + 1,
1896 if (next_level > GTK_CTREE_ROW (work)->level)
1898 (clist->clist_window, ctree->lines_gc,
1900 xcenter, rect->y + rect->height);
1903 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1904 xcenter, clip_rectangle.y,
1907 in = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1909 if (clist_row->state != GTK_STATE_SELECTED)
1911 work2 = GTK_CTREE_ROW (work)->parent;
1913 if (work2 && GTK_CTREE_ROW (work2)->row.bg_set)
1915 gdk_gc_set_foreground
1917 &(GTK_CTREE_ROW (work2)->row.background));
1920 (clist->clist_window, clist->bg_gc, TRUE,
1921 xcenter + 1 - in / 2 - in % 2,
1924 row_rectangle.height / 2 + 1);
1926 if (GTK_CTREE_ROW (work)->row.bg_set)
1927 gdk_gc_set_foreground
1929 &(GTK_CTREE_ROW(work)->row.background));
1933 (clist->clist_window,
1934 widget->style->bg_gc[GTK_STATE_PRELIGHT],
1936 xcenter + 1 - in / 2 - in % 2,
1939 row_rectangle.height / 2 + 1);
1941 gdk_draw_arc (clist->clist_window, mbg_gc, TRUE,
1942 xcenter - in, clip_rectangle.y,
1943 in, clist->row_height,
1947 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
1949 xcenter - in, clip_rectangle.y,
1950 in, clist->row_height,
1954 work = GTK_CTREE_ROW (work)->parent;
1957 if (clist_row->state != GTK_STATE_SELECTED)
1959 (clist->clist_window,
1960 widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
1961 xcenter + 1, row_rectangle.y,
1962 TAB_SIZE, row_rectangle.height);
1964 xcenter = xdest - (ctree->tree_indent / 2);
1966 if (clist_row->bg_set)
1967 gdk_gc_set_foreground
1968 (clist->bg_gc, &clist_row->background);
1970 if (((GtkCTreeRow *)clist_row)->is_leaf)
1972 points[0].x = xdest - TAB_SIZE;
1973 points[0].y = row_rectangle.y - 1;
1975 points[1].x = points[0].x + 4;
1976 points[1].y = points[0].y;
1978 points[2].x = points[1].x + 2;
1979 points[2].y = points[1].y + 3;
1981 points[3].x = points[2].x;
1982 points[3].y = points[2].y + clist->row_height - 5;
1984 points[4].x = points[3].x - 2;
1985 points[4].y = points[3].y + 3;
1987 points[5].x = points[4].x - 4;
1988 points[5].y = points[4].y;
1990 if (clist_row->state != GTK_STATE_SELECTED)
1991 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE,
1994 gdk_draw_lines (clist->clist_window, ctree->lines_gc,
1999 if (clist_row->state != GTK_STATE_SELECTED)
2000 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
2001 xdest - 2 * TAB_SIZE,
2002 row_rectangle.y - 1,
2003 2 * TAB_SIZE, clist->row_height,
2004 270 * 64, 180 * 64);
2006 gdk_draw_arc (clist->clist_window, ctree->lines_gc,
2008 xdest - 2 * TAB_SIZE,
2009 row_rectangle.y - 1,
2010 2 * TAB_SIZE, clist->row_height,
2011 270 * 64, 180 * 64);
2014 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
2015 gdk_gc_set_clip_rectangle (clist->bg_gc, NULL);
2016 gdk_gc_set_clip_rectangle
2017 (widget->style->bg_gc[GTK_STATE_PRELIGHT], NULL);
2021 xcenter = xdest - (ctree->tree_indent / 2);
2022 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
2024 offset_x += abs ((clip_rectangle.x + clist->hoffset) %
2026 offset_y = abs ((clip_rectangle.y + clist->voffset) % 2);
2029 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2030 xcenter, clip_rectangle.y + offset_y,
2032 (((GtkCTreeRow *)clist_row)->sibling) ?
2033 rect->y + rect->height : ycenter);
2035 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2036 xcenter - offset_x, ycenter,
2037 xcenter - PM_SIZE / 2 - 2, ycenter);
2039 work = ((GtkCTreeRow *)clist_row)->parent;
2042 xcenter += ctree->tree_indent;
2043 if (GTK_CTREE_ROW (work)->sibling)
2044 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2045 xcenter, clip_rectangle.y - offset_y,
2046 xcenter, rect->y + rect->height);
2047 work = GTK_CTREE_ROW (work)->parent;
2049 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
2053 if (((GtkCTreeRow *)clist_row)->children)
2055 if (clist_row->state == GTK_STATE_SELECTED)
2057 if (clist_row->fg_set)
2060 tgc = widget->style->fg_gc[GTK_STATE_NORMAL];
2066 GTK_WIDGET(clist)->style->fg_gc[GTK_STATE_SELECTED];
2070 gdk_gc_set_clip_rectangle (cgc, rect);
2072 switch (ctree->line_style)
2074 case GTK_CTREE_LINES_NONE:
2075 if (!((GtkCTreeRow *)clist_row)->expanded)
2077 points[0].x = xdest - xoffset - (PM_SIZE+2) / 6 - 2;
2078 points[0].y = clip_rectangle.y + yoffset - 1;
2079 points[1].x = points[0].x;
2080 points[1].y = points[0].y + (PM_SIZE+2);
2081 points[2].x = points[0].x - 2 * (PM_SIZE+2) / 3 + 1;
2082 points[2].y = points[0].y + (PM_SIZE+2) / 2;
2086 points[0].x = xdest - xoffset;
2087 points[0].y = clip_rectangle.y + yoffset +
2089 points[1].x = points[0].x - (PM_SIZE+2);
2090 points[1].y = points[0].y;
2091 points[2].x = points[0].x - (PM_SIZE+2) / 2;
2092 points[2].y = clip_rectangle.y + yoffset +
2093 2 * (PM_SIZE+2) / 3;
2096 gdk_draw_polygon (clist->clist_window,
2097 GTK_WIDGET (clist)->style->
2098 fg_gc[GTK_STATE_SELECTED],
2100 gdk_draw_polygon (clist->clist_window, tgc, FALSE,
2103 case GTK_CTREE_LINES_TABBED:
2104 xcenter = xdest - PM_SIZE - 2;
2106 gdk_draw_arc (clist->clist_window,
2107 GTK_WIDGET (clist)->style->
2108 fg_gc[GTK_STATE_SELECTED],
2110 xcenter - PM_SIZE/2,
2111 ycenter - PM_SIZE/2,
2112 PM_SIZE, PM_SIZE, 0, 360 * 64);
2114 gdk_draw_line (clist->clist_window, tgc,
2120 if (!((GtkCTreeRow *)clist_row)->expanded)
2122 gdk_draw_line (clist->clist_window, tgc, xcenter,
2123 clip_rectangle.y + yoffset + 2,
2124 xcenter, clip_rectangle.y + yoffset
2129 gdk_draw_rectangle (clist->clist_window,
2130 GTK_WIDGET(clist)->style->
2131 fg_gc[GTK_STATE_SELECTED], TRUE,
2132 xdest - xoffset - PM_SIZE,
2133 clip_rectangle.y + yoffset,
2136 gdk_draw_rectangle (clist->clist_window, tgc, FALSE,
2137 xdest - xoffset - PM_SIZE,
2138 clip_rectangle.y + yoffset,
2141 gdk_draw_line (clist->clist_window, tgc,
2142 xdest - xoffset - 2, ycenter,
2143 xdest - xoffset - PM_SIZE + 2, ycenter);
2145 if (!((GtkCTreeRow *)clist_row)->expanded)
2147 xcenter = xdest - (ctree->tree_indent / 2);
2148 gdk_draw_line (clist->clist_window, tgc, xcenter,
2149 clip_rectangle.y + yoffset + 2,
2150 xcenter, clip_rectangle.y + yoffset
2154 gdk_gc_set_clip_rectangle (cgc, NULL);
2157 xdest -= (ctree->tree_indent + pixmap_width
2158 + clist_row->cell[i].horizontal);
2160 if (pixmap_width && xdest + pixmap_width >= rect->x &&
2161 xdest <= rect->x + rect->width)
2170 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2172 gdk_gc_set_clip_mask
2173 (fg_gc, GTK_CELL_PIXTEXT (clist_row->cell[i])->mask);
2174 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2177 if (xdest < clip_rectangle.x)
2179 xsrc = clip_rectangle.x - xdest;
2180 pixmap_width -= xsrc;
2181 xdest = clip_rectangle.x;
2184 if (xdest + pixmap_width >
2185 clip_rectangle.x + clip_rectangle.width)
2187 (clip_rectangle.x + clip_rectangle.width) - xdest;
2189 if (ydest < clip_rectangle.y)
2191 ysrc = clip_rectangle.y - ydest;
2193 ydest = clip_rectangle.y;
2196 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2197 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2199 gdk_draw_pixmap (clist->clist_window, fg_gc,
2201 (clist_row->cell[i])->pixmap,
2202 xsrc, ysrc, xdest, ydest,
2203 pixmap_width, height);
2210 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2211 xdest -= (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
2214 xdest += (GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
2217 delta = CELL_SPACING - (rect->y - clip_rectangle.y);
2221 rect->height -= delta;
2224 gdk_gc_set_clip_rectangle (fg_gc, rect);
2227 (clist->clist_window, widget->style->font, fg_gc, xdest,
2228 row_rectangle.y + clist->row_center_offset +
2229 clist_row->cell[i].vertical,
2230 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2232 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2236 switch (clist_row->cell[i].type)
2238 case GTK_CELL_EMPTY:
2243 gdk_gc_set_clip_rectangle (fg_gc, rect);
2245 gdk_draw_string (clist->clist_window,
2246 widget->style->font,
2248 offset + clist_row->cell[i].horizontal,
2249 row_rectangle.y + clist->row_center_offset +
2250 clist_row->cell[i].vertical,
2251 GTK_CELL_TEXT (clist_row->cell[i])->text);
2253 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2256 case GTK_CELL_PIXMAP:
2259 xdest = offset + clist_row->cell[i].horizontal;
2260 ydest = (clip_rectangle.y + (clip_rectangle.height / 2))
2261 - height / 2 + clist_row->cell[i].vertical;
2263 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2265 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXMAP
2266 (clist_row->cell[i])->mask);
2267 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2270 if (xdest < clip_rectangle.x)
2272 xsrc = clip_rectangle.x - xdest;
2273 pixmap_width -= xsrc;
2274 xdest = clip_rectangle.x;
2277 if (xdest + pixmap_width >
2278 clip_rectangle.x + clip_rectangle.width)
2279 pixmap_width = (clip_rectangle.x + clip_rectangle.width) -
2282 if (ydest < clip_rectangle.y)
2284 ysrc = clip_rectangle.y - ydest;
2286 ydest = clip_rectangle.y;
2289 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2290 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2292 gdk_draw_pixmap (clist->clist_window, fg_gc,
2293 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2294 xsrc, ysrc, xdest, ydest, pixmap_width, height);
2296 if (GTK_CELL_PIXMAP (clist_row->cell[i])->mask)
2298 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2299 gdk_gc_set_clip_mask (fg_gc, NULL);
2303 case GTK_CELL_PIXTEXT:
2304 /* draw the pixmap */
2307 xdest = offset + clist_row->cell[i].horizontal;
2308 ydest = (clip_rectangle.y + (clip_rectangle.height / 2))
2309 - height / 2 + clist_row->cell[i].vertical;
2311 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->mask)
2313 gdk_gc_set_clip_mask (fg_gc, GTK_CELL_PIXTEXT
2314 (clist_row->cell[i])->mask);
2315 gdk_gc_set_clip_origin (fg_gc, xdest, ydest);
2318 if (xdest < clip_rectangle.x)
2320 xsrc = clip_rectangle.x - xdest;
2321 pixmap_width -= xsrc;
2322 xdest = clip_rectangle.x;
2325 if (xdest + pixmap_width >
2326 clip_rectangle.x + clip_rectangle.width)
2327 pixmap_width = (clip_rectangle.x + clip_rectangle.width)
2330 if (ydest < clip_rectangle.y)
2332 ysrc = clip_rectangle.y - ydest;
2334 ydest = clip_rectangle.y;
2337 if (ydest + height > clip_rectangle.y + clip_rectangle.height)
2338 height = (clip_rectangle.y + clip_rectangle.height) - ydest;
2340 gdk_draw_pixmap (clist->clist_window, fg_gc,
2341 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2342 xsrc, ysrc, xdest, ydest, pixmap_width, height);
2344 gdk_gc_set_clip_origin (fg_gc, 0, 0);
2346 xdest += pixmap_width + GTK_CELL_PIXTEXT
2347 (clist_row->cell[i])->spacing;
2349 /* draw the string */
2350 gdk_gc_set_clip_rectangle (fg_gc, rect);
2352 gdk_draw_string (clist->clist_window, widget->style->font, fg_gc,
2354 row_rectangle.y + clist->row_center_offset +
2355 clist_row->cell[i].vertical,
2356 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2358 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2362 case GTK_CELL_WIDGET:
2373 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
2377 if (gdk_rectangle_intersect (area, &row_rectangle,
2378 &intersect_rectangle))
2380 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
2381 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2382 row_rectangle.x, row_rectangle.y,
2383 row_rectangle.width - 1,
2384 row_rectangle.height - 1);
2385 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
2389 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2390 row_rectangle.x, row_rectangle.y,
2391 row_rectangle.width - 1, row_rectangle.height - 1);
2396 tree_draw_node (GtkCTree *ctree,
2401 clist = GTK_CLIST (ctree);
2403 if (!GTK_CLIST_FROZEN (clist) && gtk_ctree_is_visible (ctree, node))
2408 work = GTK_CTREE_NODE (clist->row_list);
2409 while (work != node)
2411 work = GTK_CTREE_NODE_NEXT (work);
2414 if (gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
2415 GTK_CLIST_CLASS_FW (clist)->draw_row
2416 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2420 static GtkCTreeNode *
2421 gtk_ctree_last_visible (GtkCTree *ctree,
2429 work = GTK_CTREE_ROW (node)->children;
2431 if (!work || !GTK_CTREE_ROW (node)->expanded)
2434 while (GTK_CTREE_ROW (work)->sibling)
2435 work = GTK_CTREE_ROW (work)->sibling;
2437 return gtk_ctree_last_visible (ctree, work);
2441 gtk_ctree_link (GtkCTree *ctree,
2443 GtkCTreeNode *parent,
2444 GtkCTreeNode *sibling,
2445 gboolean update_focus_row)
2448 GtkCTreeNode *list_end;
2449 gboolean visible = FALSE;
2452 g_return_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent);
2453 g_return_if_fail (node != NULL);
2454 g_return_if_fail (node != sibling);
2455 g_return_if_fail (node != parent);
2457 clist = GTK_CLIST (ctree);
2459 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2461 if (clist->anchor != -1)
2462 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2464 g_list_free (clist->undo_selection);
2465 g_list_free (clist->undo_unselection);
2466 clist->undo_selection = NULL;
2467 clist->undo_unselection = NULL;
2470 for (rows = 1, list_end = node; GTK_CTREE_NODE_NEXT (list_end);
2471 list_end = GTK_CTREE_NODE_NEXT (list_end))
2474 GTK_CTREE_ROW (node)->parent = parent;
2475 GTK_CTREE_ROW (node)->sibling = sibling;
2477 if (!parent || (parent && (gtk_ctree_is_visible (ctree, parent) &&
2478 GTK_CTREE_ROW (parent)->expanded)))
2481 clist->rows += rows;
2490 work = GTK_CTREE_ROW (parent)->children;
2492 work = GTK_CTREE_NODE (clist->row_list);
2493 if (work != sibling)
2495 while (GTK_CTREE_ROW (work)->sibling != sibling)
2496 work = GTK_CTREE_ROW (work)->sibling;
2497 GTK_CTREE_ROW (work)->sibling = node;
2500 if (sibling == GTK_CTREE_NODE (clist->row_list))
2501 GTK_CTREE_NODE (clist->row_list) = node;
2502 if (GTK_CTREE_NODE_PREV (sibling) &&
2503 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2504 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) = node;
2506 GTK_CTREE_NODE_PREV (node) = GTK_CTREE_NODE_PREV (sibling);
2507 GTK_CTREE_NODE_NEXT (list_end) = sibling;
2508 GTK_CTREE_NODE_PREV (sibling) = list_end;
2509 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2510 GTK_CTREE_ROW (parent)->children = node;
2517 work = GTK_CTREE_ROW (parent)->children;
2519 work = GTK_CTREE_NODE (clist->row_list);
2524 while (GTK_CTREE_ROW (work)->sibling)
2525 work = GTK_CTREE_ROW (work)->sibling;
2526 GTK_CTREE_ROW (work)->sibling = node;
2528 /* find last visible child of sibling */
2529 work = gtk_ctree_last_visible (ctree, work);
2531 GTK_CTREE_NODE_NEXT (list_end) = GTK_CTREE_NODE_NEXT (work);
2532 if (GTK_CTREE_NODE_NEXT (work))
2533 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (work)) = list_end;
2534 GTK_CTREE_NODE_NEXT (work) = node;
2535 GTK_CTREE_NODE_PREV (node) = work;
2541 GTK_CTREE_ROW (parent)->children = node;
2542 GTK_CTREE_NODE_PREV (node) = parent;
2543 if (GTK_CTREE_ROW (parent)->expanded)
2545 GTK_CTREE_NODE_NEXT (list_end)= GTK_CTREE_NODE_NEXT (parent);
2546 if (GTK_CTREE_NODE_NEXT(parent))
2547 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (parent)) =
2549 GTK_CTREE_NODE_NEXT (parent) = node;
2552 GTK_CTREE_NODE_NEXT (list_end) = NULL;
2556 GTK_CTREE_NODE (clist->row_list) = node;
2557 GTK_CTREE_NODE_PREV (node) = NULL;
2558 GTK_CTREE_NODE_NEXT (list_end) = NULL;
2563 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2565 if (clist->row_list_end == NULL ||
2566 GTK_CTREE_NODE (clist->row_list_end->next) == node)
2567 GTK_CTREE_NODE (clist->row_list_end) = list_end;
2569 if (visible && update_focus_row)
2573 pos = g_list_position (clist->row_list, (GList *)node);
2575 if (pos <= clist->focus_row)
2577 clist->focus_row += rows;
2578 clist->undo_anchor = clist->focus_row;
2584 gtk_ctree_unlink (GtkCTree *ctree,
2586 gboolean update_focus_row)
2593 GtkCTreeNode *parent;
2595 g_return_if_fail (ctree != NULL);
2596 g_return_if_fail (GTK_IS_CTREE (ctree));
2597 g_return_if_fail (node != NULL);
2599 clist = GTK_CLIST (ctree);
2601 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2603 if (clist->anchor != -1)
2604 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2606 g_list_free (clist->undo_selection);
2607 g_list_free (clist->undo_unselection);
2608 clist->undo_selection = NULL;
2609 clist->undo_unselection = NULL;
2612 visible = gtk_ctree_is_visible (ctree, node);
2614 /* clist->row_list_end unlinked ? */
2616 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2617 (GTK_CTREE_ROW (node)->children &&
2618 gtk_ctree_is_ancestor (ctree, node,
2619 GTK_CTREE_NODE (clist->row_list_end)))))
2620 GTK_CTREE_NODE (clist->row_list_end) = GTK_CTREE_NODE_PREV (node);
2624 level = GTK_CTREE_ROW (node)->level;
2625 work = GTK_CTREE_NODE_NEXT (node);
2626 while (work && GTK_CTREE_ROW (work)->level > level)
2628 work = GTK_CTREE_NODE_NEXT (work);
2634 clist->rows -= (rows + 1);
2636 if (update_focus_row)
2640 pos = g_list_position (clist->row_list, (GList *)node);
2641 if (pos + rows + 1 < clist->focus_row)
2642 clist->focus_row -= (rows + 1);
2643 else if (pos <= clist->focus_row)
2644 clist->focus_row = pos - 1;
2645 clist->undo_anchor = clist->focus_row;
2651 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL;
2652 GTK_CTREE_NODE_PREV (work) = GTK_CTREE_NODE_PREV (node);
2655 if (GTK_CTREE_NODE_PREV (node) &&
2656 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2657 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) = work;
2660 parent = GTK_CTREE_ROW (node)->parent;
2663 if (GTK_CTREE_ROW (parent)->children == node)
2665 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2666 if (!GTK_CTREE_ROW (parent)->children &&
2667 GTK_CTREE_ROW (parent)->pixmap_closed)
2669 GTK_CTREE_ROW (parent)->expanded = FALSE;
2671 (GTK_CTREE_ROW(parent)->row.cell[ctree->tree_column])->pixmap =
2672 GTK_CTREE_ROW (parent)->pixmap_closed;
2674 (GTK_CTREE_ROW (parent)->row.cell[ctree->tree_column])->mask =
2675 GTK_CTREE_ROW (parent)->mask_closed;
2680 GtkCTreeNode *sibling;
2682 sibling = GTK_CTREE_ROW (parent)->children;
2683 while (GTK_CTREE_ROW (sibling)->sibling != node)
2684 sibling = GTK_CTREE_ROW (sibling)->sibling;
2685 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2690 if (GTK_CTREE_NODE (clist->row_list) == node)
2691 GTK_CTREE_NODE (clist->row_list) = GTK_CTREE_ROW (node)->sibling;
2694 GtkCTreeNode *sibling;
2696 sibling = GTK_CTREE_NODE (clist->row_list);
2697 while (GTK_CTREE_ROW (sibling)->sibling != node)
2698 sibling = GTK_CTREE_ROW (sibling)->sibling;
2699 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2705 real_tree_move (GtkCTree *ctree,
2707 GtkCTreeNode *new_parent,
2708 GtkCTreeNode *new_sibling)
2712 gboolean thaw = FALSE;
2714 g_return_if_fail (ctree != NULL);
2715 g_return_if_fail (node != NULL);
2716 g_return_if_fail (!new_sibling ||
2717 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2719 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2722 /* new_parent != child of child */
2723 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2727 clist = GTK_CLIST (ctree);
2729 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2731 if (clist->anchor != -1)
2732 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2734 g_list_free (clist->undo_selection);
2735 g_list_free (clist->undo_unselection);
2736 clist->undo_selection = NULL;
2737 clist->undo_unselection = NULL;
2740 if (GTK_CLIST_AUTO_SORT (clist))
2742 if (new_parent == GTK_CTREE_ROW (node)->parent)
2746 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2748 new_sibling = GTK_CTREE_NODE (clist->row_list);
2750 while (new_sibling && clist->compare (clist, node, new_sibling) > 0)
2751 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2754 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2755 new_sibling == GTK_CTREE_ROW (node)->sibling)
2758 if (!GTK_CLIST_FROZEN (clist))
2760 gtk_clist_freeze (clist);
2765 if (gtk_ctree_is_visible (ctree, node) ||
2766 gtk_ctree_is_visible (ctree, new_sibling))
2767 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2769 gtk_ctree_unlink (ctree, node, FALSE);
2770 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2774 while (work && !gtk_ctree_is_visible (ctree, work))
2775 work = GTK_CTREE_ROW (work)->parent;
2776 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2777 clist->undo_anchor = clist->focus_row;
2781 gtk_clist_thaw (clist);
2785 change_focus_row_expansion (GtkCTree *ctree,
2786 GtkCTreeExpansionType action)
2791 g_return_if_fail (ctree != NULL);
2792 g_return_if_fail (GTK_IS_CTREE (ctree));
2794 clist = GTK_CLIST (ctree);
2796 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2800 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2801 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2806 case GTK_CTREE_EXPANSION_EXPAND:
2807 gtk_ctree_expand (ctree, node);
2809 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2810 gtk_ctree_expand_recursive (ctree, node);
2812 case GTK_CTREE_EXPANSION_COLLAPSE:
2813 gtk_ctree_collapse (ctree, node);
2815 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2816 gtk_ctree_collapse_recursive (ctree, node);
2818 case GTK_CTREE_EXPANSION_TOGGLE:
2819 gtk_ctree_toggle_expansion (ctree, node);
2821 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2822 gtk_ctree_toggle_expansion_recursive (ctree, node);
2828 real_tree_expand (GtkCTree *ctree,
2835 g_return_if_fail (ctree != NULL);
2836 g_return_if_fail (GTK_IS_CTREE (ctree));
2838 if (!node || GTK_CTREE_ROW (node)->expanded)
2841 clist = GTK_CLIST (ctree);
2843 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2844 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2846 GTK_CTREE_ROW (node)->expanded = TRUE;
2847 level = GTK_CTREE_ROW (node)->level;
2849 if (GTK_CTREE_ROW (node)->pixmap_opened)
2852 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2853 GTK_CTREE_ROW (node)->pixmap_opened;
2855 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2856 GTK_CTREE_ROW (node)->mask_opened;
2859 work = GTK_CTREE_ROW (node)->children;
2866 clist = GTK_CLIST (ctree);
2868 while (GTK_CTREE_NODE_NEXT (work))
2870 work = GTK_CTREE_NODE_NEXT (work);
2874 GTK_CTREE_NODE_NEXT (work) = GTK_CTREE_NODE_NEXT (node);
2876 if (GTK_CTREE_NODE_NEXT (node))
2877 GTK_CTREE_NODE_PREV (GTK_CTREE_NODE_NEXT (node)) = work;
2879 GTK_CTREE_NODE (clist->row_list_end) = work;
2881 GTK_CTREE_NODE_NEXT (node) = GTK_CTREE_ROW (node)->children;
2883 if (gtk_ctree_is_visible (ctree, node))
2885 row = g_list_position (clist->row_list, (GList *)node);
2886 if (row < clist->focus_row)
2887 clist->focus_row += tmp + 1;
2888 clist->rows += tmp + 1;
2889 if (!GTK_CLIST_FROZEN (ctree))
2890 gtk_clist_thaw (clist);
2896 real_tree_collapse (GtkCTree *ctree,
2903 g_return_if_fail (ctree != NULL);
2904 g_return_if_fail (GTK_IS_CTREE (ctree));
2906 if (!node || !GTK_CTREE_ROW (node)->expanded)
2909 clist = GTK_CLIST (ctree);
2911 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2912 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2914 GTK_CTREE_ROW (node)->expanded = FALSE;
2915 level = GTK_CTREE_ROW (node)->level;
2917 if (GTK_CTREE_ROW (node)->pixmap_closed)
2920 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2921 GTK_CTREE_ROW (node)->pixmap_closed;
2923 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2924 GTK_CTREE_ROW (node)->mask_closed;
2927 work = GTK_CTREE_ROW (node)->children;
2934 clist = GTK_CLIST (ctree);
2936 while (work && GTK_CTREE_ROW (work)->level > level)
2938 work = GTK_CTREE_NODE_NEXT (work);
2944 GTK_CTREE_NODE_NEXT (node) = work;
2945 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (work)) = NULL;
2946 GTK_CTREE_NODE_PREV (work) = node;
2950 GTK_CTREE_NODE_NEXT (node) = NULL;
2951 GTK_CTREE_NODE (clist->row_list_end) = node;
2954 if (gtk_ctree_is_visible (ctree, node))
2956 row = g_list_position (clist->row_list, (GList *)node);
2957 if (row < clist->focus_row)
2958 clist->focus_row -= tmp;
2960 if (!GTK_CLIST_FROZEN (ctree))
2961 gtk_clist_thaw (clist);
2967 cell_set_text (GtkCList *clist,
2968 GtkCListRow *clist_row,
2972 cell_empty (clist, clist_row, column);
2976 clist_row->cell[column].type = GTK_CELL_TEXT;
2977 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2982 cell_set_pixmap (GtkCList *clist,
2983 GtkCListRow *clist_row,
2988 cell_empty (clist, clist_row, column);
2992 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2993 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2994 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2999 cell_set_pixtext (GtkCList *clist,
3000 GtkCListRow *clist_row,
3007 cell_empty (clist, clist_row, column);
3011 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3012 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3013 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3014 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3015 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3020 set_node_info (GtkCTree *ctree,
3024 GdkPixmap *pixmap_closed,
3025 GdkBitmap *mask_closed,
3026 GdkPixmap *pixmap_opened,
3027 GdkBitmap *mask_opened,
3031 GtkCellPixText *tree_cell;
3033 if (GTK_CTREE_ROW (node)->pixmap_opened)
3035 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3036 if (GTK_CTREE_ROW (node)->mask_opened)
3037 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3039 if (GTK_CTREE_ROW (node)->pixmap_closed)
3041 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3042 if (GTK_CTREE_ROW (node)->mask_closed)
3043 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3046 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3047 GTK_CTREE_ROW (node)->mask_opened = NULL;
3048 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3049 GTK_CTREE_ROW (node)->mask_closed = NULL;
3053 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3055 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3059 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3061 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3064 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3065 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3067 GTK_CTREE_ROW (node)->row.cell[ctree->tree_column].type = GTK_CELL_PIXTEXT;
3069 tree_cell = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
3070 (node)->row.cell[ctree->tree_column]);
3072 if (tree_cell->text)
3073 g_free (tree_cell->text);
3075 tree_cell->text = g_strdup (text);
3076 tree_cell->spacing = spacing;
3078 if (GTK_CTREE_ROW (node)->expanded)
3080 tree_cell->pixmap = pixmap_opened;
3081 tree_cell->mask = mask_opened;
3085 tree_cell->pixmap = pixmap_closed;
3086 tree_cell->mask = mask_closed;
3091 tree_delete (GtkCTree *ctree,
3097 clist = GTK_CLIST (ctree);
3099 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3103 work = g_list_find (clist->selection, node);
3106 if (clist->selection_end && clist->selection_end == work)
3107 clist->selection_end = clist->selection_end->prev;
3108 clist->selection = g_list_remove (clist->selection, node);
3112 row_delete (ctree, GTK_CTREE_ROW (node));
3113 g_list_free_1 ((GList *)node);
3117 tree_delete_row (GtkCTree *ctree,
3121 row_delete (ctree, GTK_CTREE_ROW (node));
3122 g_list_free_1 ((GList *)node);
3126 tree_update_level (GtkCTree *ctree,
3133 if (GTK_CTREE_ROW (node)->parent)
3134 GTK_CTREE_ROW (node)->level =
3135 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3137 GTK_CTREE_ROW (node)->level = 1;
3141 tree_select (GtkCTree *ctree,
3145 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3146 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3151 tree_unselect (GtkCTree *ctree,
3155 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3156 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3161 tree_expand (GtkCTree *ctree,
3165 if (node && !GTK_CTREE_ROW (node)->expanded)
3166 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3170 tree_collapse (GtkCTree *ctree,
3174 if (node && GTK_CTREE_ROW (node)->expanded)
3175 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3179 tree_collapse_to_depth (GtkCTree *ctree,
3183 if (node && GTK_CTREE_ROW (node)->level == depth)
3184 gtk_ctree_collapse_recursive (ctree, node);
3188 tree_toggle_expansion (GtkCTree *ctree,
3195 if (GTK_CTREE_ROW (node)->expanded)
3196 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3198 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3201 static GtkCTreeRow *
3202 row_new (GtkCTree *ctree)
3205 GtkCTreeRow *ctree_row;
3208 clist = GTK_CLIST (ctree);
3209 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3210 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3212 for (i = 0; i < clist->columns; i++)
3214 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3215 ctree_row->row.cell[i].vertical = 0;
3216 ctree_row->row.cell[i].horizontal = 0;
3219 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3221 ctree_row->row.fg_set = FALSE;
3222 ctree_row->row.bg_set = FALSE;
3223 ctree_row->row.state = GTK_STATE_NORMAL;
3224 ctree_row->row.data = NULL;
3225 ctree_row->row.destroy = NULL;
3227 ctree_row->level = 0;
3228 ctree_row->expanded = FALSE;
3229 ctree_row->parent = NULL;
3230 ctree_row->sibling = NULL;
3231 ctree_row->children = NULL;
3232 ctree_row->pixmap_closed = NULL;
3233 ctree_row->mask_closed = NULL;
3234 ctree_row->pixmap_opened = NULL;
3235 ctree_row->mask_opened = NULL;
3241 row_delete (GtkCTree *ctree,
3242 GtkCTreeRow *ctree_row)
3247 clist = GTK_CLIST (ctree);
3249 for (i = 0; i < clist->columns; i++)
3250 cell_empty (clist, &(ctree_row->row), i);
3252 if (ctree_row->pixmap_closed)
3254 gdk_pixmap_unref (ctree_row->pixmap_closed);
3255 if (ctree_row->mask_closed)
3256 gdk_bitmap_unref (ctree_row->mask_closed);
3259 if (ctree_row->pixmap_opened)
3261 gdk_pixmap_unref (ctree_row->pixmap_opened);
3262 if (ctree_row->mask_opened)
3263 gdk_bitmap_unref (ctree_row->mask_opened);
3266 if (ctree_row->row.destroy)
3267 ctree_row->row.destroy (ctree_row->row.data);
3269 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3270 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3274 cell_empty (GtkCList *clist,
3275 GtkCListRow *clist_row,
3278 switch (clist_row->cell[column].type)
3280 case GTK_CELL_EMPTY:
3284 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3287 case GTK_CELL_PIXMAP:
3288 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3289 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3290 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3293 case GTK_CELL_PIXTEXT:
3294 if (GTK_CTREE (clist)->tree_column == column)
3296 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
3297 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3300 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3301 gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3302 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3303 gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3306 case GTK_CELL_WIDGET:
3314 clist_row->cell[column].type = GTK_CELL_EMPTY;
3318 real_select_row (GtkCList *clist,
3325 g_return_if_fail (clist != NULL);
3326 g_return_if_fail (GTK_IS_CTREE (clist));
3328 if ((node = g_list_nth (clist->row_list, row)))
3329 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3334 real_unselect_row (GtkCList *clist,
3341 g_return_if_fail (clist != NULL);
3342 g_return_if_fail (GTK_IS_CTREE (clist));
3344 if ((node = g_list_nth (clist->row_list, row)))
3345 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3350 real_tree_select (GtkCTree *ctree,
3356 GtkCTreeNode *sel_row;
3357 gboolean node_selected;
3359 g_return_if_fail (ctree != NULL);
3360 g_return_if_fail (GTK_IS_CTREE (ctree));
3362 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3365 clist = GTK_CLIST (ctree);
3367 switch (clist->selection_mode)
3369 case GTK_SELECTION_SINGLE:
3370 case GTK_SELECTION_BROWSE:
3372 node_selected = FALSE;
3373 list = clist->selection;
3377 sel_row = list->data;
3380 if (node == sel_row)
3381 node_selected = TRUE;
3383 gtk_signal_emit (GTK_OBJECT (ctree),
3384 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3394 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3396 if (!clist->selection)
3398 clist->selection = g_list_append (clist->selection, node);
3399 clist->selection_end = clist->selection;
3402 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3404 tree_draw_node (ctree, node);
3408 real_tree_unselect (GtkCTree *ctree,
3414 g_return_if_fail (ctree != NULL);
3415 g_return_if_fail (GTK_IS_CTREE (ctree));
3417 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3420 clist = GTK_CLIST (ctree);
3422 if (clist->selection_end && clist->selection_end->data == node)
3423 clist->selection_end = clist->selection_end->prev;
3425 clist->selection = g_list_remove (clist->selection, node);
3427 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3429 tree_draw_node (ctree, node);
3433 tree_toggle_selection (GtkCTree *ctree,
3439 g_return_if_fail (ctree != NULL);
3440 g_return_if_fail (GTK_IS_CTREE (ctree));
3442 clist = GTK_CLIST (ctree);
3444 switch (clist->selection_mode)
3446 case GTK_SELECTION_SINGLE:
3447 case GTK_SELECTION_MULTIPLE:
3448 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3449 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3452 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3456 case GTK_SELECTION_BROWSE:
3457 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
3458 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3462 case GTK_SELECTION_EXTENDED:
3468 select_row_recursive (GtkCTree *ctree,
3472 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3475 GTK_CLIST (ctree)->undo_unselection =
3476 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3477 gtk_ctree_select (ctree, node);
3481 real_select_all (GtkCList *clist)
3485 gboolean thaw = FALSE;
3487 g_return_if_fail (clist != NULL);
3488 g_return_if_fail (GTK_IS_CTREE (clist));
3490 ctree = GTK_CTREE (clist);
3492 switch (clist->selection_mode)
3494 case GTK_SELECTION_SINGLE:
3495 case GTK_SELECTION_BROWSE:
3498 case GTK_SELECTION_EXTENDED:
3500 if (!GTK_CLIST_FROZEN (clist))
3502 gtk_clist_freeze (clist);
3506 g_list_free (clist->undo_selection);
3507 g_list_free (clist->undo_unselection);
3508 clist->undo_selection = NULL;
3509 clist->undo_unselection = NULL;
3511 clist->anchor_state = GTK_STATE_SELECTED;
3513 clist->drag_pos = -1;
3514 clist->undo_anchor = clist->focus_row;
3516 for (node = GTK_CTREE_NODE (clist->row_list); node;
3517 node = GTK_CTREE_NODE_NEXT (node))
3518 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3521 gtk_clist_thaw (clist);
3524 case GTK_SELECTION_MULTIPLE:
3525 gtk_ctree_select_recursive (ctree, NULL);
3531 real_unselect_all (GtkCList *clist)
3537 g_return_if_fail (clist != NULL);
3538 g_return_if_fail (GTK_IS_CTREE (clist));
3540 ctree = GTK_CTREE (clist);
3542 switch (clist->selection_mode)
3544 case GTK_SELECTION_BROWSE:
3545 if (clist->focus_row >= 0)
3549 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3554 case GTK_SELECTION_EXTENDED:
3555 g_list_free (clist->undo_selection);
3556 g_list_free (clist->undo_unselection);
3557 clist->undo_selection = NULL;
3558 clist->undo_unselection = NULL;
3561 clist->drag_pos = -1;
3562 clist->undo_anchor = clist->focus_row;
3569 list = clist->selection;
3575 gtk_ctree_unselect (ctree, node);
3580 ctree_is_hot_spot (GtkCTree *ctree,
3586 GtkCTreeRow *tree_row;
3588 GtkCellPixText *cell;
3592 g_return_val_if_fail (ctree != NULL, FALSE);
3593 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3594 g_return_val_if_fail (node != NULL, FALSE);
3596 tree_row = GTK_CTREE_ROW (node);
3597 clist = GTK_CLIST (ctree);
3599 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3601 yu = ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2;
3603 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3605 xl = clist->column[ctree->tree_column].area.x
3606 + clist->column[ctree->tree_column].area.width + clist->hoffset
3607 /*+ cell->horizontal +*/
3608 - (tree_row->level - 1) * ctree->tree_indent
3610 (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 1);
3614 xl = clist->column[ctree->tree_column].area.x + clist->hoffset
3615 + cell->horizontal + (tree_row->level - 1) * ctree->tree_indent +
3616 (ctree->line_style == GTK_CTREE_LINES_TABBED) * ((PM_SIZE / 2) + 2);
3619 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3623 default_compare (GtkCList *clist,
3627 GtkCTreeNode *node1 = (GtkCTreeNode *) ptr1;
3628 GtkCTreeNode *node2 = (GtkCTreeNode *) ptr2;
3632 text1 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
3633 (node1)->row.cell[clist->sort_column])->text;
3634 text2 = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
3635 (node2)->row.cell[clist->sort_column])->text;
3637 return strcmp (text1, text2);
3640 /***********************************************************
3641 ***********************************************************
3642 *** Public interface ***
3643 ***********************************************************
3644 ***********************************************************/
3647 /***********************************************************
3648 * Creation, insertion, deletion *
3649 ***********************************************************/
3652 gtk_ctree_construct (GtkCTree *ctree,
3659 g_return_if_fail (ctree != NULL);
3660 g_return_if_fail (GTK_IS_CTREE (ctree));
3661 g_return_if_fail (GTK_CLIST_CONSTRUCTED (ctree) == FALSE);
3663 clist = GTK_CLIST (ctree);
3665 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
3666 sizeof (GtkCTreeRow),
3667 sizeof (GtkCTreeRow)
3668 * CLIST_OPTIMUM_SIZE,
3671 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
3672 sizeof (GtkCell) * columns,
3673 sizeof (GtkCell) * columns
3674 * CLIST_OPTIMUM_SIZE,
3677 ctree->tree_column = tree_column;
3679 gtk_clist_construct (clist, columns, titles);
3683 gtk_ctree_new_with_titles (gint columns,
3689 g_return_val_if_fail (columns > 0, NULL);
3690 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3692 widget = gtk_type_new (GTK_TYPE_CTREE);
3693 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
3698 gtk_ctree_new (gint columns,
3701 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3705 gtk_ctree_insert (GtkCTree *ctree,
3706 GtkCTreeNode *parent,
3707 GtkCTreeNode *sibling,
3710 GdkPixmap *pixmap_closed,
3711 GdkBitmap *mask_closed,
3712 GdkPixmap *pixmap_opened,
3713 GdkBitmap *mask_opened,
3718 GtkCTreeRow *new_row;
3722 g_return_val_if_fail (ctree != NULL, NULL);
3723 g_return_val_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent,
3726 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
3729 clist = GTK_CLIST (ctree);
3731 /* create the row */
3732 new_row = row_new (ctree);
3733 node = GTK_CTREE_NODE (g_list_alloc ());
3734 GTK_CTREE_ROW (node) = new_row;
3737 for (i = 0; i < clist->columns; i++)
3738 if (text[i] && i != ctree->tree_column)
3739 cell_set_text (clist, &(new_row->row), i, text[i]);
3741 set_node_info (ctree, node, text[ctree->tree_column], spacing, pixmap_closed,
3742 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
3744 /* sorted insertion */
3745 if (GTK_CLIST_AUTO_SORT (clist))
3748 sibling = GTK_CTREE_ROW (parent)->children;
3750 sibling = GTK_CTREE_NODE (clist->row_list);
3752 while (sibling && clist->compare (clist, node, sibling) > 0)
3753 sibling = GTK_CTREE_ROW (sibling)->sibling;
3756 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
3758 if (!GTK_CLIST_FROZEN (clist))
3759 gtk_clist_thaw (clist);
3765 gtk_ctree_insert_gnode (GtkCTree *ctree,
3766 GtkCTreeNode *parent,
3767 GtkCTreeNode *sibling,
3769 GtkCTreeGNodeFunc func,
3773 GtkCTreeNode *cnode = NULL;
3774 GtkCTreeNode *child = NULL;
3775 GtkCTreeNode *new_child;
3776 GtkCTreeRow *new_row;
3781 g_return_val_if_fail (ctree != NULL, NULL);
3782 g_return_val_if_fail (gnode != NULL, NULL);
3783 g_return_val_if_fail (func != NULL, NULL);
3785 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3787 clist = GTK_CLIST (ctree);
3790 depth = GTK_CTREE_ROW (parent)->level + 1;
3792 if (!(new_row = row_new (ctree)))
3794 if (!(cnode = GTK_CTREE_NODE (g_list_alloc ())))
3796 GTK_CTREE_ROW (cnode) = new_row;
3798 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
3800 if (!func (ctree, depth, gnode, cnode, data))
3802 tree_delete_row (ctree, cnode, NULL);
3806 if ((thaw = !GTK_CLIST_FROZEN (clist)))
3807 gtk_clist_freeze (clist);
3809 if (GTK_CLIST_AUTO_SORT (clist))
3812 sibling = GTK_CTREE_ROW (parent)->children;
3814 sibling = GTK_CTREE_NODE (clist->row_list);
3816 while (sibling && clist->compare (clist, cnode, sibling) > 0)
3817 sibling = GTK_CTREE_ROW (sibling)->sibling;
3820 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
3822 for (work = g_node_last_child (gnode); work; work = work->prev)
3824 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
3831 gtk_clist_thaw (clist);
3837 gtk_ctree_remove (GtkCTree *ctree,
3841 gboolean thaw = FALSE;
3843 g_return_if_fail (ctree != NULL);
3844 g_return_if_fail (GTK_IS_CTREE (ctree));
3846 clist = GTK_CLIST (ctree);
3848 if (!GTK_CLIST_FROZEN (clist))
3850 gtk_clist_freeze (clist);
3856 gtk_ctree_unlink (ctree, node, TRUE);
3857 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
3861 gtk_clist_clear (clist);
3864 gtk_clist_thaw (clist);
3868 real_clear (GtkCList *clist)
3874 g_return_if_fail (clist != NULL);
3875 g_return_if_fail (GTK_IS_CTREE (clist));
3877 ctree = GTK_CTREE (clist);
3879 ctree->drag_row = -1;
3880 ctree->drag_rect = FALSE;
3881 ctree->in_drag = FALSE;
3882 ctree->drag_source = NULL;
3883 ctree->drag_target = NULL;
3884 ctree->drag_icon = NULL;
3886 /* remove all the rows */
3887 work = GTK_CTREE_NODE (clist->row_list);
3888 clist->row_list = NULL;
3889 clist->row_list_end = NULL;
3894 work = GTK_CTREE_ROW (work)->sibling;
3895 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
3899 (parent_class->clear) (clist);
3903 /***********************************************************
3904 * Generic recursive functions, querying / finding tree *
3906 ***********************************************************/
3910 gtk_ctree_post_recursive (GtkCTree *ctree,
3918 g_return_if_fail (ctree != NULL);
3919 g_return_if_fail (GTK_IS_CTREE (ctree));
3920 g_return_if_fail (func != NULL);
3923 work = GTK_CTREE_ROW (node)->children;
3925 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3929 tmp = GTK_CTREE_ROW (work)->sibling;
3930 gtk_ctree_post_recursive (ctree, work, func, data);
3935 func (ctree, node, data);
3939 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
3948 g_return_if_fail (ctree != NULL);
3949 g_return_if_fail (GTK_IS_CTREE (ctree));
3950 g_return_if_fail (func != NULL);
3954 gtk_ctree_post_recursive (ctree, node, func, data);
3959 work = GTK_CTREE_ROW (node)->children;
3961 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3963 if (work && GTK_CTREE_ROW (work)->level <= depth)
3967 tmp = GTK_CTREE_ROW (work)->sibling;
3968 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
3973 if (node && GTK_CTREE_ROW (node)->level <= depth)
3974 func (ctree, node, data);
3978 gtk_ctree_pre_recursive (GtkCTree *ctree,
3986 g_return_if_fail (ctree != NULL);
3987 g_return_if_fail (GTK_IS_CTREE (ctree));
3988 g_return_if_fail (func != NULL);
3992 work = GTK_CTREE_ROW (node)->children;
3993 func (ctree, node, data);
3996 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4000 tmp = GTK_CTREE_ROW (work)->sibling;
4001 gtk_ctree_pre_recursive (ctree, work, func, data);
4007 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4016 g_return_if_fail (ctree != NULL);
4017 g_return_if_fail (GTK_IS_CTREE (ctree));
4018 g_return_if_fail (func != NULL);
4022 gtk_ctree_pre_recursive (ctree, node, func, data);
4028 work = GTK_CTREE_ROW (node)->children;
4029 if (GTK_CTREE_ROW (node)->level <= depth)
4030 func (ctree, node, data);
4033 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4035 if (work && GTK_CTREE_ROW (work)->level <= depth)
4039 tmp = GTK_CTREE_ROW (work)->sibling;
4040 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4047 gtk_ctree_is_visible (GtkCTree *ctree,
4052 g_return_val_if_fail (ctree != NULL, FALSE);
4053 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4054 g_return_val_if_fail (node != NULL, FALSE);
4056 work = GTK_CTREE_ROW (node);
4058 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4059 work = GTK_CTREE_ROW (work->parent);
4068 gtk_ctree_last (GtkCTree *ctree,
4071 g_return_val_if_fail (ctree != NULL, NULL);
4072 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4077 while (GTK_CTREE_ROW (node)->sibling)
4078 node = GTK_CTREE_ROW (node)->sibling;
4080 if (GTK_CTREE_ROW (node)->children)
4081 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4087 gtk_ctree_find_glist_ptr (GtkCTree *ctree,
4088 GtkCTreeRow *ctree_row)
4092 g_return_val_if_fail (ctree != NULL, FALSE);
4093 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4094 g_return_val_if_fail (ctree_row != NULL, FALSE);
4096 if (ctree_row->parent)
4097 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4099 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4101 while (GTK_CTREE_ROW (node) != ctree_row)
4102 node = GTK_CTREE_ROW (node)->sibling;
4108 gtk_ctree_find (GtkCTree *ctree,
4110 GtkCTreeNode *child)
4116 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4122 if (GTK_CTREE_ROW (node)->children)
4124 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4127 node = GTK_CTREE_ROW (node)->sibling;
4133 gtk_ctree_is_ancestor (GtkCTree *ctree,
4135 GtkCTreeNode *child)
4137 g_return_val_if_fail (node != NULL, FALSE);
4139 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4143 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4150 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4154 if (GTK_CTREE_ROW (node)->row.data == data)
4156 if (GTK_CTREE_ROW (node)->children &&
4157 (work = gtk_ctree_find_by_row_data
4158 (ctree, GTK_CTREE_ROW (node)->children, data)))
4160 node = GTK_CTREE_ROW (node)->sibling;
4166 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4173 g_return_val_if_fail (func != NULL, NULL);
4176 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4180 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4182 if (GTK_CTREE_ROW (node)->children &&
4183 (work = gtk_ctree_find_by_row_data_custom
4184 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4186 node = GTK_CTREE_ROW (node)->sibling;
4192 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4200 g_return_val_if_fail (ctree != NULL, FALSE);
4201 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4203 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4204 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4205 return ctree_is_hot_spot (ctree, node, row, x, y);
4211 /***********************************************************
4212 * Tree signals : move, expand, collapse, (un)select *
4213 ***********************************************************/
4217 gtk_ctree_move (GtkCTree *ctree,
4219 GtkCTreeNode *new_parent,
4220 GtkCTreeNode *new_sibling)
4222 g_return_if_fail (ctree != NULL);
4223 g_return_if_fail (GTK_IS_CTREE (ctree));
4224 g_return_if_fail (node != NULL);
4226 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4227 new_parent, new_sibling);
4231 gtk_ctree_expand (GtkCTree *ctree,
4234 g_return_if_fail (ctree != NULL);
4235 g_return_if_fail (GTK_IS_CTREE (ctree));
4236 g_return_if_fail (node != NULL);
4238 if (GTK_CTREE_ROW (node)->is_leaf)
4241 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4245 gtk_ctree_expand_recursive (GtkCTree *ctree,
4249 gboolean thaw = FALSE;
4251 g_return_if_fail (ctree != NULL);
4252 g_return_if_fail (GTK_IS_CTREE (ctree));
4254 clist = GTK_CLIST (ctree);
4256 if (node && GTK_CTREE_ROW (node)->is_leaf)
4259 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4260 !GTK_CLIST_FROZEN (clist))
4262 gtk_clist_freeze (clist);
4266 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4269 gtk_clist_thaw (clist);
4273 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4278 gboolean thaw = FALSE;
4280 g_return_if_fail (ctree != NULL);
4281 g_return_if_fail (GTK_IS_CTREE (ctree));
4283 clist = GTK_CLIST (ctree);
4285 if (node && GTK_CTREE_ROW (node)->is_leaf)
4288 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4289 !GTK_CLIST_FROZEN (clist))
4291 gtk_clist_freeze (clist);
4295 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4296 GTK_CTREE_FUNC (tree_expand), NULL);
4299 gtk_clist_thaw (clist);
4303 gtk_ctree_collapse (GtkCTree *ctree,
4306 g_return_if_fail (ctree != NULL);
4307 g_return_if_fail (GTK_IS_CTREE (ctree));
4308 g_return_if_fail (node != NULL);
4310 if (GTK_CTREE_ROW (node)->is_leaf)
4313 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4317 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4321 gboolean thaw = FALSE;
4323 g_return_if_fail (ctree != NULL);
4324 g_return_if_fail (GTK_IS_CTREE (ctree));
4326 if (node && GTK_CTREE_ROW (node)->is_leaf)
4329 clist = GTK_CLIST (ctree);
4331 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4332 !GTK_CLIST_FROZEN (clist))
4334 gtk_clist_freeze (clist);
4338 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4341 gtk_clist_thaw (clist);
4345 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4350 gboolean thaw = FALSE;
4352 g_return_if_fail (ctree != NULL);
4353 g_return_if_fail (GTK_IS_CTREE (ctree));
4355 if (node && GTK_CTREE_ROW (node)->is_leaf)
4358 clist = GTK_CLIST (ctree);
4360 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4361 !GTK_CLIST_FROZEN (clist))
4363 gtk_clist_freeze (clist);
4367 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4368 GTK_CTREE_FUNC (tree_collapse_to_depth),
4369 GINT_TO_POINTER (depth));
4372 gtk_clist_thaw (clist);
4376 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4379 g_return_if_fail (ctree != NULL);
4380 g_return_if_fail (GTK_IS_CTREE (ctree));
4381 g_return_if_fail (node != NULL);
4383 if (GTK_CTREE_ROW (node)->is_leaf)
4386 tree_toggle_expansion (ctree, node, NULL);
4390 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4394 gboolean thaw = FALSE;
4396 g_return_if_fail (ctree != NULL);
4397 g_return_if_fail (GTK_IS_CTREE (ctree));
4399 if (node && GTK_CTREE_ROW (node)->is_leaf)
4402 clist = GTK_CLIST (ctree);
4404 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4405 !GTK_CLIST_FROZEN (clist))
4407 gtk_clist_freeze (clist);
4411 gtk_ctree_post_recursive (ctree, node,
4412 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4415 gtk_clist_thaw (clist);
4419 gtk_ctree_select (GtkCTree *ctree,
4422 g_return_if_fail (ctree != NULL);
4423 g_return_if_fail (GTK_IS_CTREE (ctree));
4424 g_return_if_fail (node != NULL);
4426 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4431 gtk_ctree_unselect (GtkCTree *ctree,
4434 g_return_if_fail (ctree != NULL);
4435 g_return_if_fail (GTK_IS_CTREE (ctree));
4436 g_return_if_fail (node != NULL);
4438 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4443 gtk_ctree_select_recursive (GtkCTree *ctree,
4446 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4450 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4453 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4457 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4462 gboolean thaw = FALSE;
4464 g_return_if_fail (ctree != NULL);
4465 g_return_if_fail (GTK_IS_CTREE (ctree));
4467 clist = GTK_CLIST (ctree);
4470 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4471 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4472 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4475 if (((node && gtk_ctree_is_visible (ctree, node)) || !node) &&
4476 !GTK_CLIST_FROZEN (clist))
4478 gtk_clist_freeze (clist);
4482 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4484 if (clist->anchor != -1)
4485 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4487 g_list_free (clist->undo_selection);
4488 g_list_free (clist->undo_unselection);
4489 clist->undo_selection = NULL;
4490 clist->undo_unselection = NULL;
4494 gtk_ctree_post_recursive (ctree, node,
4495 GTK_CTREE_FUNC (tree_select), NULL);
4497 gtk_ctree_post_recursive (ctree, node,
4498 GTK_CTREE_FUNC (tree_unselect), NULL);
4501 gtk_clist_thaw (clist);
4505 /***********************************************************
4506 * Analogons of GtkCList functions *
4507 ***********************************************************/
4511 gtk_ctree_set_text (GtkCTree *ctree,
4516 g_return_if_fail (ctree != NULL);
4517 g_return_if_fail (GTK_IS_CTREE (ctree));
4518 g_return_if_fail (node != NULL);
4519 g_return_if_fail (ctree->tree_column != column);
4521 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4524 cell_set_text (GTK_CLIST (ctree), &(GTK_CTREE_ROW(node)->row), column, text);
4525 tree_draw_node (ctree, node);
4529 gtk_ctree_set_pixmap (GtkCTree *ctree,
4535 g_return_if_fail (ctree != NULL);
4536 g_return_if_fail (GTK_IS_CTREE (ctree));
4537 g_return_if_fail (node != NULL);
4538 g_return_if_fail (pixmap != NULL);
4539 g_return_if_fail (ctree->tree_column != column);
4541 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4544 gdk_pixmap_ref (pixmap);
4546 gdk_pixmap_ref (mask);
4548 cell_set_pixmap (GTK_CLIST (ctree), &(GTK_CTREE_ROW (node)->row), column,
4550 tree_draw_node (ctree, node);
4554 gtk_ctree_set_pixtext (GtkCTree *ctree,
4562 g_return_if_fail (ctree != NULL);
4563 g_return_if_fail (GTK_IS_CTREE (ctree));
4564 g_return_if_fail (node != NULL);
4565 g_return_if_fail (pixmap != NULL);
4566 g_return_if_fail (ctree->tree_column != column);
4568 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4571 gdk_pixmap_ref (pixmap);
4573 gdk_pixmap_ref (mask);
4575 cell_set_pixtext (GTK_CLIST (ctree), &(GTK_CTREE_ROW (node)->row), column,
4576 text, spacing, pixmap, mask);
4577 tree_draw_node (ctree, node);
4581 gtk_ctree_set_node_info (GtkCTree *ctree,
4585 GdkPixmap *pixmap_closed,
4586 GdkBitmap *mask_closed,
4587 GdkPixmap *pixmap_opened,
4588 GdkBitmap *mask_opened,
4593 gboolean old_expanded;
4595 g_return_if_fail (ctree != NULL);
4596 g_return_if_fail (GTK_IS_CTREE (ctree));
4597 g_return_if_fail (node != NULL);
4599 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
4600 old_expanded = GTK_CTREE_ROW (node)->expanded;
4602 if (is_leaf && GTK_CTREE_ROW (node)->children)
4607 work = GTK_CTREE_ROW (node)->children;
4611 work = GTK_CTREE_ROW(work)->sibling;
4612 gtk_ctree_remove (ctree, ptr);
4616 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
4617 pixmap_opened, mask_opened, is_leaf, expanded);
4619 if (!is_leaf && !old_leaf)
4621 GTK_CTREE_ROW (node)->expanded = old_expanded;
4622 if (expanded && !old_expanded)
4623 gtk_ctree_expand (ctree, node);
4624 else if (!expanded && old_expanded)
4625 gtk_ctree_collapse (ctree, node);
4628 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
4630 tree_draw_node (ctree, node);
4634 gtk_ctree_set_shift (GtkCTree *ctree,
4640 g_return_if_fail (ctree != NULL);
4641 g_return_if_fail (GTK_IS_CTREE (ctree));
4642 g_return_if_fail (node != NULL);
4644 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4647 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
4648 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
4650 tree_draw_node (ctree, node);
4654 gtk_ctree_get_cell_type (GtkCTree *ctree,
4658 g_return_val_if_fail (ctree != NULL, -1);
4659 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
4660 g_return_val_if_fail (node != NULL, -1);
4662 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4665 return GTK_CTREE_ROW (node)->row.cell[column].type;
4669 gtk_ctree_get_text (GtkCTree *ctree,
4674 g_return_val_if_fail (ctree != NULL, 0);
4675 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4676 g_return_val_if_fail (node != NULL, 0);
4678 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4681 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
4685 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4691 gtk_ctree_get_pixmap (GtkCTree *ctree,
4697 g_return_val_if_fail (ctree != NULL, 0);
4698 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4699 g_return_val_if_fail (node != NULL, 0);
4701 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4704 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
4708 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
4710 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4716 gtk_ctree_get_pixtext (GtkCTree *ctree,
4724 g_return_val_if_fail (ctree != NULL, 0);
4725 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4726 g_return_val_if_fail (node != NULL, 0);
4728 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4731 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
4735 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4737 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4738 (node)->row.cell[column])->spacing;
4740 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4741 (node)->row.cell[column])->pixmap;
4743 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4749 gtk_ctree_get_node_info (GtkCTree *ctree,
4753 GdkPixmap **pixmap_closed,
4754 GdkBitmap **mask_closed,
4755 GdkPixmap **pixmap_opened,
4756 GdkBitmap **mask_opened,
4760 g_return_val_if_fail (ctree != NULL, 0);
4761 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4762 g_return_val_if_fail (node != NULL, 0);
4765 *text = GTK_CELL_PIXTEXT
4766 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
4768 *spacing = GTK_CELL_PIXTEXT
4769 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
4771 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
4773 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
4775 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
4777 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
4779 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
4781 *expanded = GTK_CTREE_ROW (node)->expanded;
4787 gtk_ctree_set_foreground (GtkCTree *ctree,
4791 g_return_if_fail (ctree != NULL);
4792 g_return_if_fail (GTK_IS_CTREE (ctree));
4793 g_return_if_fail (node != NULL);
4797 GTK_CTREE_ROW (node)->row.foreground = *color;
4798 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
4801 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
4803 tree_draw_node (ctree, node);
4807 gtk_ctree_set_background (GtkCTree *ctree,
4811 g_return_if_fail (ctree != NULL);
4812 g_return_if_fail (GTK_IS_CTREE (ctree));
4813 g_return_if_fail (node != NULL);
4817 GTK_CTREE_ROW (node)->row.background = *color;
4818 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
4821 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
4823 tree_draw_node (ctree, node);
4827 gtk_ctree_set_row_data (GtkCTree *ctree,
4831 gtk_ctree_set_row_data_full (ctree, node, data, NULL);
4835 gtk_ctree_set_row_data_full (GtkCTree *ctree,
4838 GtkDestroyNotify destroy)
4840 g_return_if_fail (ctree != NULL);
4841 g_return_if_fail (GTK_IS_CTREE (ctree));
4843 GTK_CTREE_ROW (node)->row.data = data;
4844 GTK_CTREE_ROW (node)->row.destroy = destroy;
4848 gtk_ctree_get_row_data (GtkCTree *ctree,
4851 g_return_val_if_fail (ctree != NULL, NULL);
4852 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4854 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
4858 gtk_ctree_moveto (GtkCTree *ctree,
4867 g_return_if_fail (ctree != NULL);
4868 g_return_if_fail (GTK_IS_CTREE (ctree));
4870 clist = GTK_CLIST (ctree);
4872 while (node && !gtk_ctree_is_visible (ctree, node))
4873 node = GTK_CTREE_ROW (node)->parent;
4876 row = g_list_position (clist->row_list, (GList *)node);
4878 gtk_clist_moveto (clist, row, column, row_align, col_align);
4882 /***********************************************************
4883 * GtkCTree specific functions *
4884 ***********************************************************/
4888 gtk_ctree_set_indent (GtkCTree *ctree,
4891 g_return_if_fail (ctree != NULL);
4892 g_return_if_fail (GTK_IS_CTREE (ctree));
4893 g_return_if_fail (indent >= 0);
4895 if (indent != ctree->tree_indent)
4897 ctree->tree_indent = indent;
4898 if (!GTK_CLIST_FROZEN (ctree))
4899 gtk_clist_thaw (GTK_CLIST (ctree));
4904 gtk_ctree_set_reorderable (GtkCTree *ctree,
4905 gboolean reorderable)
4907 g_return_if_fail (ctree != NULL);
4908 g_return_if_fail (GTK_IS_CTREE (ctree));
4910 if (ctree->reorderable == (reorderable != 0))
4913 ctree->reorderable = (reorderable != 0);
4915 if (GTK_WIDGET_REALIZED (ctree))
4917 if (ctree->reorderable)
4918 create_xor_gc (ctree);
4920 gdk_gc_destroy (ctree->xor_gc);
4925 gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
4928 g_return_if_fail (ctree != NULL);
4929 g_return_if_fail (GTK_IS_CTREE (ctree));
4931 if (ctree->use_icons == (use_icons != 0))
4934 ctree->use_icons = (use_icons != 0);
4938 gtk_ctree_set_line_style (GtkCTree *ctree,
4939 GtkCTreeLineStyle line_style)
4941 g_return_if_fail (ctree != NULL);
4942 g_return_if_fail (GTK_IS_CTREE (ctree));
4944 if (line_style != ctree->line_style)
4946 ctree->line_style = line_style;
4948 if (!GTK_WIDGET_REALIZED (ctree))
4953 case GTK_CTREE_LINES_SOLID:
4954 if (GTK_WIDGET_REALIZED (ctree))
4955 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
4958 case GTK_CTREE_LINES_DOTTED:
4959 if (GTK_WIDGET_REALIZED (ctree))
4960 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
4961 GDK_LINE_ON_OFF_DASH, None, None);
4962 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
4964 case GTK_CTREE_LINES_TABBED:
4965 if (GTK_WIDGET_REALIZED (ctree))
4966 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
4969 case GTK_CTREE_LINES_NONE:
4974 if (!GTK_CLIST_FROZEN (ctree))
4975 gtk_clist_thaw (GTK_CLIST (ctree));
4980 /***********************************************************
4981 * Tree sorting functions *
4982 ***********************************************************/
4986 tree_sort (GtkCTree *ctree,
4990 GtkCTreeNode *list_start;
4995 clist = GTK_CLIST (ctree);
4998 list_start = GTK_CTREE_ROW (node)->children;
5000 list_start = GTK_CTREE_NODE (clist->row_list);
5005 work = GTK_CTREE_ROW (cmp)->sibling;
5008 if (clist->sort_type == GTK_SORT_ASCENDING)
5010 if (clist->compare (clist, work, cmp) < 0)
5015 if (clist->compare (clist, work, cmp) > 0)
5018 work = GTK_CTREE_ROW (work)->sibling;
5020 if (cmp == list_start)
5021 list_start = GTK_CTREE_ROW (cmp)->sibling;
5024 gtk_ctree_unlink (ctree, cmp, FALSE);
5025 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5031 gtk_ctree_sort_recursive (GtkCTree *ctree,
5035 GtkCTreeNode *focus_node = NULL;
5036 gboolean thaw = FALSE;
5038 g_return_if_fail (ctree != NULL);
5039 g_return_if_fail (GTK_IS_CTREE (ctree));
5041 clist = GTK_CLIST (ctree);
5043 if (!GTK_CLIST_FROZEN (clist))
5045 gtk_clist_freeze (clist);
5049 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5051 if (clist->anchor != -1)
5052 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5054 g_list_free (clist->undo_selection);
5055 g_list_free (clist->undo_unselection);
5056 clist->undo_selection = NULL;
5057 clist->undo_unselection = NULL;
5060 if (!node || (node && gtk_ctree_is_visible (ctree, node)))
5062 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5064 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5067 tree_sort (ctree, NULL, NULL);
5071 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5072 clist->undo_anchor = clist->focus_row;
5076 gtk_clist_thaw (clist);
5080 gtk_ctree_sort (GtkCTree *ctree,
5084 GtkCTreeNode *focus_node = NULL;
5085 gboolean thaw = FALSE;
5087 g_return_if_fail (ctree != NULL);
5088 g_return_if_fail (GTK_IS_CTREE (ctree));
5090 clist = GTK_CLIST (ctree);
5092 if (!GTK_CLIST_FROZEN (clist))
5094 gtk_clist_freeze (clist);
5098 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5100 if (clist->anchor != -1)
5101 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5103 g_list_free (clist->undo_selection);
5104 g_list_free (clist->undo_unselection);
5105 clist->undo_selection = NULL;
5106 clist->undo_unselection = NULL;
5109 if (!node || (node && gtk_ctree_is_visible (ctree, node)))
5110 focus_node = GTK_CTREE_NODE
5111 (g_list_nth (clist->row_list, clist->focus_row));
5113 tree_sort (ctree, node, NULL);
5117 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5118 clist->undo_anchor = clist->focus_row;
5122 gtk_clist_thaw (clist);
5125 /************************************************************************/
5128 fake_unselect_all (GtkCList *clist,
5132 GList *focus_node = NULL;
5134 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5136 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL)
5138 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5140 if (!GTK_CLIST_FROZEN (clist) &&
5141 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5142 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5143 GTK_CLIST_ROW (focus_node));
5147 clist->undo_selection = clist->selection;
5148 clist->selection = NULL;
5149 clist->selection_end = NULL;
5151 for (list = clist->undo_selection; list; list = list->next)
5153 if (list->data == focus_node)
5156 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
5157 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
5162 selection_find (GtkCList *clist,
5164 GList *row_list_element)
5166 return g_list_find (clist->selection, row_list_element);
5170 resync_selection (GtkCList *clist, GdkEvent *event)
5178 gboolean thaw = FALSE;
5181 g_return_if_fail (clist != NULL);
5182 g_return_if_fail (GTK_IS_CTREE (clist));
5184 if (clist->anchor < 0)
5187 ctree = GTK_CTREE (clist);
5189 if (!GTK_CLIST_FROZEN (clist))
5191 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
5195 i = MIN (clist->anchor, clist->drag_pos);
5196 e = MAX (clist->anchor, clist->drag_pos);
5198 if (clist->undo_selection)
5200 list = clist->selection;
5201 clist->selection = clist->undo_selection;
5202 clist->selection_end = g_list_last (clist->selection);
5203 clist->undo_selection = list;
5204 list = clist->selection;
5213 if (gtk_ctree_is_visible (ctree, node))
5215 row = g_list_position (clist->row_list, (GList *)node);
5216 if (row >= i && row <= e)
5221 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5222 gtk_ctree_unselect (ctree, node);
5223 clist->undo_selection = g_list_prepend (clist->undo_selection,
5230 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
5231 i++, node = GTK_CTREE_NODE_NEXT (node))
5232 if (g_list_find (clist->selection, node))
5234 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5236 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5237 gtk_ctree_unselect (ctree, node);
5238 clist->undo_selection = g_list_prepend (clist->undo_selection,
5242 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5244 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5245 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
5249 for (list = clist->undo_unselection; list; list = list->next)
5250 gtk_ctree_select (ctree, list->data);
5253 clist->drag_pos = -1;
5256 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
5260 real_undo_selection (GtkCList *clist)
5265 g_return_if_fail (clist != NULL);
5266 g_return_if_fail (GTK_IS_CTREE (clist));
5268 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
5271 if (!(clist->undo_selection || clist->undo_unselection))
5273 gtk_clist_unselect_all (clist);
5277 ctree = GTK_CTREE (clist);
5279 for (work = clist->undo_selection; work; work = work->next)
5280 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
5282 for (work = clist->undo_unselection; work; work = work->next)
5283 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
5285 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
5287 gtk_widget_draw_focus (GTK_WIDGET (clist));
5288 clist->focus_row = clist->undo_anchor;
5289 gtk_widget_draw_focus (GTK_WIDGET (clist));
5292 clist->focus_row = clist->undo_anchor;
5294 clist->undo_anchor = -1;
5296 g_list_free (clist->undo_selection);
5297 g_list_free (clist->undo_unselection);
5298 clist->undo_selection = NULL;
5299 clist->undo_unselection = NULL;
5301 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5302 clist->clist_window_height)
5303 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5304 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5305 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);