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)
63 static void gtk_ctree_class_init (GtkCTreeClass *klass);
64 static void gtk_ctree_init (GtkCTree *ctree);
65 static void gtk_ctree_set_arg (GtkObject *object,
68 static void gtk_ctree_get_arg (GtkObject *object,
71 static void gtk_ctree_realize (GtkWidget *widget);
72 static void gtk_ctree_unrealize (GtkWidget *widget);
73 static gint gtk_ctree_button_press (GtkWidget *widget,
74 GdkEventButton *event);
75 static gint gtk_ctree_button_release (GtkWidget *widget,
76 GdkEventButton *event);
77 static gint gtk_ctree_button_motion (GtkWidget *widget,
78 GdkEventMotion *event);
79 static void ctree_attach_styles (GtkCTree *ctree,
82 static void ctree_detach_styles (GtkCTree *ctree,
85 static gint draw_cell_pixmap (GdkWindow *window,
86 GdkRectangle *clip_rectangle,
94 static void get_cell_style (GtkCList *clist,
95 GtkCListRow *clist_row,
101 static gint gtk_ctree_draw_expander (GtkCTree *ctree,
102 GtkCTreeRow *ctree_row,
104 GdkRectangle *clip_rectangle,
106 static gint gtk_ctree_draw_lines (GtkCTree *ctree,
107 GtkCTreeRow *ctree_row,
111 GdkRectangle *clip_rectangle,
112 GdkRectangle *cell_rectangle,
116 static void draw_row (GtkCList *clist,
119 GtkCListRow *clist_row);
120 static void draw_xor_line (GtkCTree *ctree);
121 static void draw_xor_rect (GtkCTree *ctree);
122 static void create_drag_icon (GtkCTree *ctree,
124 static void tree_draw_node (GtkCTree *ctree,
126 static void set_cell_contents (GtkCList *clist,
127 GtkCListRow *clist_row,
134 static void set_node_info (GtkCTree *ctree,
138 GdkPixmap *pixmap_closed,
139 GdkBitmap *mask_closed,
140 GdkPixmap *pixmap_opened,
141 GdkBitmap *mask_opened,
144 static GtkCTreeRow *row_new (GtkCTree *ctree);
145 static void row_delete (GtkCTree *ctree,
146 GtkCTreeRow *ctree_row);
147 static void tree_delete (GtkCTree *ctree,
150 static void tree_delete_row (GtkCTree *ctree,
153 static void real_clear (GtkCList *clist);
154 static void tree_update_level (GtkCTree *ctree,
157 static void tree_select (GtkCTree *ctree,
160 static void tree_unselect (GtkCTree *ctree,
163 static void real_select_all (GtkCList *clist);
164 static void real_unselect_all (GtkCList *clist);
165 static void tree_expand (GtkCTree *ctree,
168 static void tree_collapse (GtkCTree *ctree,
171 static void tree_collapse_to_depth (GtkCTree *ctree,
174 static void tree_toggle_expansion (GtkCTree *ctree,
177 static void change_focus_row_expansion (GtkCTree *ctree,
178 GtkCTreeExpansionType expansion);
179 static void real_select_row (GtkCList *clist,
183 static void real_unselect_row (GtkCList *clist,
187 static void real_tree_select (GtkCTree *ctree,
190 static void real_tree_unselect (GtkCTree *ctree,
193 static void tree_toggle_selection (GtkCTree *ctree,
196 static void real_tree_expand (GtkCTree *ctree,
198 static void real_tree_collapse (GtkCTree *ctree,
200 static void real_tree_move (GtkCTree *ctree,
202 GtkCTreeNode *new_parent,
203 GtkCTreeNode *new_sibling);
204 static void gtk_ctree_link (GtkCTree *ctree,
206 GtkCTreeNode *parent,
207 GtkCTreeNode *sibling,
208 gboolean update_focus_row);
209 static void gtk_ctree_unlink (GtkCTree *ctree,
211 gboolean update_focus_row);
212 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
214 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
219 static void tree_sort (GtkCTree *ctree,
222 static void fake_unselect_all (GtkCList *clist,
224 static GList * selection_find (GtkCList *clist,
226 GList *row_list_element);
227 static void resync_selection (GtkCList *clist,
229 static void real_undo_selection (GtkCList *clist);
230 static void select_row_recursive (GtkCTree *ctree,
233 static gint real_insert_row (GtkCList *clist,
236 static void real_remove_row (GtkCList *clist,
238 static void real_sort_list (GtkCList *clist);
239 static void set_mouse_cursor (GtkCTree *ctree,
241 static void check_cursor (GtkCTree *ctree);
242 static void cell_size_request (GtkCList *clist,
243 GtkCListRow *clist_row,
245 GtkRequisition *requisition);
246 static void column_auto_resize (GtkCList *clist,
247 GtkCListRow *clist_row,
250 static void auto_resize_columns (GtkCList *clist);
259 CHANGE_FOCUS_ROW_EXPANSION,
263 typedef void (*GtkCTreeSignal1) (GtkObject *object,
268 typedef void (*GtkCTreeSignal2) (GtkObject *object,
274 typedef void (*GtkCTreeSignal3) (GtkObject *object,
278 typedef void (*GtkCTreeSignal4) (GtkObject *object,
279 GtkCTreeExpansionType arg1,
283 static GtkCListClass *parent_class = NULL;
284 static GtkContainerClass *container_class = NULL;
285 static guint ctree_signals[LAST_SIGNAL] = {0};
289 gtk_ctree_get_type (void)
291 static GtkType ctree_type = 0;
295 GtkTypeInfo ctree_info =
299 sizeof (GtkCTreeClass),
300 (GtkClassInitFunc) gtk_ctree_class_init,
301 (GtkObjectInitFunc) gtk_ctree_init,
302 /* reserved_1 */ NULL,
303 /* reserved_2 */ NULL,
304 (GtkClassInitFunc) NULL,
307 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
314 gtk_ctree_class_init (GtkCTreeClass *klass)
316 GtkObjectClass *object_class;
317 GtkWidgetClass *widget_class;
318 GtkCListClass *clist_class;
320 object_class = (GtkObjectClass *) klass;
321 widget_class = (GtkWidgetClass *) klass;
322 container_class = (GtkContainerClass *) klass;
323 clist_class = (GtkCListClass *) klass;
325 parent_class = gtk_type_class (GTK_TYPE_CLIST);
326 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
328 gtk_object_add_arg_type ("GtkCTree::n_columns",
330 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
332 gtk_object_add_arg_type ("GtkCTree::tree_column",
334 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
336 gtk_object_add_arg_type ("GtkCTree::indent",
340 gtk_object_add_arg_type ("GtkCTree::spacing",
344 gtk_object_add_arg_type ("GtkCTree::show_stub",
348 gtk_object_add_arg_type ("GtkCTree::reorderable",
352 gtk_object_add_arg_type ("GtkCTree::use_drag_icons",
356 gtk_object_add_arg_type ("GtkCTree::line_style",
357 GTK_TYPE_CTREE_LINE_STYLE,
360 gtk_object_add_arg_type ("GtkCTree::expander_style",
361 GTK_TYPE_CTREE_EXPANDER_STYLE,
364 object_class->set_arg = gtk_ctree_set_arg;
365 object_class->get_arg = gtk_ctree_get_arg;
367 ctree_signals[TREE_SELECT_ROW] =
368 gtk_signal_new ("tree_select_row",
371 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
372 gtk_marshal_NONE__POINTER_INT,
373 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
374 ctree_signals[TREE_UNSELECT_ROW] =
375 gtk_signal_new ("tree_unselect_row",
378 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
379 gtk_marshal_NONE__POINTER_INT,
380 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
381 ctree_signals[TREE_EXPAND] =
382 gtk_signal_new ("tree_expand",
385 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
386 gtk_marshal_NONE__POINTER,
387 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
388 ctree_signals[TREE_COLLAPSE] =
389 gtk_signal_new ("tree_collapse",
392 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
393 gtk_marshal_NONE__POINTER,
394 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
395 ctree_signals[TREE_MOVE] =
396 gtk_signal_new ("tree_move",
399 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
400 gtk_marshal_NONE__POINTER_POINTER_POINTER,
401 GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER,
403 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
404 gtk_signal_new ("change_focus_row_expansion",
405 GTK_RUN_LAST | GTK_RUN_ACTION,
407 GTK_SIGNAL_OFFSET (GtkCTreeClass,
408 change_focus_row_expansion),
409 gtk_marshal_NONE__ENUM,
410 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_EXPANSION_TYPE);
411 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
413 widget_class->realize = gtk_ctree_realize;
414 widget_class->unrealize = gtk_ctree_unrealize;
415 widget_class->button_press_event = gtk_ctree_button_press;
416 widget_class->button_release_event = gtk_ctree_button_release;
417 widget_class->motion_notify_event = gtk_ctree_button_motion;
419 clist_class->select_row = real_select_row;
420 clist_class->unselect_row = real_unselect_row;
421 clist_class->undo_selection = real_undo_selection;
422 clist_class->resync_selection = resync_selection;
423 clist_class->selection_find = selection_find;
424 clist_class->click_column = NULL;
425 clist_class->draw_row = draw_row;
426 clist_class->clear = real_clear;
427 clist_class->select_all = real_select_all;
428 clist_class->unselect_all = real_unselect_all;
429 clist_class->fake_unselect_all = fake_unselect_all;
430 clist_class->insert_row = real_insert_row;
431 clist_class->remove_row = real_remove_row;
432 clist_class->sort_list = real_sort_list;
433 clist_class->set_cell_contents = set_cell_contents;
434 clist_class->cell_size_request = cell_size_request;
436 klass->tree_select_row = real_tree_select;
437 klass->tree_unselect_row = real_tree_unselect;
438 klass->tree_expand = real_tree_expand;
439 klass->tree_collapse = real_tree_collapse;
440 klass->tree_move = real_tree_move;
441 klass->change_focus_row_expansion = change_focus_row_expansion;
444 GtkBindingSet *binding_set;
446 binding_set = gtk_binding_set_by_class (klass);
447 gtk_binding_entry_add_signal (binding_set,
449 "change_focus_row_expansion", 1,
450 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
451 gtk_binding_entry_add_signal (binding_set,
453 "change_focus_row_expansion", 1,
454 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
455 gtk_binding_entry_add_signal (binding_set,
456 GDK_KP_Add, GDK_CONTROL_MASK,
457 "change_focus_row_expansion", 1,
459 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
460 gtk_binding_entry_add_signal (binding_set,
462 "change_focus_row_expansion", 1,
463 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
464 gtk_binding_entry_add_signal (binding_set,
466 "change_focus_row_expansion", 1,
467 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
468 gtk_binding_entry_add_signal (binding_set,
469 GDK_KP_Subtract, GDK_CONTROL_MASK,
470 "change_focus_row_expansion", 1,
472 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
473 gtk_binding_entry_add_signal (binding_set,
475 "change_focus_row_expansion", 1,
476 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
477 gtk_binding_entry_add_signal (binding_set,
479 "change_focus_row_expansion", 1,
480 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
481 gtk_binding_entry_add_signal (binding_set,
482 GDK_KP_Multiply, GDK_CONTROL_MASK,
483 "change_focus_row_expansion", 1,
485 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
491 gtk_ctree_set_arg (GtkObject *object,
497 ctree = GTK_CTREE (object);
501 case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
502 if (ctree->tree_column)
503 gtk_ctree_construct (ctree,
504 MAX (1, GTK_VALUE_UINT (*arg)),
505 ctree->tree_column, NULL);
507 GTK_CLIST (ctree)->columns = MAX (1, GTK_VALUE_UINT (*arg));
509 case ARG_TREE_COLUMN: /* construct-only arg, only set when !GTK_CONSTRUCTED */
510 if (GTK_CLIST (ctree)->columns)
511 gtk_ctree_construct (ctree,
512 GTK_CLIST (ctree)->columns,
513 MAX (1, GTK_VALUE_UINT (*arg)),
516 ctree->tree_column = MAX (1, GTK_VALUE_UINT (*arg));
519 gtk_ctree_set_indent (ctree, GTK_VALUE_UINT (*arg));
522 gtk_ctree_set_spacing (ctree, GTK_VALUE_UINT (*arg));
525 gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg));
527 case ARG_REORDERABLE:
528 gtk_ctree_set_reorderable (ctree, GTK_VALUE_BOOL (*arg));
530 case ARG_USE_DRAG_ICONS:
531 gtk_ctree_set_use_drag_icons (ctree, GTK_VALUE_BOOL (*arg));
534 gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg));
536 case ARG_EXPANDER_STYLE:
537 gtk_ctree_set_expander_style (ctree, GTK_VALUE_ENUM (*arg));
545 gtk_ctree_get_arg (GtkObject *object,
551 ctree = GTK_CTREE (object);
556 GTK_VALUE_UINT (*arg) = GTK_CLIST (ctree)->columns;
558 case ARG_TREE_COLUMN:
559 GTK_VALUE_UINT (*arg) = ctree->tree_column;
562 GTK_VALUE_UINT (*arg) = ctree->tree_indent;
565 GTK_VALUE_UINT (*arg) = ctree->tree_spacing;
568 GTK_VALUE_BOOL (*arg) = ctree->show_stub;
570 case ARG_REORDERABLE:
571 GTK_VALUE_BOOL (*arg) = ctree->reorderable;
573 case ARG_USE_DRAG_ICONS:
574 GTK_VALUE_BOOL (*arg) = ctree->use_icons;
577 GTK_VALUE_ENUM (*arg) = ctree->line_style;
579 case ARG_EXPANDER_STYLE:
580 GTK_VALUE_ENUM (*arg) = ctree->expander_style;
583 arg->type = GTK_TYPE_INVALID;
589 gtk_ctree_init (GtkCTree *ctree)
591 ctree->drag_icon = NULL;
592 ctree->tree_indent = 20;
593 ctree->tree_spacing = 5;
594 ctree->tree_column = 0;
595 ctree->drag_row = -1;
596 ctree->drag_source = NULL;
597 ctree->drag_target = NULL;
598 ctree->insert_pos = GTK_CTREE_POS_AS_CHILD;
599 ctree->reorderable = FALSE;
600 ctree->use_icons = TRUE;
601 ctree->in_drag = FALSE;
602 ctree->drag_rect = FALSE;
603 ctree->line_style = GTK_CTREE_LINES_SOLID;
604 ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE;
605 ctree->drag_compare = NULL;
606 ctree->show_stub = TRUE;
610 ctree_attach_styles (GtkCTree *ctree,
617 clist = GTK_CLIST (ctree);
619 if (GTK_CTREE_ROW (node)->row.style)
620 GTK_CTREE_ROW (node)->row.style =
621 gtk_style_attach (GTK_CTREE_ROW (node)->row.style, clist->clist_window);
623 if (GTK_CTREE_ROW (node)->row.fg_set || GTK_CTREE_ROW (node)->row.bg_set)
625 GdkColormap *colormap;
627 colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
628 if (GTK_CTREE_ROW (node)->row.fg_set)
629 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.foreground));
630 if (GTK_CTREE_ROW (node)->row.bg_set)
631 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.background));
634 for (i = 0; i < clist->columns; i++)
635 if (GTK_CTREE_ROW (node)->row.cell[i].style)
636 GTK_CTREE_ROW (node)->row.cell[i].style =
637 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[i].style,
638 clist->clist_window);
642 ctree_detach_styles (GtkCTree *ctree,
649 clist = GTK_CLIST (ctree);
651 if (GTK_CTREE_ROW (node)->row.style)
652 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
653 for (i = 0; i < clist->columns; i++)
654 if (GTK_CTREE_ROW (node)->row.cell[i].style)
655 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[i].style);
659 gtk_ctree_realize (GtkWidget *widget)
668 g_return_if_fail (widget != NULL);
669 g_return_if_fail (GTK_IS_CTREE (widget));
671 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
673 ctree = GTK_CTREE (widget);
674 clist = GTK_CLIST (widget);
676 node = GTK_CTREE_NODE (clist->row_list);
677 for (i = 0; i < clist->rows; i++)
679 if (GTK_CTREE_ROW (node)->children && !GTK_CTREE_ROW (node)->expanded)
680 for (child = GTK_CTREE_ROW (node)->children; child;
681 child = GTK_CTREE_ROW (child)->sibling)
682 gtk_ctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
683 node = GTK_CTREE_NODE_NEXT (node);
686 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
687 values.background = widget->style->bg[GTK_STATE_NORMAL];
688 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
689 values.line_style = GDK_LINE_SOLID;
690 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
697 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
699 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
700 GDK_LINE_ON_OFF_DASH, None, None);
701 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
706 gtk_ctree_unrealize (GtkWidget *widget)
711 g_return_if_fail (widget != NULL);
712 g_return_if_fail (GTK_IS_CTREE (widget));
714 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
716 ctree = GTK_CTREE (widget);
717 clist = GTK_CLIST (widget);
719 if (GTK_WIDGET_REALIZED (widget))
725 node = GTK_CTREE_NODE (clist->row_list);
726 for (i = 0; i < clist->rows; i++)
728 if (GTK_CTREE_ROW (node)->children &&
729 !GTK_CTREE_ROW (node)->expanded)
730 for (child = GTK_CTREE_ROW (node)->children; child;
731 child = GTK_CTREE_ROW (child)->sibling)
732 gtk_ctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
733 node = GTK_CTREE_NODE_NEXT (node);
737 gdk_gc_destroy (ctree->lines_gc);
741 gtk_ctree_button_press (GtkWidget *widget,
742 GdkEventButton *event)
747 g_return_val_if_fail (widget != NULL, FALSE);
748 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
749 g_return_val_if_fail (event != NULL, FALSE);
751 ctree = GTK_CTREE (widget);
752 clist = GTK_CLIST (widget);
754 if (event->window == clist->clist_window)
756 gboolean collapse_expand = FALSE;
766 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
769 if (event->button == 2)
770 ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
772 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
774 if (ctree->reorderable && event->button == 2 && !ctree->in_drag &&
777 gdk_pointer_grab (event->window, FALSE,
778 GDK_POINTER_MOTION_HINT_MASK |
779 GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
780 NULL, NULL, event->time);
781 gtk_grab_add (widget);
782 ctree->in_drag = TRUE;
783 ctree->drag_source = work;
784 ctree->drag_target = NULL;
785 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
787 gdk_gc_set_dashes (clist->xor_gc, 0, "\2\2", 2);
790 else if (event->button == 1 &&
791 (GTK_CTREE_ROW (work)->children &&
792 (event->type == GDK_2BUTTON_PRESS ||
793 ctree_is_hot_spot (ctree, work, row, x, y))))
795 if (GTK_CTREE_ROW (work)->expanded)
796 gtk_ctree_collapse (ctree, work);
798 gtk_ctree_expand (ctree, work);
800 collapse_expand = TRUE;
802 if (event->button == 1)
804 gint old_row = clist->focus_row;
805 gboolean no_focus_row = FALSE;
807 switch (clist->selection_mode)
809 case GTK_SELECTION_MULTIPLE:
810 case GTK_SELECTION_SINGLE:
811 if (!collapse_expand)
814 if (clist->focus_row == -1)
820 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
821 gdk_pointer_grab (clist->clist_window, FALSE,
822 GDK_POINTER_MOTION_HINT_MASK |
823 GDK_BUTTON1_MOTION_MASK |
824 GDK_BUTTON_RELEASE_MASK,
825 NULL, NULL, event->time);
826 gtk_grab_add (widget);
828 if (GTK_CLIST_ADD_MODE (clist))
830 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
831 if (GTK_WIDGET_HAS_FOCUS (widget))
833 gtk_widget_draw_focus (widget);
834 gdk_gc_set_line_attributes (clist->xor_gc, 1,
835 GDK_LINE_SOLID, 0, 0);
836 clist->focus_row = row;
837 gtk_widget_draw_focus (widget);
841 gdk_gc_set_line_attributes (clist->xor_gc, 1,
842 GDK_LINE_SOLID, 0, 0);
843 clist->focus_row = row;
846 else if (row != clist->focus_row)
848 if (GTK_WIDGET_HAS_FOCUS (widget))
850 gtk_widget_draw_focus (widget);
851 clist->focus_row = row;
852 gtk_widget_draw_focus (widget);
855 clist->focus_row = row;
858 if (!GTK_WIDGET_HAS_FOCUS (widget))
859 gtk_widget_grab_focus (widget);
868 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
872 gtk_ctree_button_motion (GtkWidget *widget,
873 GdkEventMotion *event)
880 gint insert_pos = GTK_CTREE_POS_AS_CHILD;
882 g_return_val_if_fail (widget != NULL, FALSE);
883 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
884 g_return_val_if_fail (event != NULL, FALSE);
886 ctree = GTK_CTREE (widget);
887 clist = GTK_CLIST (widget);
889 if (GTK_CLIST_IN_DRAG (clist))
890 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
893 if (event->window == clist->clist_window &&
894 ctree->in_drag && ctree->reorderable)
896 GdkModifierType modmask;
903 gdk_window_get_pointer (event->window, &x, &y, NULL);
905 /* delayed drag start */
906 if (!ctree->drag_target &&
907 y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
908 y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
910 GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
912 if (ctree->use_icons)
914 if (!ctree->drag_icon)
915 create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
918 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
919 gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
920 root_y - ctree->icon_height);
924 /* out of bounds check */
925 if (x < 0 || y < -3 || x > clist->clist_window_width ||
926 y > clist->clist_window_height + 3 ||
927 y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
929 if (ctree->drag_row >= 0)
931 if (ctree->drag_rect)
933 draw_xor_rect (ctree);
934 ctree->drag_rect = FALSE;
937 draw_xor_line (ctree);
938 ctree->drag_row = -1;
941 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
945 row = ROW_FROM_YPIXEL (clist, y);
947 /* re-calculate target (mouse left the window) */
948 if (ctree->drag_target && ctree->drag_row == -1)
949 ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row));
951 if (y < 0 || y > clist->clist_window_height ||
952 ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
953 || row >= clist->rows)
954 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
957 if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
958 insert_pos = GTK_CTREE_POS_BEFORE;
959 else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y
960 < clist->row_height / 4)
961 insert_pos = GTK_CTREE_POS_AFTER;
963 if (row != ctree->drag_row ||
964 (row == ctree->drag_row && ctree->insert_pos != insert_pos))
966 if (insert_pos != GTK_CTREE_POS_AS_CHILD)
968 if (ctree->drag_row >= 0)
970 if (ctree->drag_rect)
972 draw_xor_rect (ctree);
973 ctree->drag_rect = FALSE;
976 draw_xor_line (ctree);
978 ctree->insert_pos = insert_pos;
980 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
981 ctree->drag_row = row;
982 draw_xor_line (ctree);
985 else if (ctree->drag_target &&
986 !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
988 if (ctree->drag_row >= 0)
990 if (ctree->drag_rect)
991 draw_xor_rect (ctree);
993 draw_xor_line (ctree);
995 ctree->drag_rect = TRUE;
996 ctree->insert_pos = insert_pos;
998 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
999 ctree->drag_row = row;
1000 draw_xor_rect (ctree);
1001 check_cursor(ctree);
1005 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
1009 gtk_ctree_button_release (GtkWidget *widget,
1010 GdkEventButton *event)
1015 g_return_val_if_fail (widget != NULL, FALSE);
1016 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
1017 g_return_val_if_fail (event != NULL, FALSE);
1019 ctree = GTK_CTREE (widget);
1020 clist = GTK_CLIST (widget);
1022 if (event->button == 2 && clist->anchor == -1)
1024 gtk_grab_remove (widget);
1025 gdk_pointer_ungrab (event->time);
1027 ctree->in_drag = FALSE;
1029 set_mouse_cursor(ctree, TRUE);
1031 if (ctree->use_icons && ctree->drag_icon)
1033 gdk_window_destroy (ctree->drag_icon);
1034 ctree->drag_icon = NULL;
1037 if (ctree->drag_row >= 0)
1039 if (ctree->drag_rect)
1041 draw_xor_rect (ctree);
1042 ctree->drag_rect = FALSE;
1045 draw_xor_line (ctree);
1046 ctree->drag_row = -1;
1049 if (GTK_CLIST_ADD_MODE (clist))
1050 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
1052 gdk_gc_set_line_attributes (clist->xor_gc, 1,
1053 GDK_LINE_SOLID, 0, 0);
1055 /* nop if out of bounds / source == target */
1056 if (event->x < 0 || event->y < -3 ||
1057 event->x > clist->clist_window_width ||
1058 event->y > clist->clist_window_height + 3 ||
1059 ctree->drag_target == ctree->drag_source ||
1060 !ctree->drag_target)
1061 return GTK_WIDGET_CLASS (parent_class)->button_release_event
1064 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
1065 !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
1066 ctree->drag_target))
1068 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
1070 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
1072 if (!ctree->drag_compare ||
1073 ctree->drag_compare (ctree,
1075 GTK_CTREE_ROW (ctree->drag_target)->parent,
1076 GTK_CTREE_ROW (ctree->drag_target)->sibling))
1077 gtk_signal_emit (GTK_OBJECT (ctree),
1078 ctree_signals[TREE_MOVE],
1080 GTK_CTREE_ROW (ctree->drag_target)->parent,
1081 GTK_CTREE_ROW (ctree->drag_target)->sibling);
1083 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
1085 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
1087 if (!ctree->drag_compare ||
1088 ctree->drag_compare (ctree,
1090 GTK_CTREE_ROW (ctree->drag_target)->parent,
1091 ctree->drag_target))
1092 gtk_signal_emit (GTK_OBJECT (ctree),
1093 ctree_signals[TREE_MOVE],
1095 GTK_CTREE_ROW (ctree->drag_target)->parent,
1096 ctree->drag_target);
1098 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
1100 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
1102 if (!ctree->drag_compare ||
1103 ctree->drag_compare (ctree,
1106 GTK_CTREE_ROW (ctree->drag_target)->children))
1107 gtk_signal_emit (GTK_OBJECT (ctree),
1108 ctree_signals[TREE_MOVE],
1111 GTK_CTREE_ROW (ctree->drag_target)->children);
1114 ctree->drag_source = NULL;
1115 ctree->drag_target = NULL;
1117 else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) &&
1118 (clist->selection_mode == GTK_SELECTION_SINGLE ||
1119 clist->selection_mode == GTK_SELECTION_MULTIPLE))
1125 if (gtk_clist_get_selection_info
1126 (clist, event->x, event->y, &row, &column))
1128 if (clist->anchor == clist->focus_row &&
1129 (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row))))
1130 tree_toggle_selection (ctree, work, column);
1134 return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
1138 create_drag_icon (GtkCTree *ctree,
1143 GdkWindow *window = NULL;
1144 GdkWindowAttr attributes;
1145 gint attributes_mask;
1148 GdkModifierType modmask;
1152 clist = GTK_CLIST (ctree);
1153 widget = GTK_WIDGET (ctree);
1155 if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap))
1157 mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
1159 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
1160 gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
1162 attributes.window_type = GDK_WINDOW_TEMP;
1163 attributes.x = root_x - ctree->icon_width / 2;
1164 attributes.y = root_y - ctree->icon_height;
1165 attributes.width = ctree->icon_width;
1166 attributes.height = ctree->icon_height;
1167 attributes.wclass = GDK_INPUT_OUTPUT;
1168 attributes.visual = gtk_widget_get_visual (widget);
1169 attributes.colormap = gtk_widget_get_colormap (widget);
1170 attributes.event_mask = gtk_widget_get_events (widget);
1172 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1174 window = gdk_window_new (widget->window, &attributes, attributes_mask);
1175 gdk_window_set_back_pixmap (window, pixmap, FALSE);
1177 gdk_window_shape_combine_mask (window, mask, 0, 0);
1178 gdk_window_show (window);
1180 ctree->drag_icon = window;
1184 draw_xor_line (GtkCTree *ctree)
1190 clist = GTK_CLIST (ctree);
1192 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1194 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
1195 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1197 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
1199 if (clist->column[ctree->tree_column].visible)
1200 switch (clist->column[ctree->tree_column].justification)
1202 case GTK_JUSTIFY_CENTER:
1203 case GTK_JUSTIFY_FILL:
1204 case GTK_JUSTIFY_LEFT:
1205 if (ctree->tree_column > 0)
1206 gdk_draw_line (clist->clist_window, clist->xor_gc,
1207 COLUMN_LEFT_XPIXEL(clist, 0), y,
1208 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1209 clist->column[ctree->tree_column - 1].area.width, y);
1211 gdk_draw_line (clist->clist_window, clist->xor_gc,
1212 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1213 ctree->tree_indent * level -
1214 (ctree->tree_indent - PM_SIZE) / 2, y,
1215 GTK_WIDGET (ctree)->allocation.width, y);
1217 case GTK_JUSTIFY_RIGHT:
1218 if (ctree->tree_column < clist->columns - 1)
1219 gdk_draw_line (clist->clist_window, clist->xor_gc,
1220 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
1221 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
1222 clist->column[clist->columns - 1].area.width, y);
1224 gdk_draw_line (clist->clist_window, clist->xor_gc,
1225 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
1226 + clist->column[ctree->tree_column].area.width -
1227 ctree->tree_indent * level +
1228 (ctree->tree_indent - PM_SIZE) / 2, y);
1232 gdk_draw_line (clist->clist_window, clist->xor_gc,
1233 0, y, clist->clist_window_width, y);
1237 draw_xor_rect (GtkCTree *ctree)
1245 clist = GTK_CLIST (ctree);
1247 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1249 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1251 if (clist->column[ctree->tree_column].visible)
1252 switch (clist->column[ctree->tree_column].justification)
1254 case GTK_JUSTIFY_CENTER:
1255 case GTK_JUSTIFY_FILL:
1256 case GTK_JUSTIFY_LEFT:
1257 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1258 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
1260 points[3].x = points[0].x;
1261 points[3].y = y - clist->row_height - 1;
1262 points[1].x = clist->clist_window_width - 1;
1263 points[1].y = points[0].y;
1264 points[2].x = points[1].x;
1265 points[2].y = points[3].y;
1267 for (i = 0; i < 3; i++)
1268 gdk_draw_line (clist->clist_window, clist->xor_gc,
1269 points[i].x, points[i].y,
1270 points[i+1].x, points[i+1].y);
1272 if (ctree->tree_column > 0)
1274 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1275 clist->column[ctree->tree_column - 1].area.width ;
1277 points[3].x = points[0].x;
1278 points[3].y = y - clist->row_height - 1;
1280 points[1].y = points[0].y;
1282 points[2].y = points[3].y;
1284 for (i = 0; i < 3; i++)
1285 gdk_draw_line (clist->clist_window, clist->xor_gc,
1286 points[i].x, points[i].y, points[i+1].x,
1290 case GTK_JUSTIFY_RIGHT:
1291 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
1292 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
1293 clist->column[ctree->tree_column].area.width;
1295 points[3].x = points[0].x;
1296 points[3].y = y - clist->row_height - 1;
1298 points[1].y = points[0].y;
1300 points[2].y = points[3].y;
1302 for (i = 0; i < 3; i++)
1303 gdk_draw_line (clist->clist_window, clist->xor_gc,
1304 points[i].x, points[i].y,
1305 points[i+1].x, points[i+1].y);
1307 if (ctree->tree_column < clist->columns - 1)
1309 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
1311 points[3].x = points[0].x;
1312 points[3].y = y - clist->row_height - 1;
1313 points[1].x = clist->clist_window_width - 1;
1314 points[1].y = points[0].y;
1315 points[2].x = points[1].x;
1316 points[2].y = points[3].y;
1318 for (i = 0; i < 3; i++)
1319 gdk_draw_line (clist->clist_window, clist->xor_gc,
1320 points[i].x, points[i].y,
1321 points[i+1].x, points[i+1].y);
1326 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1327 0, y - clist->row_height,
1328 clist->clist_window_width - 1, clist->row_height);
1332 draw_cell_pixmap (GdkWindow *window,
1333 GdkRectangle *clip_rectangle,
1347 gdk_gc_set_clip_mask (fg_gc, mask);
1348 gdk_gc_set_clip_origin (fg_gc, x, y);
1350 if (x < clip_rectangle->x)
1352 xsrc = clip_rectangle->x - x;
1354 x = clip_rectangle->x;
1356 if (x + width > clip_rectangle->x + clip_rectangle->width)
1357 width = clip_rectangle->x + clip_rectangle->width - x;
1359 if (y < clip_rectangle->y)
1361 ysrc = clip_rectangle->y - y;
1363 y = clip_rectangle->y;
1365 if (y + height > clip_rectangle->y + clip_rectangle->height)
1366 height = clip_rectangle->y + clip_rectangle->height - y;
1368 if (width > 0 && height > 0)
1369 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
1371 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1373 return x + MAX (width, 0);
1377 get_cell_style (GtkCList *clist,
1378 GtkCListRow *clist_row,
1385 if (clist_row->cell[column].style)
1388 *style = clist_row->cell[column].style;
1390 *fg_gc = clist_row->cell[column].style->fg_gc[state];
1392 *bg_gc = clist_row->cell[column].style->bg_gc[state];
1394 else if (clist_row->style)
1397 *style = clist_row->style;
1399 *fg_gc = clist_row->style->fg_gc[state];
1401 *bg_gc = clist_row->style->bg_gc[state];
1406 *style = GTK_WIDGET (clist)->style;
1408 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[state];
1410 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1412 if (state != GTK_STATE_SELECTED)
1414 if (fg_gc && clist_row->fg_set)
1415 *fg_gc = clist->fg_gc;
1416 if (bg_gc && clist_row->bg_set)
1417 *bg_gc = clist->bg_gc;
1423 gtk_ctree_draw_expander (GtkCTree *ctree,
1424 GtkCTreeRow *ctree_row,
1426 GdkRectangle *clip_rectangle,
1431 gint justification_factor;
1434 if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
1437 clist = GTK_CLIST (ctree);
1438 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
1439 justification_factor = -1;
1441 justification_factor = 1;
1442 y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
1443 (clip_rectangle->height + 1) % 2);
1445 if (!ctree_row->children)
1447 switch (ctree->expander_style)
1449 case GTK_CTREE_EXPANDER_NONE:
1451 case GTK_CTREE_EXPANDER_TRIANGLE:
1452 return x + justification_factor * (PM_SIZE + 3);
1453 case GTK_CTREE_EXPANDER_SQUARE:
1454 case GTK_CTREE_EXPANDER_CIRCULAR:
1455 return x + justification_factor * (PM_SIZE + 1);
1459 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle);
1460 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle);
1462 switch (ctree->expander_style)
1464 case GTK_CTREE_EXPANDER_NONE:
1466 case GTK_CTREE_EXPANDER_TRIANGLE:
1467 if (ctree_row->expanded)
1470 points[0].y = y + (PM_SIZE + 2) / 6;
1471 points[1].x = points[0].x + justification_factor * (PM_SIZE + 2);
1472 points[1].y = points[0].y;
1473 points[2].x = (points[0].x +
1474 justification_factor * (PM_SIZE + 2) / 2);
1475 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
1479 points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2);
1480 points[0].y = y - 1;
1481 points[1].x = points[0].x;
1482 points[1].y = points[0].y + (PM_SIZE + 2);
1483 points[2].x = (points[0].x +
1484 justification_factor * (2 * (PM_SIZE + 2) / 3 - 1));
1485 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
1488 gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1490 gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1493 x += justification_factor * (PM_SIZE + 3);
1495 case GTK_CTREE_EXPANDER_SQUARE:
1496 case GTK_CTREE_EXPANDER_CIRCULAR:
1497 if (justification_factor == -1)
1498 x += justification_factor * (PM_SIZE + 1);
1500 if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
1502 gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1503 TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1504 gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1505 FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1509 gdk_draw_rectangle (clist->clist_window,
1510 style->base_gc[GTK_STATE_NORMAL], TRUE,
1511 x, y, PM_SIZE, PM_SIZE);
1512 gdk_draw_rectangle (clist->clist_window,
1513 style->fg_gc[GTK_STATE_NORMAL], FALSE,
1514 x, y, PM_SIZE, PM_SIZE);
1517 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1518 x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
1520 if (!ctree_row->expanded)
1521 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1522 x + PM_SIZE / 2, y + 2,
1523 x + PM_SIZE / 2, y + PM_SIZE - 2);
1525 if (justification_factor == 1)
1526 x += justification_factor * (PM_SIZE + 1);
1530 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
1531 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
1538 gtk_ctree_draw_lines (GtkCTree *ctree,
1539 GtkCTreeRow *ctree_row,
1543 GdkRectangle *clip_rectangle,
1544 GdkRectangle *cell_rectangle,
1545 GdkRectangle *crect,
1551 GtkCTreeNode *parent;
1552 GdkRectangle tree_rectangle;
1553 GdkRectangle tc_rectangle;
1564 gint justification_factor;
1566 clist = GTK_CLIST (ctree);
1567 ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
1568 justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
1572 offset = (clip_rectangle->x + clip_rectangle->width - 1 -
1573 ctree->tree_indent * (ctree_row->level - 1));
1574 justification_factor = -1;
1578 offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1);
1579 justification_factor = 1;
1582 switch (ctree->line_style)
1584 case GTK_CTREE_LINES_NONE:
1586 case GTK_CTREE_LINES_TABBED:
1587 xcenter = offset + justification_factor * TAB_SIZE;
1589 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1590 clist->column[ctree->tree_column].area.width +
1592 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1593 COLUMN_INSET - CELL_SPACING);
1597 tree_rectangle.y = crect->y;
1598 tree_rectangle.height = crect->height;
1602 tree_rectangle.x = xcenter;
1603 tree_rectangle.width = column_right - xcenter;
1607 tree_rectangle.x = column_left;
1608 tree_rectangle.width = xcenter - column_left;
1611 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1613 offset += justification_factor * 3;
1618 gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
1620 next_level = ctree_row->level;
1622 if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
1624 node = gtk_ctree_find_node_ptr (ctree, ctree_row);
1625 if (GTK_CTREE_NODE_NEXT (node))
1626 next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level;
1631 if (ctree->tree_indent > 0)
1633 node = ctree_row->parent;
1636 xcenter -= (justification_factor * ctree->tree_indent);
1638 if ((justify_right && xcenter < column_left) ||
1639 (!justify_right && xcenter > column_right))
1641 node = GTK_CTREE_ROW (node)->parent;
1645 tree_rectangle.y = cell_rectangle->y;
1646 tree_rectangle.height = cell_rectangle->height;
1649 tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1,
1651 tree_rectangle.width = MIN (xcenter - column_left,
1652 ctree->tree_indent);
1656 tree_rectangle.x = xcenter;
1657 tree_rectangle.width = MIN (column_right - xcenter,
1658 ctree->tree_indent);
1661 if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
1664 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1665 state, column, NULL, NULL, &bg_gc);
1667 if (bg_gc == clist->bg_gc)
1668 gdk_gc_set_foreground
1669 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1672 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1675 tree_rectangle.width,
1676 tree_rectangle.height);
1678 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1682 tc_rectangle.height);
1684 if (next_level > GTK_CTREE_ROW (node)->level)
1685 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1687 xcenter, crect->y + crect->height);
1692 offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1693 width = offset_x / 2 + offset_x % 2;
1695 parent = GTK_CTREE_ROW (node)->parent;
1697 tree_rectangle.y = ycenter;
1698 tree_rectangle.height = (cell_rectangle->y - ycenter +
1699 cell_rectangle->height);
1703 tree_rectangle.x = MAX(xcenter + 1 - width, column_left);
1704 tree_rectangle.width = MIN (xcenter + 1 - column_left,
1709 tree_rectangle.x = xcenter;
1710 tree_rectangle.width = MIN (column_right - xcenter,
1715 gdk_rectangle_intersect (area, &tree_rectangle,
1720 get_cell_style (clist, >K_CTREE_ROW (parent)->row,
1721 state, column, NULL, NULL, &bg_gc);
1722 if (bg_gc == clist->bg_gc)
1723 gdk_gc_set_foreground
1725 >K_CTREE_ROW (parent)->row.background);
1727 else if (state == GTK_STATE_SELECTED)
1728 bg_gc = style->bg_gc[state];
1730 bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1733 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1736 tree_rectangle.width,
1737 tree_rectangle.height);
1739 gdk_draw_rectangle (clist->clist_window,
1744 tc_rectangle.height);
1747 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1748 state, column, NULL, NULL, &bg_gc);
1749 if (bg_gc == clist->bg_gc)
1750 gdk_gc_set_foreground
1751 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1753 gdk_gc_set_clip_rectangle (bg_gc, crect);
1754 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1755 xcenter - (justify_right * offset_x),
1757 offset_x, clist->row_height,
1758 (180 + (justify_right * 90)) * 64, 90 * 64);
1759 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1761 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1762 xcenter, cell_rectangle->y, xcenter, ycenter);
1765 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1766 xcenter - offset_x, cell_rectangle->y,
1767 offset_x, clist->row_height,
1770 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1771 xcenter, cell_rectangle->y,
1772 offset_x, clist->row_height,
1775 node = GTK_CTREE_ROW (node)->parent;
1779 if (state != GTK_STATE_SELECTED)
1781 tree_rectangle.y = clip_rectangle->y;
1782 tree_rectangle.height = clip_rectangle->height;
1783 tree_rectangle.width = COLUMN_INSET + CELL_SPACING +
1784 MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET,
1788 tree_rectangle.x = MAX (xcenter + 1, column_left);
1790 tree_rectangle.x = column_left;
1793 gdk_draw_rectangle (clist->clist_window,
1795 (ctree)->style->bg_gc[GTK_STATE_PRELIGHT],
1799 tree_rectangle.width,
1800 tree_rectangle.height);
1801 else if (gdk_rectangle_intersect (area, &tree_rectangle,
1803 gdk_draw_rectangle (clist->clist_window,
1805 (ctree)->style->bg_gc[GTK_STATE_PRELIGHT],
1810 tc_rectangle.height);
1813 xcenter = offset + (justification_factor * ctree->tree_indent / 2);
1815 get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL,
1817 if (bg_gc == clist->bg_gc)
1818 gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background);
1820 gdk_gc_set_clip_rectangle (bg_gc, crect);
1821 if (ctree_row->is_leaf)
1825 points[0].x = offset + justification_factor * TAB_SIZE;
1826 points[0].y = cell_rectangle->y;
1828 points[1].x = points[0].x - justification_factor * 4;
1829 points[1].y = points[0].y;
1831 points[2].x = points[1].x - justification_factor * 2;
1832 points[2].y = points[1].y + 3;
1834 points[3].x = points[2].x;
1835 points[3].y = points[2].y + clist->row_height - 5;
1837 points[4].x = points[3].x + justification_factor * 2;
1838 points[4].y = points[3].y + 3;
1840 points[5].x = points[4].x + justification_factor * 4;
1841 points[5].y = points[4].y;
1843 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6);
1844 gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6);
1848 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1849 offset - (justify_right * 2 * TAB_SIZE),
1851 2 * TAB_SIZE, clist->row_height,
1852 (90 + (180 * justify_right)) * 64, 180 * 64);
1853 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1854 offset - (justify_right * 2 * TAB_SIZE),
1856 2 * TAB_SIZE, clist->row_height,
1857 (90 + (180 * justify_right)) * 64, 180 * 64);
1859 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1860 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1862 offset += justification_factor * 3;
1865 xcenter = offset + justification_factor * PM_SIZE / 2;
1869 tree_rectangle.y = crect->y;
1870 tree_rectangle.height = crect->height;
1874 tree_rectangle.x = xcenter - PM_SIZE / 2 - 2;
1875 tree_rectangle.width = (clip_rectangle->x +
1876 clip_rectangle->width -tree_rectangle.x);
1880 tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2;
1881 tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 -
1885 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1891 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1893 offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
1894 offset_y = abs((cell_rectangle->y + clist->voffset) % 2);
1897 clip_rectangle->y--;
1898 clip_rectangle->height++;
1899 gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle);
1900 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1902 (ctree->show_stub || clist->row_list->data != ctree_row) ?
1903 cell_rectangle->y + offset_y : ycenter,
1905 (ctree_row->sibling) ? crect->y +crect->height : ycenter);
1907 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1908 xcenter + (justification_factor * offset_x), ycenter,
1909 xcenter + (justification_factor * (PM_SIZE / 2 + 2)),
1912 node = ctree_row->parent;
1915 xcenter -= (justification_factor * ctree->tree_indent);
1917 if (GTK_CTREE_ROW (node)->sibling)
1918 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1919 xcenter, cell_rectangle->y + offset_y,
1920 xcenter, crect->y + crect->height);
1921 node = GTK_CTREE_ROW (node)->parent;
1923 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1924 clip_rectangle->y++;
1925 clip_rectangle->height--;
1932 draw_row (GtkCList *clist,
1935 GtkCListRow *clist_row)
1940 GdkRectangle *crect;
1941 GdkRectangle row_rectangle;
1942 GdkRectangle cell_rectangle;
1943 GdkRectangle clip_rectangle;
1944 GdkRectangle intersect_rectangle;
1945 gint column_left = 0;
1946 gint column_right = 0;
1951 g_return_if_fail (clist != NULL);
1953 /* bail now if we arn't drawable yet */
1954 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
1957 widget = GTK_WIDGET (clist);
1958 ctree = GTK_CTREE (clist);
1960 /* if the function is passed the pointer to the row instead of null,
1961 * it avoids this expensive lookup */
1963 clist_row = (g_list_nth (clist->row_list, row))->data;
1965 /* rectangle of the entire row */
1966 row_rectangle.x = 0;
1967 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1968 row_rectangle.width = clist->clist_window_width;
1969 row_rectangle.height = clist->row_height;
1971 /* rectangle of the cell spacing above the row */
1972 cell_rectangle.x = 0;
1973 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1974 cell_rectangle.width = row_rectangle.width;
1975 cell_rectangle.height = CELL_SPACING;
1977 /* rectangle used to clip drawing operations, it's y and height
1978 * positions only need to be set once, so we set them once here.
1979 * the x and width are set withing the drawing loop below once per
1981 clip_rectangle.y = row_rectangle.y;
1982 clip_rectangle.height = row_rectangle.height;
1984 if (clist_row->state == GTK_STATE_NORMAL)
1986 state = GTK_STATE_PRELIGHT;
1987 if (clist_row->fg_set)
1988 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1989 if (clist_row->bg_set)
1990 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1993 state = clist_row->state;
1995 gdk_gc_set_foreground (ctree->lines_gc,
1996 &widget->style->fg[clist_row->state]);
1998 /* draw the cell borders */
2001 rect = &intersect_rectangle;
2002 crect = &intersect_rectangle;
2004 if (gdk_rectangle_intersect (area, &cell_rectangle, crect))
2005 gdk_draw_rectangle (clist->clist_window,
2006 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2007 crect->x, crect->y, crect->width, crect->height);
2011 rect = &clip_rectangle;
2012 crect = &cell_rectangle;
2014 gdk_draw_rectangle (clist->clist_window,
2015 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2016 crect->x, crect->y, crect->width, crect->height);
2019 /* horizontal black lines */
2020 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2023 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
2024 clist->column[ctree->tree_column].area.width +
2026 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
2027 COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING);
2029 switch (clist->column[ctree->tree_column].justification)
2031 case GTK_JUSTIFY_CENTER:
2032 case GTK_JUSTIFY_FILL:
2033 case GTK_JUSTIFY_LEFT:
2034 offset = (column_left + ctree->tree_indent *
2035 (((GtkCTreeRow *)clist_row)->level - 1));
2037 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2038 MIN (offset + TAB_SIZE, column_right),
2040 clist->clist_window_width, cell_rectangle.y);
2042 case GTK_JUSTIFY_RIGHT:
2043 offset = (column_right - 1 - ctree->tree_indent *
2044 (((GtkCTreeRow *)clist_row)->level - 1));
2046 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2047 -1, cell_rectangle.y,
2048 MAX (offset - TAB_SIZE, column_left),
2054 /* the last row has to clear it's bottom cell spacing too */
2055 if (clist_row == clist->row_list_end->data)
2057 cell_rectangle.y += clist->row_height + CELL_SPACING;
2059 if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect))
2061 gdk_draw_rectangle (clist->clist_window,
2062 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2063 crect->x, crect->y, crect->width, crect->height);
2065 /* horizontal black lines */
2066 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2068 switch (clist->column[ctree->tree_column].justification)
2070 case GTK_JUSTIFY_CENTER:
2071 case GTK_JUSTIFY_FILL:
2072 case GTK_JUSTIFY_LEFT:
2073 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2074 MIN (column_left + TAB_SIZE + COLUMN_INSET +
2075 (((GtkCTreeRow *)clist_row)->level > 1) *
2076 MIN (ctree->tree_indent / 2, TAB_SIZE),
2079 clist->clist_window_width, cell_rectangle.y);
2081 case GTK_JUSTIFY_RIGHT:
2082 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2083 -1, cell_rectangle.y,
2084 MAX (column_right - TAB_SIZE - 1 -
2086 (((GtkCTreeRow *)clist_row)->level > 1) *
2087 MIN (ctree->tree_indent / 2, TAB_SIZE),
2088 column_left - 1), cell_rectangle.y);
2095 /* iterate and draw all the columns (row cells) and draw their contents */
2096 for (i = 0; i < clist->columns; i++)
2107 gint row_center_offset;
2109 if (!clist->column[i].visible)
2112 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
2114 /* calculate clipping region */
2115 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
2116 clip_rectangle.width = clist->column[i].area.width;
2118 cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING;
2119 cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET +
2120 (1 + (i + 1 == clist->columns)) * CELL_SPACING);
2121 cell_rectangle.y = clip_rectangle.y;
2122 cell_rectangle.height = clip_rectangle.height;
2127 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
2128 &intersect_rectangle))
2130 if (i != ctree->tree_column)
2135 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
2136 crect->x, crect->y, crect->width, crect->height);
2138 /* calculate real width for column justification */
2139 switch (clist_row->cell[i].type)
2142 width = gdk_string_width
2143 (style->font, GTK_CELL_TEXT (clist_row->cell[i])->text);
2145 case GTK_CELL_PIXMAP:
2147 (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
2149 width = pixmap_width;
2151 case GTK_CELL_PIXTEXT:
2152 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
2154 (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2155 &pixmap_width, &height);
2157 width = (pixmap_width +
2158 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing);
2160 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
2162 string_width = gdk_string_width
2163 (style->font, GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2164 width += string_width;
2167 if (i == ctree->tree_column)
2168 width += (ctree->tree_indent *
2169 ((GtkCTreeRow *)clist_row)->level);
2176 switch (clist->column[i].justification)
2178 case GTK_JUSTIFY_LEFT:
2179 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
2181 case GTK_JUSTIFY_RIGHT:
2182 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
2183 clip_rectangle.width - width);
2185 case GTK_JUSTIFY_CENTER:
2186 case GTK_JUSTIFY_FILL:
2187 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
2188 (clip_rectangle.width / 2) - (width / 2));
2192 if (i != ctree->tree_column)
2194 offset += clist_row->cell[i].horizontal;
2195 switch (clist_row->cell[i].type)
2197 case GTK_CELL_PIXMAP:
2199 (clist->clist_window, &clip_rectangle, fg_gc,
2200 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2201 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
2203 clip_rectangle.y + clist_row->cell[i].vertical +
2204 (clip_rectangle.height - height) / 2,
2205 pixmap_width, height);
2207 case GTK_CELL_PIXTEXT:
2208 offset = draw_cell_pixmap
2209 (clist->clist_window, &clip_rectangle, fg_gc,
2210 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2211 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
2213 clip_rectangle.y + clist_row->cell[i].vertical +
2214 (clip_rectangle.height - height) / 2,
2215 pixmap_width, height);
2216 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2218 if (style != GTK_WIDGET (clist)->style)
2219 row_center_offset = (((clist->row_height -
2220 style->font->ascent -
2221 style->font->descent - 1) / 2) +
2222 1.5 + style->font->ascent);
2224 row_center_offset = clist->row_center_offset;
2226 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
2228 (clist->clist_window, style->font, fg_gc,
2230 row_rectangle.y + row_center_offset +
2231 clist_row->cell[i].vertical,
2232 (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
2233 GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
2234 GTK_CELL_TEXT (clist_row->cell[i])->text);
2235 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2244 if (bg_gc == clist->bg_gc)
2245 gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
2247 /* draw ctree->tree_column */
2248 cell_rectangle.y -= CELL_SPACING;
2249 cell_rectangle.height += CELL_SPACING;
2251 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
2252 &intersect_rectangle))
2256 offset = gtk_ctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
2257 state, &clip_rectangle, &cell_rectangle,
2258 crect, area, style);
2261 offset = gtk_ctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
2262 style, &clip_rectangle, offset);
2264 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2265 offset -= ctree->tree_spacing;
2267 offset += ctree->tree_spacing;
2269 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2270 offset -= (pixmap_width + clist_row->cell[i].horizontal);
2272 offset += clist_row->cell[i].horizontal;
2274 old_offset = offset;
2275 offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
2276 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2277 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
2279 clip_rectangle.y + clist_row->cell[i].vertical
2280 + (clip_rectangle.height - height) / 2,
2281 pixmap_width, height);
2285 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2286 offset = (old_offset - string_width -
2287 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing);
2289 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2291 if (style != GTK_WIDGET (clist)->style)
2292 row_center_offset = (((clist->row_height - style->font->ascent -
2293 style->font->descent - 1) / 2) +
2294 1.5 + style->font->ascent);
2296 row_center_offset = clist->row_center_offset;
2298 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
2299 gdk_draw_string (clist->clist_window, style->font, fg_gc, offset,
2300 row_rectangle.y + row_center_offset +
2301 clist_row->cell[i].vertical,
2302 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2304 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2307 /* draw focus rectangle */
2308 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
2311 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2312 row_rectangle.x, row_rectangle.y,
2313 row_rectangle.width - 1, row_rectangle.height - 1);
2314 else if (gdk_rectangle_intersect (area, &row_rectangle,
2315 &intersect_rectangle))
2317 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
2318 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2319 row_rectangle.x, row_rectangle.y,
2320 row_rectangle.width - 1,
2321 row_rectangle.height - 1);
2322 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
2328 tree_draw_node (GtkCTree *ctree,
2333 clist = GTK_CLIST (ctree);
2335 if (!GTK_CLIST_FROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
2340 work = GTK_CTREE_NODE (clist->row_list);
2341 while (work && work != node)
2343 work = GTK_CTREE_NODE_NEXT (work);
2346 if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
2347 GTK_CLIST_CLASS_FW (clist)->draw_row
2348 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2352 static GtkCTreeNode *
2353 gtk_ctree_last_visible (GtkCTree *ctree,
2361 work = GTK_CTREE_ROW (node)->children;
2363 if (!work || !GTK_CTREE_ROW (node)->expanded)
2366 while (GTK_CTREE_ROW (work)->sibling)
2367 work = GTK_CTREE_ROW (work)->sibling;
2369 return gtk_ctree_last_visible (ctree, work);
2373 gtk_ctree_link (GtkCTree *ctree,
2375 GtkCTreeNode *parent,
2376 GtkCTreeNode *sibling,
2377 gboolean update_focus_row)
2383 gboolean visible = FALSE;
2387 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
2388 g_return_if_fail (node != NULL);
2389 g_return_if_fail (node != sibling);
2390 g_return_if_fail (node != parent);
2392 clist = GTK_CLIST (ctree);
2394 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2396 if (clist->anchor != -1)
2397 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2399 g_list_free (clist->undo_selection);
2400 g_list_free (clist->undo_unselection);
2401 clist->undo_selection = NULL;
2402 clist->undo_unselection = NULL;
2405 for (rows = 1, list_end = (GList *)node; list_end->next;
2406 list_end = list_end->next)
2409 GTK_CTREE_ROW (node)->parent = parent;
2410 GTK_CTREE_ROW (node)->sibling = sibling;
2412 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
2413 GTK_CTREE_ROW (parent)->expanded)))
2416 clist->rows += rows;
2420 work = (GList *)(GTK_CTREE_ROW (parent)->children);
2422 work = clist->row_list;
2426 if (work != (GList *)sibling)
2428 while (GTK_CTREE_ROW (work)->sibling != sibling)
2429 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2430 GTK_CTREE_ROW (work)->sibling = node;
2433 if (sibling == GTK_CTREE_NODE (clist->row_list))
2434 clist->row_list = (GList *) node;
2435 if (GTK_CTREE_NODE_PREV (sibling) &&
2436 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2438 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
2439 list->next = (GList *)node;
2442 list = (GList *)node;
2443 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
2444 list_end->next = (GList *)sibling;
2445 list = (GList *)sibling;
2446 list->prev = list_end;
2447 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2448 GTK_CTREE_ROW (parent)->children = node;
2455 while (GTK_CTREE_ROW (work)->sibling)
2456 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2457 GTK_CTREE_ROW (work)->sibling = node;
2459 /* find last visible child of sibling */
2460 work = (GList *) gtk_ctree_last_visible (ctree,
2461 GTK_CTREE_NODE (work));
2463 list_end->next = work->next;
2465 list = work->next->prev = list_end;
2466 work->next = (GList *)node;
2467 list = (GList *)node;
2474 GTK_CTREE_ROW (parent)->children = node;
2475 list = (GList *)node;
2476 list->prev = (GList *)parent;
2477 if (GTK_CTREE_ROW (parent)->expanded)
2479 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
2480 if (GTK_CTREE_NODE_NEXT(parent))
2482 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
2483 list->prev = list_end;
2485 list = (GList *)parent;
2486 list->next = (GList *)node;
2489 list_end->next = NULL;
2493 clist->row_list = (GList *)node;
2494 list = (GList *)node;
2496 list_end->next = NULL;
2501 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2503 if (clist->row_list_end == NULL ||
2504 clist->row_list_end->next == (GList *)node)
2505 clist->row_list_end = list_end;
2507 if (visible && update_focus_row)
2511 pos = g_list_position (clist->row_list, (GList *)node);
2513 if (pos <= clist->focus_row)
2515 clist->focus_row += rows;
2516 clist->undo_anchor = clist->focus_row;
2522 gtk_ctree_unlink (GtkCTree *ctree,
2524 gboolean update_focus_row)
2531 GtkCTreeNode *parent;
2534 g_return_if_fail (ctree != NULL);
2535 g_return_if_fail (GTK_IS_CTREE (ctree));
2536 g_return_if_fail (node != NULL);
2538 clist = GTK_CLIST (ctree);
2540 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2542 if (clist->anchor != -1)
2543 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2545 g_list_free (clist->undo_selection);
2546 g_list_free (clist->undo_unselection);
2547 clist->undo_selection = NULL;
2548 clist->undo_unselection = NULL;
2551 visible = gtk_ctree_is_viewable (ctree, node);
2553 /* clist->row_list_end unlinked ? */
2555 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2556 (GTK_CTREE_ROW (node)->children &&
2557 gtk_ctree_is_ancestor (ctree, node,
2558 GTK_CTREE_NODE (clist->row_list_end)))))
2559 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
2563 level = GTK_CTREE_ROW (node)->level;
2564 work = GTK_CTREE_NODE_NEXT (node);
2565 while (work && GTK_CTREE_ROW (work)->level > level)
2567 work = GTK_CTREE_NODE_NEXT (work);
2573 clist->rows -= (rows + 1);
2575 if (update_focus_row)
2579 pos = g_list_position (clist->row_list, (GList *)node);
2580 if (pos + rows < clist->focus_row)
2581 clist->focus_row -= (rows + 1);
2582 else if (pos <= clist->focus_row)
2584 if (!GTK_CTREE_ROW (node)->sibling)
2585 clist->focus_row = MAX (pos - 1, 0);
2587 clist->focus_row = pos;
2589 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
2591 clist->undo_anchor = clist->focus_row;
2597 list = (GList *)GTK_CTREE_NODE_PREV (work);
2599 list = (GList *)work;
2600 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
2603 if (GTK_CTREE_NODE_PREV (node) &&
2604 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2606 list = (GList *)GTK_CTREE_NODE_PREV (node);
2607 list->next = (GList *)work;
2611 parent = GTK_CTREE_ROW (node)->parent;
2614 if (GTK_CTREE_ROW (parent)->children == node)
2616 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2617 if (!GTK_CTREE_ROW (parent)->children)
2618 gtk_ctree_collapse (ctree, parent);
2622 GtkCTreeNode *sibling;
2624 sibling = GTK_CTREE_ROW (parent)->children;
2625 while (GTK_CTREE_ROW (sibling)->sibling != node)
2626 sibling = GTK_CTREE_ROW (sibling)->sibling;
2627 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2632 if (clist->row_list == (GList *)node)
2633 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
2636 GtkCTreeNode *sibling;
2638 sibling = GTK_CTREE_NODE (clist->row_list);
2639 while (GTK_CTREE_ROW (sibling)->sibling != node)
2640 sibling = GTK_CTREE_ROW (sibling)->sibling;
2641 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2647 real_tree_move (GtkCTree *ctree,
2649 GtkCTreeNode *new_parent,
2650 GtkCTreeNode *new_sibling)
2654 gboolean thaw = FALSE;
2655 gboolean visible = FALSE;
2657 g_return_if_fail (ctree != NULL);
2658 g_return_if_fail (node != NULL);
2659 g_return_if_fail (!new_sibling ||
2660 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2662 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2665 /* new_parent != child of child */
2666 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2670 clist = GTK_CLIST (ctree);
2672 visible = gtk_ctree_is_viewable (ctree, node);
2674 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2676 if (clist->anchor != -1)
2677 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2679 g_list_free (clist->undo_selection);
2680 g_list_free (clist->undo_unselection);
2681 clist->undo_selection = NULL;
2682 clist->undo_unselection = NULL;
2685 if (GTK_CLIST_AUTO_SORT (clist))
2687 if (new_parent == GTK_CTREE_ROW (node)->parent)
2691 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2693 new_sibling = GTK_CTREE_NODE (clist->row_list);
2695 while (new_sibling && clist->compare
2696 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
2697 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2700 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2701 new_sibling == GTK_CTREE_ROW (node)->sibling)
2704 if (!GTK_CLIST_FROZEN (clist))
2706 gtk_clist_freeze (clist);
2711 if (gtk_ctree_is_viewable (ctree, node) ||
2712 gtk_ctree_is_viewable (ctree, new_sibling))
2713 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2715 gtk_ctree_unlink (ctree, node, FALSE);
2716 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2720 while (work && !gtk_ctree_is_viewable (ctree, work))
2721 work = GTK_CTREE_ROW (work)->parent;
2722 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2723 clist->undo_anchor = clist->focus_row;
2726 if (clist->column[ctree->tree_column].auto_resize &&
2727 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
2728 (visible || gtk_ctree_is_viewable (ctree, node)))
2729 gtk_clist_set_column_width
2730 (clist, ctree->tree_column,
2731 gtk_clist_optimal_column_width (clist, ctree->tree_column));
2734 gtk_clist_thaw (clist);
2738 change_focus_row_expansion (GtkCTree *ctree,
2739 GtkCTreeExpansionType action)
2744 g_return_if_fail (ctree != NULL);
2745 g_return_if_fail (GTK_IS_CTREE (ctree));
2747 clist = GTK_CLIST (ctree);
2749 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2753 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2754 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2759 case GTK_CTREE_EXPANSION_EXPAND:
2760 gtk_ctree_expand (ctree, node);
2762 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2763 gtk_ctree_expand_recursive (ctree, node);
2765 case GTK_CTREE_EXPANSION_COLLAPSE:
2766 gtk_ctree_collapse (ctree, node);
2768 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2769 gtk_ctree_collapse_recursive (ctree, node);
2771 case GTK_CTREE_EXPANSION_TOGGLE:
2772 gtk_ctree_toggle_expansion (ctree, node);
2774 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2775 gtk_ctree_toggle_expansion_recursive (ctree, node);
2781 real_tree_expand (GtkCTree *ctree,
2786 GtkRequisition requisition;
2790 g_return_if_fail (ctree != NULL);
2791 g_return_if_fail (GTK_IS_CTREE (ctree));
2793 if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
2796 clist = GTK_CLIST (ctree);
2798 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2799 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2801 GTK_CTREE_ROW (node)->expanded = TRUE;
2802 level = GTK_CTREE_ROW (node)->level;
2804 visible = gtk_ctree_is_viewable (ctree, node);
2805 /* get cell width if tree_column is auto resized */
2806 if (visible && clist->column[ctree->tree_column].auto_resize &&
2807 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2808 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2809 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2811 /* unref/unset closed pixmap */
2812 if (GTK_CELL_PIXTEXT
2813 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2817 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2820 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2822 if (GTK_CELL_PIXTEXT
2823 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2827 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2829 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2833 /* set/ref opened pixmap */
2834 if (GTK_CTREE_ROW (node)->pixmap_opened)
2837 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2838 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
2840 if (GTK_CTREE_ROW (node)->mask_opened)
2842 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2843 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
2847 work = GTK_CTREE_ROW (node)->children;
2851 gint *cell_width = NULL;
2856 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2858 cell_width = g_new0 (gint, clist->columns);
2859 if (clist->column[ctree->tree_column].auto_resize)
2860 cell_width[ctree->tree_column] = requisition.width;
2863 while (GTK_CTREE_NODE_NEXT (work))
2865 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2867 /* search maximum cell widths of auto_resize columns */
2868 for (i = 0; i < clist->columns; i++)
2869 if (clist->column[i].auto_resize)
2871 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2872 (clist, >K_CTREE_ROW (work)->row, i, &requisition);
2873 cell_width[i] = MAX (requisition.width, cell_width[i]);
2877 work = GTK_CTREE_NODE_NEXT (work);
2881 list = (GList *)work;
2882 list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
2884 if (GTK_CTREE_NODE_NEXT (node))
2886 list = (GList *)GTK_CTREE_NODE_NEXT (node);
2887 list->prev = (GList *)work;
2890 clist->row_list_end = (GList *)work;
2892 list = (GList *)node;
2893 list->next = (GList *)(GTK_CTREE_ROW (node)->children);
2897 /* resize auto_resize columns if needed */
2898 for (i = 0; i < clist->columns; i++)
2899 if (clist->column[i].auto_resize &&
2900 cell_width[i] > clist->column[i].width)
2901 gtk_clist_set_column_width (clist, i, cell_width[i]);
2902 g_free (cell_width);
2904 /* update focus_row position */
2905 row = g_list_position (clist->row_list, (GList *)node);
2906 if (row < clist->focus_row)
2907 clist->focus_row += tmp + 1;
2909 clist->rows += tmp + 1;
2910 if (!GTK_CLIST_FROZEN (ctree))
2911 gtk_clist_thaw (clist);
2914 else if (visible && clist->column[ctree->tree_column].auto_resize)
2915 /* resize tree_column if needed */
2916 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2921 real_tree_collapse (GtkCTree *ctree,
2926 GtkRequisition requisition;
2930 g_return_if_fail (ctree != NULL);
2931 g_return_if_fail (GTK_IS_CTREE (ctree));
2933 if (!node || !GTK_CTREE_ROW (node)->expanded ||
2934 GTK_CTREE_ROW (node)->is_leaf)
2937 clist = GTK_CLIST (ctree);
2939 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2940 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2942 GTK_CTREE_ROW (node)->expanded = FALSE;
2943 level = GTK_CTREE_ROW (node)->level;
2945 visible = gtk_ctree_is_viewable (ctree, node);
2946 /* get cell width if tree_column is auto resized */
2947 if (visible && clist->column[ctree->tree_column].auto_resize &&
2948 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2949 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2950 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2952 /* unref/unset opened pixmap */
2953 if (GTK_CELL_PIXTEXT
2954 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2958 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2961 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2963 if (GTK_CELL_PIXTEXT
2964 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2968 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2970 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2974 /* set/ref closed pixmap */
2975 if (GTK_CTREE_ROW (node)->pixmap_closed)
2978 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2979 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed);
2981 if (GTK_CTREE_ROW (node)->mask_closed)
2983 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2984 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed);
2987 work = GTK_CTREE_ROW (node)->children;
2994 while (work && GTK_CTREE_ROW (work)->level > level)
2996 work = GTK_CTREE_NODE_NEXT (work);
3002 list = (GList *)node;
3003 list->next = (GList *)work;
3004 list = (GList *)GTK_CTREE_NODE_PREV (work);
3006 list = (GList *)work;
3007 list->prev = (GList *)node;
3011 list = (GList *)node;
3013 clist->row_list_end = (GList *)node;
3018 /* resize auto_resize columns if needed */
3019 auto_resize_columns (clist);
3021 row = g_list_position (clist->row_list, (GList *)node);
3022 if (row < clist->focus_row)
3023 clist->focus_row -= tmp;
3025 if (!GTK_CLIST_FROZEN (ctree))
3026 gtk_clist_thaw (clist);
3029 else if (visible && clist->column[ctree->tree_column].auto_resize &&
3030 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3031 /* resize tree_column if needed */
3032 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
3038 column_auto_resize (GtkCList *clist,
3039 GtkCListRow *clist_row,
3043 /* resize column if needed for auto_resize */
3044 GtkRequisition requisition;
3046 if (!clist->column[column].auto_resize ||
3047 GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3051 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3052 column, &requisition);
3054 requisition.width = 0;
3056 if (requisition.width > clist->column[column].width)
3057 gtk_clist_set_column_width (clist, column, requisition.width);
3058 else if (requisition.width < old_width &&
3059 old_width == clist->column[column].width)
3064 /* run a "gtk_clist_optimal_column_width" but break, if
3065 * the column doesn't shrink */
3066 if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
3067 new_width = (clist->column[column].button->requisition.width -
3068 (CELL_SPACING + (2 * COLUMN_INSET)));
3072 for (list = clist->row_list; list; list = list->next)
3074 GTK_CLIST_CLASS_FW (clist)->cell_size_request
3075 (clist, GTK_CLIST_ROW (list), column, &requisition);
3076 new_width = MAX (new_width, requisition.width);
3077 if (new_width == clist->column[column].width)
3080 if (new_width < clist->column[column].width)
3081 gtk_clist_set_column_width (clist, column, new_width);
3086 auto_resize_columns (GtkCList *clist)
3090 if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3093 for (i = 0; i < clist->columns; i++)
3094 column_auto_resize (clist, NULL, i, clist->column[i].width);
3098 cell_size_request (GtkCList *clist,
3099 GtkCListRow *clist_row,
3101 GtkRequisition *requisition)
3108 g_return_if_fail (clist != NULL);
3109 g_return_if_fail (GTK_IS_CTREE (clist));
3110 g_return_if_fail (requisition != NULL);
3112 ctree = GTK_CTREE (clist);
3114 get_cell_style (clist, clist_row, GTK_STATE_PRELIGHT, column, &style,
3117 switch (clist_row->cell[column].type)
3120 requisition->width =
3121 gdk_string_width (style->font,
3122 GTK_CELL_TEXT (clist_row->cell[column])->text);
3123 requisition->height = style->font->ascent + style->font->descent;
3125 case GTK_CELL_PIXTEXT:
3126 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
3128 gdk_window_get_size (GTK_CELL_PIXTEXT
3129 (clist_row->cell[column])->pixmap,
3131 width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
3136 requisition->width = width +
3137 gdk_string_width (style->font,
3138 GTK_CELL_TEXT (clist_row->cell[column])->text);
3140 requisition->height = MAX (style->font->ascent + style->font->descent,
3142 if (column == ctree->tree_column)
3144 requisition->width += (ctree->tree_spacing + ctree->tree_indent *
3145 (((GtkCTreeRow *) clist_row)->level - 1));
3146 switch (ctree->expander_style)
3148 case GTK_CTREE_EXPANDER_NONE:
3150 case GTK_CTREE_EXPANDER_TRIANGLE:
3151 requisition->width += PM_SIZE + 3;
3153 case GTK_CTREE_EXPANDER_SQUARE:
3154 case GTK_CTREE_EXPANDER_CIRCULAR:
3155 requisition->width += PM_SIZE + 1;
3158 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
3159 requisition->width += 3;
3162 case GTK_CELL_PIXMAP:
3163 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
3165 requisition->width = width;
3166 requisition->height = height;
3169 requisition->width = 0;
3170 requisition->height = 0;
3174 requisition->width += clist_row->cell[column].horizontal;
3175 requisition->height += clist_row->cell[column].vertical;
3179 set_cell_contents (GtkCList *clist,
3180 GtkCListRow *clist_row,
3188 gboolean visible = FALSE;
3190 GtkRequisition requisition;
3192 g_return_if_fail (clist != NULL);
3193 g_return_if_fail (GTK_IS_CTREE (clist));
3194 g_return_if_fail (clist_row != NULL);
3196 ctree = GTK_CTREE (clist);
3198 if (clist->column[column].auto_resize &&
3199 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3201 GtkCTreeNode *parent;
3203 parent = ((GtkCTreeRow *)clist_row)->parent;
3204 if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded &&
3205 gtk_ctree_is_viewable (ctree, parent)))
3208 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3209 column, &requisition);
3213 switch (clist_row->cell[column].type)
3215 case GTK_CELL_EMPTY:
3219 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3221 case GTK_CELL_PIXMAP:
3222 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3223 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3224 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3226 case GTK_CELL_PIXTEXT:
3227 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
3228 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3229 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
3232 (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3233 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3235 (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3238 case GTK_CELL_WIDGET:
3246 clist_row->cell[column].type = GTK_CELL_EMPTY;
3247 if (column == ctree->tree_column && type != GTK_CELL_EMPTY)
3248 type = GTK_CELL_PIXTEXT;
3255 clist_row->cell[column].type = GTK_CELL_TEXT;
3256 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3259 case GTK_CELL_PIXMAP:
3262 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3263 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3264 /* We set the mask even if it is NULL */
3265 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3268 case GTK_CELL_PIXTEXT:
3269 if (column == ctree->tree_column)
3271 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3272 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3274 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3276 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL;
3279 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3280 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3284 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
3285 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
3288 else if (text && pixmap)
3290 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3291 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3292 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3293 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3294 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3302 column_auto_resize (clist, clist_row, column, requisition.width);
3306 set_node_info (GtkCTree *ctree,
3310 GdkPixmap *pixmap_closed,
3311 GdkBitmap *mask_closed,
3312 GdkPixmap *pixmap_opened,
3313 GdkBitmap *mask_opened,
3317 if (GTK_CTREE_ROW (node)->pixmap_opened)
3319 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3320 if (GTK_CTREE_ROW (node)->mask_opened)
3321 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3323 if (GTK_CTREE_ROW (node)->pixmap_closed)
3325 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3326 if (GTK_CTREE_ROW (node)->mask_closed)
3327 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3330 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3331 GTK_CTREE_ROW (node)->mask_opened = NULL;
3332 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3333 GTK_CTREE_ROW (node)->mask_closed = NULL;
3337 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3339 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3343 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3345 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3348 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3349 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3351 if (GTK_CTREE_ROW (node)->expanded)
3352 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3353 text, spacing, pixmap_opened, mask_opened);
3355 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3356 text, spacing, pixmap_closed, mask_closed);
3360 tree_delete (GtkCTree *ctree,
3366 clist = GTK_CLIST (ctree);
3368 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3372 work = g_list_find (clist->selection, node);
3375 if (clist->selection_end && clist->selection_end == work)
3376 clist->selection_end = clist->selection_end->prev;
3377 clist->selection = g_list_remove (clist->selection, node);
3381 row_delete (ctree, GTK_CTREE_ROW (node));
3382 g_list_free_1 ((GList *)node);
3386 tree_delete_row (GtkCTree *ctree,
3390 row_delete (ctree, GTK_CTREE_ROW (node));
3391 g_list_free_1 ((GList *)node);
3395 tree_update_level (GtkCTree *ctree,
3402 if (GTK_CTREE_ROW (node)->parent)
3403 GTK_CTREE_ROW (node)->level =
3404 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3406 GTK_CTREE_ROW (node)->level = 1;
3410 tree_select (GtkCTree *ctree,
3414 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
3415 GTK_CTREE_ROW (node)->row.selectable)
3416 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3421 tree_unselect (GtkCTree *ctree,
3425 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3426 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3431 tree_expand (GtkCTree *ctree,
3435 if (node && !GTK_CTREE_ROW (node)->expanded)
3436 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3440 tree_collapse (GtkCTree *ctree,
3444 if (node && GTK_CTREE_ROW (node)->expanded)
3445 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3449 tree_collapse_to_depth (GtkCTree *ctree,
3453 if (node && GTK_CTREE_ROW (node)->level == depth)
3454 gtk_ctree_collapse_recursive (ctree, node);
3458 tree_toggle_expansion (GtkCTree *ctree,
3465 if (GTK_CTREE_ROW (node)->expanded)
3466 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3468 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3471 static GtkCTreeRow *
3472 row_new (GtkCTree *ctree)
3475 GtkCTreeRow *ctree_row;
3478 clist = GTK_CLIST (ctree);
3479 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3480 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3482 for (i = 0; i < clist->columns; i++)
3484 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3485 ctree_row->row.cell[i].vertical = 0;
3486 ctree_row->row.cell[i].horizontal = 0;
3487 ctree_row->row.cell[i].style = NULL;
3490 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3492 ctree_row->row.fg_set = FALSE;
3493 ctree_row->row.bg_set = FALSE;
3494 ctree_row->row.style = NULL;
3495 ctree_row->row.selectable = TRUE;
3496 ctree_row->row.state = GTK_STATE_NORMAL;
3497 ctree_row->row.data = NULL;
3498 ctree_row->row.destroy = NULL;
3500 ctree_row->level = 0;
3501 ctree_row->expanded = FALSE;
3502 ctree_row->parent = NULL;
3503 ctree_row->sibling = NULL;
3504 ctree_row->children = NULL;
3505 ctree_row->pixmap_closed = NULL;
3506 ctree_row->mask_closed = NULL;
3507 ctree_row->pixmap_opened = NULL;
3508 ctree_row->mask_opened = NULL;
3514 row_delete (GtkCTree *ctree,
3515 GtkCTreeRow *ctree_row)
3520 clist = GTK_CLIST (ctree);
3522 for (i = 0; i < clist->columns; i++)
3524 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3525 (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
3526 if (ctree_row->row.cell[i].style)
3528 if (GTK_WIDGET_REALIZED (ctree))
3529 gtk_style_detach (ctree_row->row.cell[i].style);
3530 gtk_style_unref (ctree_row->row.cell[i].style);
3534 if (ctree_row->row.style)
3536 if (GTK_WIDGET_REALIZED (ctree))
3537 gtk_style_detach (ctree_row->row.style);
3538 gtk_style_unref (ctree_row->row.style);
3541 if (ctree_row->pixmap_closed)
3543 gdk_pixmap_unref (ctree_row->pixmap_closed);
3544 if (ctree_row->mask_closed)
3545 gdk_bitmap_unref (ctree_row->mask_closed);
3548 if (ctree_row->pixmap_opened)
3550 gdk_pixmap_unref (ctree_row->pixmap_opened);
3551 if (ctree_row->mask_opened)
3552 gdk_bitmap_unref (ctree_row->mask_opened);
3555 if (ctree_row->row.destroy)
3556 ctree_row->row.destroy (ctree_row->row.data);
3558 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3559 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3563 real_select_row (GtkCList *clist,
3570 g_return_if_fail (clist != NULL);
3571 g_return_if_fail (GTK_IS_CTREE (clist));
3573 if ((node = g_list_nth (clist->row_list, row)) &&
3574 GTK_CTREE_ROW (node)->row.selectable)
3575 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3580 real_unselect_row (GtkCList *clist,
3587 g_return_if_fail (clist != NULL);
3588 g_return_if_fail (GTK_IS_CTREE (clist));
3590 if ((node = g_list_nth (clist->row_list, row)))
3591 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3596 real_tree_select (GtkCTree *ctree,
3602 GtkCTreeNode *sel_row;
3603 gboolean node_selected;
3605 g_return_if_fail (ctree != NULL);
3606 g_return_if_fail (GTK_IS_CTREE (ctree));
3608 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3609 !GTK_CTREE_ROW (node)->row.selectable)
3612 clist = GTK_CLIST (ctree);
3614 switch (clist->selection_mode)
3616 case GTK_SELECTION_SINGLE:
3617 case GTK_SELECTION_BROWSE:
3619 node_selected = FALSE;
3620 list = clist->selection;
3624 sel_row = list->data;
3627 if (node == sel_row)
3628 node_selected = TRUE;
3630 gtk_signal_emit (GTK_OBJECT (ctree),
3631 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3641 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3643 if (!clist->selection)
3645 clist->selection = g_list_append (clist->selection, node);
3646 clist->selection_end = clist->selection;
3649 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3651 tree_draw_node (ctree, node);
3655 real_tree_unselect (GtkCTree *ctree,
3661 g_return_if_fail (ctree != NULL);
3662 g_return_if_fail (GTK_IS_CTREE (ctree));
3664 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3667 clist = GTK_CLIST (ctree);
3669 if (clist->selection_end && clist->selection_end->data == node)
3670 clist->selection_end = clist->selection_end->prev;
3672 clist->selection = g_list_remove (clist->selection, node);
3674 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3676 tree_draw_node (ctree, node);
3680 tree_toggle_selection (GtkCTree *ctree,
3686 g_return_if_fail (ctree != NULL);
3687 g_return_if_fail (GTK_IS_CTREE (ctree));
3689 clist = GTK_CLIST (ctree);
3691 switch (clist->selection_mode)
3693 case GTK_SELECTION_SINGLE:
3694 case GTK_SELECTION_MULTIPLE:
3695 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3696 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3698 else if (node && GTK_CTREE_ROW (node)->row.selectable)
3699 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3703 case GTK_SELECTION_BROWSE:
3704 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL &&
3705 GTK_CTREE_ROW (node)->row.selectable)
3706 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3710 case GTK_SELECTION_EXTENDED:
3716 select_row_recursive (GtkCTree *ctree,
3720 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3721 !GTK_CTREE_ROW (node)->row.selectable)
3724 GTK_CLIST (ctree)->undo_unselection =
3725 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3726 gtk_ctree_select (ctree, node);
3730 real_select_all (GtkCList *clist)
3734 gboolean thaw = FALSE;
3736 g_return_if_fail (clist != NULL);
3737 g_return_if_fail (GTK_IS_CTREE (clist));
3739 ctree = GTK_CTREE (clist);
3741 switch (clist->selection_mode)
3743 case GTK_SELECTION_SINGLE:
3744 case GTK_SELECTION_BROWSE:
3747 case GTK_SELECTION_EXTENDED:
3749 if (!GTK_CLIST_FROZEN (clist))
3751 gtk_clist_freeze (clist);
3755 g_list_free (clist->undo_selection);
3756 g_list_free (clist->undo_unselection);
3757 clist->undo_selection = NULL;
3758 clist->undo_unselection = NULL;
3760 clist->anchor_state = GTK_STATE_SELECTED;
3762 clist->drag_pos = -1;
3763 clist->undo_anchor = clist->focus_row;
3765 for (node = GTK_CTREE_NODE (clist->row_list); node;
3766 node = GTK_CTREE_NODE_NEXT (node))
3767 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3770 gtk_clist_thaw (clist);
3773 case GTK_SELECTION_MULTIPLE:
3774 gtk_ctree_select_recursive (ctree, NULL);
3780 real_unselect_all (GtkCList *clist)
3786 g_return_if_fail (clist != NULL);
3787 g_return_if_fail (GTK_IS_CTREE (clist));
3789 ctree = GTK_CTREE (clist);
3791 switch (clist->selection_mode)
3793 case GTK_SELECTION_BROWSE:
3794 if (clist->focus_row >= 0)
3798 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3803 case GTK_SELECTION_EXTENDED:
3804 g_list_free (clist->undo_selection);
3805 g_list_free (clist->undo_unselection);
3806 clist->undo_selection = NULL;
3807 clist->undo_unselection = NULL;
3810 clist->drag_pos = -1;
3811 clist->undo_anchor = clist->focus_row;
3818 list = clist->selection;
3824 gtk_ctree_unselect (ctree, node);
3829 ctree_is_hot_spot (GtkCTree *ctree,
3835 GtkCTreeRow *tree_row;
3837 GtkCellPixText *cell;
3841 g_return_val_if_fail (ctree != NULL, FALSE);
3842 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3843 g_return_val_if_fail (node != NULL, FALSE);
3845 clist = GTK_CLIST (ctree);
3847 if (!clist->column[ctree->tree_column].visible ||
3848 ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
3851 tree_row = GTK_CTREE_ROW (node);
3853 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3855 yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
3856 (clist->row_height - 1) % 2);
3858 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3859 xl = (clist->column[ctree->tree_column].area.x +
3860 clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
3861 (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
3862 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3864 xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
3865 (tree_row->level - 1) * ctree->tree_indent +
3866 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3868 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3871 /***********************************************************
3872 ***********************************************************
3873 *** Public interface ***
3874 ***********************************************************
3875 ***********************************************************/
3878 /***********************************************************
3879 * Creation, insertion, deletion *
3880 ***********************************************************/
3883 gtk_ctree_construct (GtkCTree *ctree,
3890 g_return_if_fail (ctree != NULL);
3891 g_return_if_fail (GTK_IS_CTREE (ctree));
3892 g_return_if_fail (GTK_OBJECT_CONSTRUCTED (ctree) == FALSE);
3894 clist = GTK_CLIST (ctree);
3896 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
3897 sizeof (GtkCTreeRow),
3898 sizeof (GtkCTreeRow)
3899 * CLIST_OPTIMUM_SIZE,
3902 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
3903 sizeof (GtkCell) * columns,
3904 sizeof (GtkCell) * columns
3905 * CLIST_OPTIMUM_SIZE,
3908 ctree->tree_column = tree_column;
3910 gtk_clist_construct (clist, columns, titles);
3914 gtk_ctree_new_with_titles (gint columns,
3920 g_return_val_if_fail (columns > 0, NULL);
3921 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3923 widget = gtk_type_new (GTK_TYPE_CTREE);
3924 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
3930 gtk_ctree_new (gint columns,
3933 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3937 real_insert_row (GtkCList *clist,
3941 GtkCTreeNode *parent = NULL;
3942 GtkCTreeNode *sibling;
3945 g_return_val_if_fail (clist != NULL, -1);
3946 g_return_val_if_fail (GTK_IS_CTREE (clist), -1);
3948 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3950 parent = GTK_CTREE_ROW (sibling)->parent;
3952 node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5,
3953 NULL, NULL, NULL, NULL, TRUE, FALSE);
3955 if (GTK_CLIST_AUTO_SORT (clist) || !sibling)
3956 return g_list_position (clist->row_list, (GList *) node);
3962 gtk_ctree_insert_node (GtkCTree *ctree,
3963 GtkCTreeNode *parent,
3964 GtkCTreeNode *sibling,
3967 GdkPixmap *pixmap_closed,
3968 GdkBitmap *mask_closed,
3969 GdkPixmap *pixmap_opened,
3970 GdkBitmap *mask_opened,
3975 GtkCTreeRow *new_row;
3980 g_return_val_if_fail (ctree != NULL, NULL);
3981 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3983 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3985 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
3988 clist = GTK_CLIST (ctree);
3990 /* create the row */
3991 new_row = row_new (ctree);
3992 list = g_list_alloc ();
3993 list->data = new_row;
3994 node = GTK_CTREE_NODE (list);
3997 for (i = 0; i < clist->columns; i++)
3998 if (text[i] && i != ctree->tree_column)
3999 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4000 (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
4002 set_node_info (ctree, node, text ?
4003 text[ctree->tree_column] : NULL, spacing, pixmap_closed,
4004 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
4006 /* sorted insertion */
4007 if (GTK_CLIST_AUTO_SORT (clist))
4010 sibling = GTK_CTREE_ROW (parent)->children;
4012 sibling = GTK_CTREE_NODE (clist->row_list);
4014 while (sibling && clist->compare
4015 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
4016 sibling = GTK_CTREE_ROW (sibling)->sibling;
4019 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
4021 if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
4022 gtk_ctree_is_viewable (ctree, node))
4024 for (i = 0; i < clist->columns; i++)
4025 if (clist->column[i].auto_resize)
4026 column_auto_resize (clist, &(new_row->row), i, 0);
4029 if (!GTK_CLIST_FROZEN (clist))
4030 gtk_clist_thaw (clist);
4036 gtk_ctree_insert_gnode (GtkCTree *ctree,
4037 GtkCTreeNode *parent,
4038 GtkCTreeNode *sibling,
4040 GtkCTreeGNodeFunc func,
4044 GtkCTreeNode *cnode = NULL;
4045 GtkCTreeNode *child = NULL;
4046 GtkCTreeNode *new_child;
4052 g_return_val_if_fail (ctree != NULL, NULL);
4053 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4054 g_return_val_if_fail (gnode != NULL, NULL);
4055 g_return_val_if_fail (func != NULL, NULL);
4057 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
4059 clist = GTK_CLIST (ctree);
4062 depth = GTK_CTREE_ROW (parent)->level + 1;
4064 list = g_list_alloc ();
4065 list->data = row_new (ctree);
4066 cnode = GTK_CTREE_NODE (list);
4068 thaw = !GTK_CLIST_FROZEN (clist);
4070 gtk_clist_freeze (clist);
4072 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
4074 if (!func (ctree, depth, gnode, cnode, data))
4076 tree_delete_row (ctree, cnode, NULL);
4080 if (GTK_CLIST_AUTO_SORT (clist))
4083 sibling = GTK_CTREE_ROW (parent)->children;
4085 sibling = GTK_CTREE_NODE (clist->row_list);
4087 while (sibling && clist->compare
4088 (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
4089 sibling = GTK_CTREE_ROW (sibling)->sibling;
4092 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
4094 for (work = g_node_last_child (gnode); work; work = work->prev)
4096 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
4103 gtk_clist_thaw (clist);
4109 gtk_ctree_export_to_gnode (GtkCTree *ctree,
4113 GtkCTreeGNodeFunc func,
4121 g_return_val_if_fail (ctree != NULL, NULL);
4122 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4123 g_return_val_if_fail (node != NULL, NULL);
4124 g_return_val_if_fail (func != NULL, NULL);
4127 g_return_val_if_fail (parent != NULL, NULL);
4128 g_return_val_if_fail (sibling->parent == parent, NULL);
4131 gnode = g_node_new (NULL);
4132 depth = g_node_depth (parent) + 1;
4134 if (!func (ctree, depth, gnode, node, data))
4136 g_node_destroy (gnode);
4141 g_node_insert_before (parent, sibling, gnode);
4143 for (work = GTK_CTREE_ROW (node)->children, new_sibling = NULL; work;
4144 work = GTK_CTREE_NODE_NEXT (work))
4146 sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling,
4149 new_sibling = sibling;
4151 g_node_reverse_children (gnode);
4157 real_remove_row (GtkCList *clist,
4162 g_return_if_fail (clist != NULL);
4163 g_return_if_fail (GTK_IS_CTREE (clist));
4165 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
4168 gtk_ctree_remove_node (GTK_CTREE (clist), node);
4172 gtk_ctree_remove_node (GtkCTree *ctree,
4176 gboolean thaw = FALSE;
4178 g_return_if_fail (ctree != NULL);
4179 g_return_if_fail (GTK_IS_CTREE (ctree));
4181 clist = GTK_CLIST (ctree);
4183 if (!GTK_CLIST_FROZEN (clist))
4185 gtk_clist_freeze (clist);
4193 visible = gtk_ctree_is_viewable (ctree, node);
4194 gtk_ctree_unlink (ctree, node, TRUE);
4195 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
4197 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
4198 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
4199 !clist->selection && clist->focus_row >= 0)
4200 gtk_clist_select_row (clist, clist->focus_row, -1);
4202 auto_resize_columns (clist);
4205 gtk_clist_clear (clist);
4208 gtk_clist_thaw (clist);
4212 real_clear (GtkCList *clist)
4218 g_return_if_fail (clist != NULL);
4219 g_return_if_fail (GTK_IS_CTREE (clist));
4221 ctree = GTK_CTREE (clist);
4223 ctree->drag_row = -1;
4224 ctree->drag_rect = FALSE;
4225 ctree->in_drag = FALSE;
4226 ctree->drag_source = NULL;
4227 ctree->drag_target = NULL;
4228 ctree->drag_icon = NULL;
4230 /* remove all rows */
4231 work = GTK_CTREE_NODE (clist->row_list);
4232 clist->row_list = NULL;
4233 clist->row_list_end = NULL;
4235 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4239 work = GTK_CTREE_ROW (work)->sibling;
4240 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
4243 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4245 (parent_class->clear) (clist);
4249 /***********************************************************
4250 * Generic recursive functions, querying / finding tree *
4252 ***********************************************************/
4256 gtk_ctree_post_recursive (GtkCTree *ctree,
4264 g_return_if_fail (ctree != NULL);
4265 g_return_if_fail (GTK_IS_CTREE (ctree));
4266 g_return_if_fail (func != NULL);
4269 work = GTK_CTREE_ROW (node)->children;
4271 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4275 tmp = GTK_CTREE_ROW (work)->sibling;
4276 gtk_ctree_post_recursive (ctree, work, func, data);
4281 func (ctree, node, data);
4285 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
4294 g_return_if_fail (ctree != NULL);
4295 g_return_if_fail (GTK_IS_CTREE (ctree));
4296 g_return_if_fail (func != NULL);
4300 gtk_ctree_post_recursive (ctree, node, func, data);
4305 work = GTK_CTREE_ROW (node)->children;
4307 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4309 if (work && GTK_CTREE_ROW (work)->level <= depth)
4313 tmp = GTK_CTREE_ROW (work)->sibling;
4314 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
4319 if (node && GTK_CTREE_ROW (node)->level <= depth)
4320 func (ctree, node, data);
4324 gtk_ctree_pre_recursive (GtkCTree *ctree,
4332 g_return_if_fail (ctree != NULL);
4333 g_return_if_fail (GTK_IS_CTREE (ctree));
4334 g_return_if_fail (func != NULL);
4338 work = GTK_CTREE_ROW (node)->children;
4339 func (ctree, node, data);
4342 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4346 tmp = GTK_CTREE_ROW (work)->sibling;
4347 gtk_ctree_pre_recursive (ctree, work, func, data);
4353 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4362 g_return_if_fail (ctree != NULL);
4363 g_return_if_fail (GTK_IS_CTREE (ctree));
4364 g_return_if_fail (func != NULL);
4368 gtk_ctree_pre_recursive (ctree, node, func, data);
4374 work = GTK_CTREE_ROW (node)->children;
4375 if (GTK_CTREE_ROW (node)->level <= depth)
4376 func (ctree, node, data);
4379 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4381 if (work && GTK_CTREE_ROW (work)->level <= depth)
4385 tmp = GTK_CTREE_ROW (work)->sibling;
4386 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4393 gtk_ctree_is_viewable (GtkCTree *ctree,
4398 g_return_val_if_fail (ctree != NULL, FALSE);
4399 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4400 g_return_val_if_fail (node != NULL, FALSE);
4402 work = GTK_CTREE_ROW (node);
4404 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4405 work = GTK_CTREE_ROW (work->parent);
4414 gtk_ctree_last (GtkCTree *ctree,
4417 g_return_val_if_fail (ctree != NULL, NULL);
4418 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4423 while (GTK_CTREE_ROW (node)->sibling)
4424 node = GTK_CTREE_ROW (node)->sibling;
4426 if (GTK_CTREE_ROW (node)->children)
4427 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4433 gtk_ctree_find_node_ptr (GtkCTree *ctree,
4434 GtkCTreeRow *ctree_row)
4438 g_return_val_if_fail (ctree != NULL, FALSE);
4439 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4440 g_return_val_if_fail (ctree_row != NULL, FALSE);
4442 if (ctree_row->parent)
4443 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4445 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4447 while (GTK_CTREE_ROW (node) != ctree_row)
4448 node = GTK_CTREE_ROW (node)->sibling;
4454 gtk_ctree_node_nth (GtkCTree *ctree,
4457 g_return_val_if_fail (ctree != NULL, NULL);
4458 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4460 if ((row < 0) || (row >= GTK_CLIST(ctree)->rows))
4463 return GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
4467 gtk_ctree_find (GtkCTree *ctree,
4469 GtkCTreeNode *child)
4475 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4481 if (GTK_CTREE_ROW (node)->children)
4483 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4486 node = GTK_CTREE_ROW (node)->sibling;
4492 gtk_ctree_is_ancestor (GtkCTree *ctree,
4494 GtkCTreeNode *child)
4496 g_return_val_if_fail (node != NULL, FALSE);
4498 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4502 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4509 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4513 if (GTK_CTREE_ROW (node)->row.data == data)
4515 if (GTK_CTREE_ROW (node)->children &&
4516 (work = gtk_ctree_find_by_row_data
4517 (ctree, GTK_CTREE_ROW (node)->children, data)))
4519 node = GTK_CTREE_ROW (node)->sibling;
4525 gtk_ctree_find_all_by_row_data (GtkCTree *ctree,
4531 g_return_val_if_fail (ctree != NULL, NULL);
4532 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4534 /* if node == NULL then look in the whole tree */
4536 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4540 if (GTK_CTREE_ROW (node)->row.data == data)
4541 list = g_list_append (list, node);
4543 if (GTK_CTREE_ROW (node)->children)
4547 sub_list = gtk_ctree_find_all_by_row_data (ctree,
4551 list = g_list_concat (list, sub_list);
4553 node = GTK_CTREE_ROW (node)->sibling;
4559 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4566 g_return_val_if_fail (func != NULL, NULL);
4569 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4573 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4575 if (GTK_CTREE_ROW (node)->children &&
4576 (work = gtk_ctree_find_by_row_data_custom
4577 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4579 node = GTK_CTREE_ROW (node)->sibling;
4585 gtk_ctree_find_all_by_row_data_custom (GtkCTree *ctree,
4592 g_return_val_if_fail (ctree != NULL, NULL);
4593 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4594 g_return_val_if_fail (func != NULL, NULL);
4596 /* if node == NULL then look in the whole tree */
4598 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4602 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4603 list = g_list_append (list, node);
4605 if (GTK_CTREE_ROW (node)->children)
4609 sub_list = gtk_ctree_find_all_by_row_data_custom (ctree,
4614 list = g_list_concat (list, sub_list);
4616 node = GTK_CTREE_ROW (node)->sibling;
4622 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4630 g_return_val_if_fail (ctree != NULL, FALSE);
4631 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4633 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4634 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4635 return ctree_is_hot_spot (ctree, node, row, x, y);
4641 /***********************************************************
4642 * Tree signals : move, expand, collapse, (un)select *
4643 ***********************************************************/
4647 gtk_ctree_move (GtkCTree *ctree,
4649 GtkCTreeNode *new_parent,
4650 GtkCTreeNode *new_sibling)
4652 g_return_if_fail (ctree != NULL);
4653 g_return_if_fail (GTK_IS_CTREE (ctree));
4654 g_return_if_fail (node != NULL);
4656 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4657 new_parent, new_sibling);
4661 gtk_ctree_expand (GtkCTree *ctree,
4664 g_return_if_fail (ctree != NULL);
4665 g_return_if_fail (GTK_IS_CTREE (ctree));
4666 g_return_if_fail (node != NULL);
4668 if (GTK_CTREE_ROW (node)->is_leaf)
4671 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4675 gtk_ctree_expand_recursive (GtkCTree *ctree,
4679 gboolean thaw = FALSE;
4681 g_return_if_fail (ctree != NULL);
4682 g_return_if_fail (GTK_IS_CTREE (ctree));
4684 clist = GTK_CLIST (ctree);
4686 if (node && GTK_CTREE_ROW (node)->is_leaf)
4689 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4690 !GTK_CLIST_FROZEN (clist))
4692 gtk_clist_freeze (clist);
4696 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4699 gtk_clist_thaw (clist);
4703 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4708 gboolean thaw = FALSE;
4710 g_return_if_fail (ctree != NULL);
4711 g_return_if_fail (GTK_IS_CTREE (ctree));
4713 clist = GTK_CLIST (ctree);
4715 if (node && GTK_CTREE_ROW (node)->is_leaf)
4718 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4719 !GTK_CLIST_FROZEN (clist))
4721 gtk_clist_freeze (clist);
4725 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4726 GTK_CTREE_FUNC (tree_expand), NULL);
4729 gtk_clist_thaw (clist);
4733 gtk_ctree_collapse (GtkCTree *ctree,
4736 g_return_if_fail (ctree != NULL);
4737 g_return_if_fail (GTK_IS_CTREE (ctree));
4738 g_return_if_fail (node != NULL);
4740 if (GTK_CTREE_ROW (node)->is_leaf)
4743 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4747 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4751 gboolean thaw = FALSE;
4754 g_return_if_fail (ctree != NULL);
4755 g_return_if_fail (GTK_IS_CTREE (ctree));
4757 if (node && GTK_CTREE_ROW (node)->is_leaf)
4760 clist = GTK_CLIST (ctree);
4762 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4763 !GTK_CLIST_FROZEN (clist))
4765 gtk_clist_freeze (clist);
4769 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4770 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4771 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4772 for (i = 0; i < clist->columns; i++)
4773 if (clist->column[i].auto_resize)
4774 gtk_clist_set_column_width (clist, i,
4775 gtk_clist_optimal_column_width (clist, i));
4778 gtk_clist_thaw (clist);
4782 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4787 gboolean thaw = FALSE;
4790 g_return_if_fail (ctree != NULL);
4791 g_return_if_fail (GTK_IS_CTREE (ctree));
4793 if (node && GTK_CTREE_ROW (node)->is_leaf)
4796 clist = GTK_CLIST (ctree);
4798 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4799 !GTK_CLIST_FROZEN (clist))
4801 gtk_clist_freeze (clist);
4805 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4806 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4807 GTK_CTREE_FUNC (tree_collapse_to_depth),
4808 GINT_TO_POINTER (depth));
4809 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4810 for (i = 0; i < clist->columns; i++)
4811 if (clist->column[i].auto_resize)
4812 gtk_clist_set_column_width (clist, i,
4813 gtk_clist_optimal_column_width (clist, i));
4816 gtk_clist_thaw (clist);
4820 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4823 g_return_if_fail (ctree != NULL);
4824 g_return_if_fail (GTK_IS_CTREE (ctree));
4825 g_return_if_fail (node != NULL);
4827 if (GTK_CTREE_ROW (node)->is_leaf)
4830 tree_toggle_expansion (ctree, node, NULL);
4834 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4838 gboolean thaw = FALSE;
4840 g_return_if_fail (ctree != NULL);
4841 g_return_if_fail (GTK_IS_CTREE (ctree));
4843 if (node && GTK_CTREE_ROW (node)->is_leaf)
4846 clist = GTK_CLIST (ctree);
4848 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4849 !GTK_CLIST_FROZEN (clist))
4851 gtk_clist_freeze (clist);
4855 gtk_ctree_post_recursive (ctree, node,
4856 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4859 gtk_clist_thaw (clist);
4863 gtk_ctree_select (GtkCTree *ctree,
4866 g_return_if_fail (ctree != NULL);
4867 g_return_if_fail (GTK_IS_CTREE (ctree));
4868 g_return_if_fail (node != NULL);
4870 if (GTK_CTREE_ROW (node)->row.selectable)
4871 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4876 gtk_ctree_unselect (GtkCTree *ctree,
4879 g_return_if_fail (ctree != NULL);
4880 g_return_if_fail (GTK_IS_CTREE (ctree));
4881 g_return_if_fail (node != NULL);
4883 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4888 gtk_ctree_select_recursive (GtkCTree *ctree,
4891 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4895 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4898 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4902 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4907 gboolean thaw = FALSE;
4909 g_return_if_fail (ctree != NULL);
4910 g_return_if_fail (GTK_IS_CTREE (ctree));
4912 clist = GTK_CLIST (ctree);
4915 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4916 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4917 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4920 if (((node && gtk_ctree_is_viewable (ctree, node)) || !node) &&
4921 !GTK_CLIST_FROZEN (clist))
4923 gtk_clist_freeze (clist);
4927 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4929 if (clist->anchor != -1)
4930 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4932 g_list_free (clist->undo_selection);
4933 g_list_free (clist->undo_unselection);
4934 clist->undo_selection = NULL;
4935 clist->undo_unselection = NULL;
4939 gtk_ctree_post_recursive (ctree, node,
4940 GTK_CTREE_FUNC (tree_select), NULL);
4942 gtk_ctree_post_recursive (ctree, node,
4943 GTK_CTREE_FUNC (tree_unselect), NULL);
4946 gtk_clist_thaw (clist);
4950 /***********************************************************
4951 * Analogons of GtkCList functions *
4952 ***********************************************************/
4956 gtk_ctree_node_set_text (GtkCTree *ctree,
4963 g_return_if_fail (ctree != NULL);
4964 g_return_if_fail (GTK_IS_CTREE (ctree));
4965 g_return_if_fail (node != NULL);
4967 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4970 clist = GTK_CLIST (ctree);
4972 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4973 (clist, &(GTK_CTREE_ROW(node)->row), column, GTK_CELL_TEXT,
4974 text, 0, NULL, NULL);
4976 tree_draw_node (ctree, node);
4980 gtk_ctree_node_set_pixmap (GtkCTree *ctree,
4988 g_return_if_fail (ctree != NULL);
4989 g_return_if_fail (GTK_IS_CTREE (ctree));
4990 g_return_if_fail (node != NULL);
4991 g_return_if_fail (pixmap != NULL);
4993 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4996 gdk_pixmap_ref (pixmap);
4998 gdk_pixmap_ref (mask);
5000 clist = GTK_CLIST (ctree);
5002 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
5003 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP,
5004 NULL, 0, pixmap, mask);
5006 tree_draw_node (ctree, node);
5010 gtk_ctree_node_set_pixtext (GtkCTree *ctree,
5020 g_return_if_fail (ctree != NULL);
5021 g_return_if_fail (GTK_IS_CTREE (ctree));
5022 g_return_if_fail (node != NULL);
5023 if (column != ctree->tree_column)
5024 g_return_if_fail (pixmap != NULL);
5025 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5028 clist = GTK_CLIST (ctree);
5032 gdk_pixmap_ref (pixmap);
5034 gdk_pixmap_ref (mask);
5037 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
5038 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT,
5039 text, spacing, pixmap, mask);
5041 tree_draw_node (ctree, node);
5045 gtk_ctree_set_node_info (GtkCTree *ctree,
5049 GdkPixmap *pixmap_closed,
5050 GdkBitmap *mask_closed,
5051 GdkPixmap *pixmap_opened,
5052 GdkBitmap *mask_opened,
5057 gboolean old_expanded;
5059 g_return_if_fail (ctree != NULL);
5060 g_return_if_fail (GTK_IS_CTREE (ctree));
5061 g_return_if_fail (node != NULL);
5063 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
5064 old_expanded = GTK_CTREE_ROW (node)->expanded;
5066 if (is_leaf && GTK_CTREE_ROW (node)->children)
5071 work = GTK_CTREE_ROW (node)->children;
5075 work = GTK_CTREE_ROW(work)->sibling;
5076 gtk_ctree_remove_node (ctree, ptr);
5080 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
5081 pixmap_opened, mask_opened, is_leaf, expanded);
5083 if (!is_leaf && !old_leaf)
5085 GTK_CTREE_ROW (node)->expanded = old_expanded;
5086 if (expanded && !old_expanded)
5087 gtk_ctree_expand (ctree, node);
5088 else if (!expanded && old_expanded)
5089 gtk_ctree_collapse (ctree, node);
5092 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
5094 tree_draw_node (ctree, node);
5098 gtk_ctree_node_set_shift (GtkCTree *ctree,
5105 GtkRequisition requisition;
5106 gboolean visible = FALSE;
5108 g_return_if_fail (ctree != NULL);
5109 g_return_if_fail (GTK_IS_CTREE (ctree));
5110 g_return_if_fail (node != NULL);
5112 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5115 clist = GTK_CLIST (ctree);
5117 if (clist->column[column].auto_resize &&
5118 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5120 visible = gtk_ctree_is_viewable (ctree, node);
5122 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5123 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5126 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
5127 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
5130 column_auto_resize (clist, >K_CTREE_ROW (node)->row,
5131 column, requisition.width);
5133 tree_draw_node (ctree, node);
5137 gtk_ctree_node_set_selectable (GtkCTree *ctree,
5139 gboolean selectable)
5141 g_return_if_fail (ctree != NULL);
5142 g_return_if_fail (GTK_IS_CTREE (ctree));
5143 g_return_if_fail (node != NULL);
5145 if (selectable == GTK_CTREE_ROW (node)->row.selectable)
5148 GTK_CTREE_ROW (node)->row.selectable = selectable;
5150 if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5154 clist = GTK_CLIST (ctree);
5156 if (clist->anchor >= 0 &&
5157 clist->selection_mode == GTK_SELECTION_EXTENDED)
5159 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
5161 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
5162 gtk_grab_remove (GTK_WIDGET (clist));
5163 gdk_pointer_ungrab (GDK_CURRENT_TIME);
5166 gtk_timeout_remove (clist->htimer);
5171 gtk_timeout_remove (clist->vtimer);
5175 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5177 gtk_ctree_unselect (ctree, node);
5182 gtk_ctree_node_get_selectable (GtkCTree *ctree,
5185 g_return_val_if_fail (node != NULL, FALSE);
5187 return GTK_CTREE_ROW (node)->row.selectable;
5191 gtk_ctree_node_get_cell_type (GtkCTree *ctree,
5195 g_return_val_if_fail (ctree != NULL, -1);
5196 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
5197 g_return_val_if_fail (node != NULL, -1);
5199 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5202 return GTK_CTREE_ROW (node)->row.cell[column].type;
5206 gtk_ctree_node_get_text (GtkCTree *ctree,
5211 g_return_val_if_fail (ctree != NULL, 0);
5212 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5213 g_return_val_if_fail (node != NULL, 0);
5215 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5218 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
5222 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
5228 gtk_ctree_node_get_pixmap (GtkCTree *ctree,
5234 g_return_val_if_fail (ctree != NULL, 0);
5235 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5236 g_return_val_if_fail (node != NULL, 0);
5238 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5241 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
5245 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
5247 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
5253 gtk_ctree_node_get_pixtext (GtkCTree *ctree,
5261 g_return_val_if_fail (ctree != NULL, 0);
5262 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5263 g_return_val_if_fail (node != NULL, 0);
5265 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5268 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
5272 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
5274 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
5275 (node)->row.cell[column])->spacing;
5277 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
5278 (node)->row.cell[column])->pixmap;
5280 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
5286 gtk_ctree_get_node_info (GtkCTree *ctree,
5290 GdkPixmap **pixmap_closed,
5291 GdkBitmap **mask_closed,
5292 GdkPixmap **pixmap_opened,
5293 GdkBitmap **mask_opened,
5297 g_return_val_if_fail (ctree != NULL, 0);
5298 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5299 g_return_val_if_fail (node != NULL, 0);
5302 *text = GTK_CELL_PIXTEXT
5303 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
5305 *spacing = GTK_CELL_PIXTEXT
5306 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
5308 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
5310 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
5312 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
5314 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
5316 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
5318 *expanded = GTK_CTREE_ROW (node)->expanded;
5324 gtk_ctree_node_set_cell_style (GtkCTree *ctree,
5330 GtkRequisition requisition;
5331 gboolean visible = FALSE;
5333 g_return_if_fail (ctree != NULL);
5334 g_return_if_fail (GTK_IS_CTREE (ctree));
5335 g_return_if_fail (node != NULL);
5337 clist = GTK_CLIST (ctree);
5339 if (column < 0 || column >= clist->columns)
5342 if (GTK_CTREE_ROW (node)->row.cell[column].style == style)
5345 if (clist->column[column].auto_resize &&
5346 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5348 visible = gtk_ctree_is_viewable (ctree, node);
5350 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5351 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5354 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5356 if (GTK_WIDGET_REALIZED (ctree))
5357 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[column].style);
5358 gtk_style_unref (GTK_CTREE_ROW (node)->row.cell[column].style);
5361 GTK_CTREE_ROW (node)->row.cell[column].style = style;
5363 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5365 gtk_style_ref (GTK_CTREE_ROW (node)->row.cell[column].style);
5367 if (GTK_WIDGET_REALIZED (ctree))
5368 GTK_CTREE_ROW (node)->row.cell[column].style =
5369 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[column].style,
5370 clist->clist_window);
5374 column_auto_resize (clist, >K_CTREE_ROW (node)->row, column,
5377 tree_draw_node (ctree, node);
5381 gtk_ctree_node_get_cell_style (GtkCTree *ctree,
5385 g_return_val_if_fail (ctree != NULL, NULL);
5386 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5387 g_return_val_if_fail (node != NULL, NULL);
5389 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5392 return GTK_CTREE_ROW (node)->row.cell[column].style;
5396 gtk_ctree_node_set_row_style (GtkCTree *ctree,
5401 GtkRequisition requisition;
5403 gint *old_width = NULL;
5406 g_return_if_fail (ctree != NULL);
5407 g_return_if_fail (GTK_IS_CTREE (ctree));
5408 g_return_if_fail (node != NULL);
5410 clist = GTK_CLIST (ctree);
5412 if (GTK_CTREE_ROW (node)->row.style == style)
5415 visible = gtk_ctree_is_viewable (ctree, node);
5416 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5418 old_width = g_new (gint, clist->columns);
5419 for (i = 0; i < clist->columns; i++)
5420 if (clist->column[i].auto_resize)
5422 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5423 (clist, >K_CTREE_ROW (node)->row, i, &requisition);
5424 old_width[i] = requisition.width;
5428 if (GTK_CTREE_ROW (node)->row.style)
5430 if (GTK_WIDGET_REALIZED (ctree))
5431 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
5432 gtk_style_unref (GTK_CTREE_ROW (node)->row.style);
5435 GTK_CTREE_ROW (node)->row.style = style;
5437 if (GTK_CTREE_ROW (node)->row.style)
5439 gtk_style_ref (GTK_CTREE_ROW (node)->row.style);
5441 if (GTK_WIDGET_REALIZED (ctree))
5442 GTK_CTREE_ROW (node)->row.style =
5443 gtk_style_attach (GTK_CTREE_ROW (node)->row.style,
5444 clist->clist_window);
5447 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5449 for (i = 0; i < clist->columns; i++)
5450 if (clist->column[i].auto_resize)
5451 column_auto_resize (clist, >K_CTREE_ROW (node)->row, i,
5455 tree_draw_node (ctree, node);
5459 gtk_ctree_node_get_row_style (GtkCTree *ctree,
5462 g_return_val_if_fail (ctree != NULL, NULL);
5463 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5464 g_return_val_if_fail (node != NULL, NULL);
5466 return GTK_CTREE_ROW (node)->row.style;
5470 gtk_ctree_node_set_foreground (GtkCTree *ctree,
5474 g_return_if_fail (ctree != NULL);
5475 g_return_if_fail (GTK_IS_CTREE (ctree));
5476 g_return_if_fail (node != NULL);
5480 GTK_CTREE_ROW (node)->row.foreground = *color;
5481 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
5482 if (GTK_WIDGET_REALIZED (ctree))
5483 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5484 >K_CTREE_ROW (node)->row.foreground);
5487 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
5489 tree_draw_node (ctree, node);
5493 gtk_ctree_node_set_background (GtkCTree *ctree,
5497 g_return_if_fail (ctree != NULL);
5498 g_return_if_fail (GTK_IS_CTREE (ctree));
5499 g_return_if_fail (node != NULL);
5503 GTK_CTREE_ROW (node)->row.background = *color;
5504 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
5505 if (GTK_WIDGET_REALIZED (ctree))
5506 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5507 >K_CTREE_ROW (node)->row.background);
5510 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
5512 tree_draw_node (ctree, node);
5516 gtk_ctree_node_set_row_data (GtkCTree *ctree,
5520 gtk_ctree_node_set_row_data_full (ctree, node, data, NULL);
5524 gtk_ctree_node_set_row_data_full (GtkCTree *ctree,
5527 GtkDestroyNotify destroy)
5529 g_return_if_fail (ctree != NULL);
5530 g_return_if_fail (GTK_IS_CTREE (ctree));
5532 GTK_CTREE_ROW (node)->row.data = data;
5533 GTK_CTREE_ROW (node)->row.destroy = destroy;
5537 gtk_ctree_node_get_row_data (GtkCTree *ctree,
5540 g_return_val_if_fail (ctree != NULL, NULL);
5541 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5543 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
5547 gtk_ctree_node_moveto (GtkCTree *ctree,
5556 g_return_if_fail (ctree != NULL);
5557 g_return_if_fail (GTK_IS_CTREE (ctree));
5559 clist = GTK_CLIST (ctree);
5561 while (node && !gtk_ctree_is_viewable (ctree, node))
5562 node = GTK_CTREE_ROW (node)->parent;
5565 row = g_list_position (clist->row_list, (GList *)node);
5567 gtk_clist_moveto (clist, row, column, row_align, col_align);
5570 GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree,
5575 g_return_val_if_fail (ctree != NULL, 0);
5576 g_return_val_if_fail (node != NULL, 0);
5578 row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node);
5579 return gtk_clist_row_is_visible (GTK_CLIST (ctree), row);
5583 /***********************************************************
5584 * GtkCTree specific functions *
5585 ***********************************************************/
5588 gtk_ctree_set_indent (GtkCTree *ctree,
5593 g_return_if_fail (ctree != NULL);
5594 g_return_if_fail (GTK_IS_CTREE (ctree));
5595 g_return_if_fail (indent >= 0);
5597 if (indent == ctree->tree_indent)
5600 clist = GTK_CLIST (ctree);
5601 ctree->tree_indent = indent;
5603 if (clist->column[ctree->tree_column].auto_resize &&
5604 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5605 gtk_clist_set_column_width
5606 (clist, ctree->tree_column,
5607 gtk_clist_optimal_column_width (clist, ctree->tree_column));
5608 else if (!GTK_CLIST_FROZEN (ctree))
5609 gtk_clist_thaw (GTK_CLIST (ctree));
5613 gtk_ctree_set_spacing (GtkCTree *ctree,
5619 g_return_if_fail (ctree != NULL);
5620 g_return_if_fail (GTK_IS_CTREE (ctree));
5621 g_return_if_fail (spacing >= 0);
5623 if (spacing == ctree->tree_spacing)
5626 clist = GTK_CLIST (ctree);
5628 old_spacing = ctree->tree_spacing;
5629 ctree->tree_spacing = spacing;
5631 if (clist->column[ctree->tree_column].auto_resize &&
5632 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5633 gtk_clist_set_column_width (clist, ctree->tree_column,
5634 clist->column[ctree->tree_column].width +
5635 spacing - old_spacing);
5636 else if (!GTK_CLIST_FROZEN (ctree))
5637 gtk_clist_thaw (GTK_CLIST (ctree));
5641 gtk_ctree_show_stub (GtkCTree *ctree,
5644 g_message ("gtk_ctree_show_stub() is deprecated");
5645 gtk_ctree_set_show_stub (ctree, show_stub);
5649 gtk_ctree_set_show_stub (GtkCTree *ctree,
5652 g_return_if_fail (ctree != NULL);
5653 g_return_if_fail (GTK_IS_CTREE (ctree));
5655 show_stub = show_stub != FALSE;
5657 if (show_stub != ctree->show_stub)
5661 clist = GTK_CLIST (ctree);
5662 ctree->show_stub = show_stub;
5664 if (!GTK_CLIST_FROZEN (clist) && clist->rows &&
5665 gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
5666 GTK_CLIST_CLASS_FW (clist)->draw_row
5667 (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list));
5672 gtk_ctree_set_reorderable (GtkCTree *ctree,
5673 gboolean reorderable)
5675 g_return_if_fail (ctree != NULL);
5676 g_return_if_fail (GTK_IS_CTREE (ctree));
5678 ctree->reorderable = reorderable;
5682 gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
5685 g_return_if_fail (ctree != NULL);
5686 g_return_if_fail (GTK_IS_CTREE (ctree));
5688 if (ctree->use_icons == (use_icons != 0))
5691 ctree->use_icons = (use_icons != 0);
5695 gtk_ctree_set_line_style (GtkCTree *ctree,
5696 GtkCTreeLineStyle line_style)
5699 GtkCTreeLineStyle old_style;
5701 g_return_if_fail (ctree != NULL);
5702 g_return_if_fail (GTK_IS_CTREE (ctree));
5704 if (line_style == ctree->line_style)
5707 clist = GTK_CLIST (ctree);
5709 old_style = ctree->line_style;
5710 ctree->line_style = line_style;
5712 if (clist->column[ctree->tree_column].auto_resize &&
5713 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5715 if (old_style == GTK_CTREE_LINES_TABBED)
5716 gtk_clist_set_column_width
5717 (clist, ctree->tree_column,
5718 clist->column[ctree->tree_column].width - 3);
5719 else if (line_style == GTK_CTREE_LINES_TABBED)
5720 gtk_clist_set_column_width
5721 (clist, ctree->tree_column,
5722 clist->column[ctree->tree_column].width + 3);
5725 if (GTK_WIDGET_REALIZED (ctree))
5729 case GTK_CTREE_LINES_SOLID:
5730 if (GTK_WIDGET_REALIZED (ctree))
5731 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5734 case GTK_CTREE_LINES_DOTTED:
5735 if (GTK_WIDGET_REALIZED (ctree))
5736 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
5737 GDK_LINE_ON_OFF_DASH, None, None);
5738 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
5740 case GTK_CTREE_LINES_TABBED:
5741 if (GTK_WIDGET_REALIZED (ctree))
5742 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5745 case GTK_CTREE_LINES_NONE:
5750 if (!GTK_CLIST_FROZEN (ctree))
5751 gtk_clist_thaw (GTK_CLIST (ctree));
5756 gtk_ctree_set_expander_style (GtkCTree *ctree,
5757 GtkCTreeExpanderStyle expander_style)
5760 GtkCTreeExpanderStyle old_style;
5762 g_return_if_fail (ctree != NULL);
5763 g_return_if_fail (GTK_IS_CTREE (ctree));
5765 if (expander_style == ctree->expander_style)
5768 clist = GTK_CLIST (ctree);
5770 old_style = ctree->expander_style;
5771 ctree->expander_style = expander_style;
5773 if (clist->column[ctree->tree_column].auto_resize &&
5774 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5778 new_width = clist->column[ctree->tree_column].width;
5781 case GTK_CTREE_EXPANDER_NONE:
5783 case GTK_CTREE_EXPANDER_TRIANGLE:
5784 new_width -= PM_SIZE + 3;
5786 case GTK_CTREE_EXPANDER_SQUARE:
5787 case GTK_CTREE_EXPANDER_CIRCULAR:
5788 new_width -= PM_SIZE + 1;
5792 switch (expander_style)
5794 case GTK_CTREE_EXPANDER_NONE:
5796 case GTK_CTREE_EXPANDER_TRIANGLE:
5797 new_width += PM_SIZE + 3;
5799 case GTK_CTREE_EXPANDER_SQUARE:
5800 case GTK_CTREE_EXPANDER_CIRCULAR:
5801 new_width += PM_SIZE + 1;
5805 gtk_clist_set_column_width (clist, ctree->tree_column, new_width);
5808 if (!GTK_CLIST_FROZEN (ctree) && GTK_WIDGET_DRAWABLE (clist))
5809 gtk_clist_thaw (GTK_CLIST (ctree));
5813 /***********************************************************
5814 * Tree sorting functions *
5815 ***********************************************************/
5819 tree_sort (GtkCTree *ctree,
5823 GtkCTreeNode *list_start;
5828 clist = GTK_CLIST (ctree);
5831 list_start = GTK_CTREE_ROW (node)->children;
5833 list_start = GTK_CTREE_NODE (clist->row_list);
5838 work = GTK_CTREE_ROW (cmp)->sibling;
5841 if (clist->sort_type == GTK_SORT_ASCENDING)
5844 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0)
5850 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0)
5853 work = GTK_CTREE_ROW (work)->sibling;
5855 if (cmp == list_start)
5856 list_start = GTK_CTREE_ROW (cmp)->sibling;
5859 gtk_ctree_unlink (ctree, cmp, FALSE);
5860 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5866 gtk_ctree_sort_recursive (GtkCTree *ctree,
5870 GtkCTreeNode *focus_node = NULL;
5871 gboolean thaw = FALSE;
5873 g_return_if_fail (ctree != NULL);
5874 g_return_if_fail (GTK_IS_CTREE (ctree));
5876 clist = GTK_CLIST (ctree);
5878 if (!GTK_CLIST_FROZEN (clist))
5880 gtk_clist_freeze (clist);
5884 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5886 if (clist->anchor != -1)
5887 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5889 g_list_free (clist->undo_selection);
5890 g_list_free (clist->undo_unselection);
5891 clist->undo_selection = NULL;
5892 clist->undo_unselection = NULL;
5895 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5897 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5899 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5902 tree_sort (ctree, NULL, NULL);
5906 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5907 clist->undo_anchor = clist->focus_row;
5911 gtk_clist_thaw (clist);
5915 real_sort_list (GtkCList *clist)
5917 gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL);
5921 gtk_ctree_sort_node (GtkCTree *ctree,
5925 GtkCTreeNode *focus_node = NULL;
5926 gboolean thaw = FALSE;
5928 g_return_if_fail (ctree != NULL);
5929 g_return_if_fail (GTK_IS_CTREE (ctree));
5931 clist = GTK_CLIST (ctree);
5933 if (!GTK_CLIST_FROZEN (clist))
5935 gtk_clist_freeze (clist);
5939 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5941 if (clist->anchor != -1)
5942 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5944 g_list_free (clist->undo_selection);
5945 g_list_free (clist->undo_unselection);
5946 clist->undo_selection = NULL;
5947 clist->undo_unselection = NULL;
5950 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5951 focus_node = GTK_CTREE_NODE
5952 (g_list_nth (clist->row_list, clist->focus_row));
5954 tree_sort (ctree, node, NULL);
5958 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5959 clist->undo_anchor = clist->focus_row;
5963 gtk_clist_thaw (clist);
5966 /************************************************************************/
5969 fake_unselect_all (GtkCList *clist,
5973 GList *focus_node = NULL;
5975 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5977 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
5978 GTK_CTREE_ROW (focus_node)->row.selectable)
5980 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5982 if (!GTK_CLIST_FROZEN (clist) &&
5983 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5984 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5985 GTK_CLIST_ROW (focus_node));
5989 clist->undo_selection = clist->selection;
5990 clist->selection = NULL;
5991 clist->selection_end = NULL;
5993 for (list = clist->undo_selection; list; list = list->next)
5995 if (list->data == focus_node)
5998 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
5999 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
6004 selection_find (GtkCList *clist,
6006 GList *row_list_element)
6008 return g_list_find (clist->selection, row_list_element);
6012 resync_selection (GtkCList *clist, GdkEvent *event)
6020 gboolean thaw = FALSE;
6023 g_return_if_fail (clist != NULL);
6024 g_return_if_fail (GTK_IS_CTREE (clist));
6026 if (clist->anchor < 0)
6029 ctree = GTK_CTREE (clist);
6031 if (!GTK_CLIST_FROZEN (clist))
6033 GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
6037 i = MIN (clist->anchor, clist->drag_pos);
6038 e = MAX (clist->anchor, clist->drag_pos);
6040 if (clist->undo_selection)
6042 list = clist->selection;
6043 clist->selection = clist->undo_selection;
6044 clist->selection_end = g_list_last (clist->selection);
6045 clist->undo_selection = list;
6046 list = clist->selection;
6055 if (gtk_ctree_is_viewable (ctree, node))
6057 row = g_list_position (clist->row_list, (GList *)node);
6058 if (row >= i && row <= e)
6061 if (unselect && GTK_CTREE_ROW (node)->row.selectable)
6063 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
6064 gtk_ctree_unselect (ctree, node);
6065 clist->undo_selection = g_list_prepend (clist->undo_selection,
6072 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
6073 i++, node = GTK_CTREE_NODE_NEXT (node))
6074 if (GTK_CTREE_ROW (node)->row.selectable)
6076 if (g_list_find (clist->selection, node))
6078 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
6080 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
6081 gtk_ctree_unselect (ctree, node);
6082 clist->undo_selection = g_list_prepend (clist->undo_selection,
6086 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
6088 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
6089 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
6094 for (list = clist->undo_unselection; list; list = list->next)
6095 gtk_ctree_select (ctree, list->data);
6098 clist->drag_pos = -1;
6101 GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
6105 real_undo_selection (GtkCList *clist)
6110 g_return_if_fail (clist != NULL);
6111 g_return_if_fail (GTK_IS_CTREE (clist));
6113 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
6116 if (!(clist->undo_selection || clist->undo_unselection))
6118 gtk_clist_unselect_all (clist);
6122 ctree = GTK_CTREE (clist);
6124 for (work = clist->undo_selection; work; work = work->next)
6125 if (GTK_CTREE_ROW (work->data)->row.selectable)
6126 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
6128 for (work = clist->undo_unselection; work; work = work->next)
6129 if (GTK_CTREE_ROW (work->data)->row.selectable)
6130 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
6132 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
6134 gtk_widget_draw_focus (GTK_WIDGET (clist));
6135 clist->focus_row = clist->undo_anchor;
6136 gtk_widget_draw_focus (GTK_WIDGET (clist));
6139 clist->focus_row = clist->undo_anchor;
6141 clist->undo_anchor = -1;
6143 g_list_free (clist->undo_selection);
6144 g_list_free (clist->undo_unselection);
6145 clist->undo_selection = NULL;
6146 clist->undo_unselection = NULL;
6148 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
6149 clist->clist_window_height)
6150 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6151 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
6152 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6157 gtk_ctree_set_drag_compare_func (GtkCTree *ctree,
6158 GtkCTreeCompareDragFunc cmp_func)
6160 g_return_if_fail (ctree != NULL);
6161 g_return_if_fail (GTK_IS_CTREE (ctree));
6163 ctree->drag_compare = cmp_func;
6167 set_mouse_cursor (GtkCTree *ctree,
6172 g_return_if_fail (ctree != NULL);
6173 g_return_if_fail (GTK_IS_CTREE (ctree));
6176 cursor = gdk_cursor_new (GDK_LEFT_PTR);
6178 cursor = gdk_cursor_new (GDK_CIRCLE);
6180 gdk_window_set_cursor (GTK_CLIST (ctree)->clist_window, cursor);
6181 gdk_cursor_destroy (cursor);
6185 check_cursor (GtkCTree *ctree)
6187 g_return_if_fail (ctree != NULL);
6188 g_return_if_fail (GTK_IS_CTREE (ctree));
6190 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
6191 !gtk_ctree_is_ancestor (ctree, ctree->drag_source, ctree->drag_target))
6193 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
6195 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
6199 (!ctree->drag_compare ||
6203 GTK_CTREE_ROW (ctree->drag_target)->parent,
6204 GTK_CTREE_ROW (ctree->drag_target)->sibling)));
6206 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
6208 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
6212 (!ctree->drag_compare ||
6216 GTK_CTREE_ROW (ctree->drag_target)->parent,
6217 ctree->drag_target)));
6219 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
6221 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
6225 (!ctree->drag_compare ||
6230 GTK_CTREE_ROW (ctree->drag_target)->children)));
6234 set_mouse_cursor(ctree, FALSE);