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 (((GtkObject*) (_widget_))->klass)
48 #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
49 #define CLIST_REFRESH(clist) G_STMT_START { \
50 if (CLIST_UNFROZEN (clist)) \
51 GTK_CLIST_CLASS_FW (clist)->refresh ((GtkCList*) (clist)); \
69 static void gtk_ctree_class_init (GtkCTreeClass *klass);
70 static void gtk_ctree_init (GtkCTree *ctree);
71 static void gtk_ctree_set_arg (GtkObject *object,
74 static void gtk_ctree_get_arg (GtkObject *object,
77 static void gtk_ctree_realize (GtkWidget *widget);
78 static void gtk_ctree_unrealize (GtkWidget *widget);
79 static gint gtk_ctree_button_press (GtkWidget *widget,
80 GdkEventButton *event);
81 static gint gtk_ctree_button_release (GtkWidget *widget,
82 GdkEventButton *event);
83 static gint gtk_ctree_button_motion (GtkWidget *widget,
84 GdkEventMotion *event);
85 static void ctree_attach_styles (GtkCTree *ctree,
88 static void ctree_detach_styles (GtkCTree *ctree,
91 static gint draw_cell_pixmap (GdkWindow *window,
92 GdkRectangle *clip_rectangle,
100 static void get_cell_style (GtkCList *clist,
101 GtkCListRow *clist_row,
107 static gint gtk_ctree_draw_expander (GtkCTree *ctree,
108 GtkCTreeRow *ctree_row,
110 GdkRectangle *clip_rectangle,
112 static gint gtk_ctree_draw_lines (GtkCTree *ctree,
113 GtkCTreeRow *ctree_row,
117 GdkRectangle *clip_rectangle,
118 GdkRectangle *cell_rectangle,
122 static void draw_row (GtkCList *clist,
125 GtkCListRow *clist_row);
126 static void draw_xor_line (GtkCTree *ctree);
127 static void draw_xor_rect (GtkCTree *ctree);
128 static void create_drag_icon (GtkCTree *ctree,
130 static void tree_draw_node (GtkCTree *ctree,
132 static void set_cell_contents (GtkCList *clist,
133 GtkCListRow *clist_row,
140 static void set_node_info (GtkCTree *ctree,
144 GdkPixmap *pixmap_closed,
145 GdkBitmap *mask_closed,
146 GdkPixmap *pixmap_opened,
147 GdkBitmap *mask_opened,
150 static GtkCTreeRow *row_new (GtkCTree *ctree);
151 static void row_delete (GtkCTree *ctree,
152 GtkCTreeRow *ctree_row);
153 static void tree_delete (GtkCTree *ctree,
156 static void tree_delete_row (GtkCTree *ctree,
159 static void real_clear (GtkCList *clist);
160 static void tree_update_level (GtkCTree *ctree,
163 static void tree_select (GtkCTree *ctree,
166 static void tree_unselect (GtkCTree *ctree,
169 static void real_select_all (GtkCList *clist);
170 static void real_unselect_all (GtkCList *clist);
171 static void tree_expand (GtkCTree *ctree,
174 static void tree_collapse (GtkCTree *ctree,
177 static void tree_collapse_to_depth (GtkCTree *ctree,
180 static void tree_toggle_expansion (GtkCTree *ctree,
183 static void change_focus_row_expansion (GtkCTree *ctree,
184 GtkCTreeExpansionType expansion);
185 static void real_select_row (GtkCList *clist,
189 static void real_unselect_row (GtkCList *clist,
193 static void real_tree_select (GtkCTree *ctree,
196 static void real_tree_unselect (GtkCTree *ctree,
199 static void tree_toggle_selection (GtkCTree *ctree,
202 static void real_tree_expand (GtkCTree *ctree,
204 static void real_tree_collapse (GtkCTree *ctree,
206 static void real_tree_move (GtkCTree *ctree,
208 GtkCTreeNode *new_parent,
209 GtkCTreeNode *new_sibling);
210 static void real_row_move (GtkCList *clist,
213 static void gtk_ctree_link (GtkCTree *ctree,
215 GtkCTreeNode *parent,
216 GtkCTreeNode *sibling,
217 gboolean update_focus_row);
218 static void gtk_ctree_unlink (GtkCTree *ctree,
220 gboolean update_focus_row);
221 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
223 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
228 static void tree_sort (GtkCTree *ctree,
231 static void fake_unselect_all (GtkCList *clist,
233 static GList * selection_find (GtkCList *clist,
235 GList *row_list_element);
236 static void resync_selection (GtkCList *clist,
238 static void real_undo_selection (GtkCList *clist);
239 static void select_row_recursive (GtkCTree *ctree,
242 static gint real_insert_row (GtkCList *clist,
245 static void real_remove_row (GtkCList *clist,
247 static void real_sort_list (GtkCList *clist);
248 static void set_mouse_cursor (GtkCTree *ctree,
250 static void check_cursor (GtkCTree *ctree);
251 static void cell_size_request (GtkCList *clist,
252 GtkCListRow *clist_row,
254 GtkRequisition *requisition);
255 static void column_auto_resize (GtkCList *clist,
256 GtkCListRow *clist_row,
259 static void auto_resize_columns (GtkCList *clist);
268 CHANGE_FOCUS_ROW_EXPANSION,
272 typedef void (*GtkCTreeSignal1) (GtkObject *object,
277 typedef void (*GtkCTreeSignal2) (GtkObject *object,
283 typedef void (*GtkCTreeSignal3) (GtkObject *object,
287 typedef void (*GtkCTreeSignal4) (GtkObject *object,
288 GtkCTreeExpansionType arg1,
292 static GtkCListClass *parent_class = NULL;
293 static GtkContainerClass *container_class = NULL;
294 static guint ctree_signals[LAST_SIGNAL] = {0};
298 gtk_ctree_get_type (void)
300 static GtkType ctree_type = 0;
304 static const GtkTypeInfo ctree_info =
308 sizeof (GtkCTreeClass),
309 (GtkClassInitFunc) gtk_ctree_class_init,
310 (GtkObjectInitFunc) gtk_ctree_init,
311 /* reserved_1 */ NULL,
312 /* reserved_2 */ NULL,
313 (GtkClassInitFunc) NULL,
316 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
323 gtk_ctree_class_init (GtkCTreeClass *klass)
325 GtkObjectClass *object_class;
326 GtkWidgetClass *widget_class;
327 GtkCListClass *clist_class;
329 object_class = (GtkObjectClass *) klass;
330 widget_class = (GtkWidgetClass *) klass;
331 container_class = (GtkContainerClass *) klass;
332 clist_class = (GtkCListClass *) klass;
334 parent_class = gtk_type_class (GTK_TYPE_CLIST);
335 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
337 gtk_object_add_arg_type ("GtkCTree::n_columns",
339 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
341 gtk_object_add_arg_type ("GtkCTree::tree_column",
343 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
345 gtk_object_add_arg_type ("GtkCTree::indent",
349 gtk_object_add_arg_type ("GtkCTree::spacing",
353 gtk_object_add_arg_type ("GtkCTree::show_stub",
357 gtk_object_add_arg_type ("GtkCTree::reorderable",
361 gtk_object_add_arg_type ("GtkCTree::use_drag_icons",
365 gtk_object_add_arg_type ("GtkCTree::line_style",
366 GTK_TYPE_CTREE_LINE_STYLE,
369 gtk_object_add_arg_type ("GtkCTree::expander_style",
370 GTK_TYPE_CTREE_EXPANDER_STYLE,
373 object_class->set_arg = gtk_ctree_set_arg;
374 object_class->get_arg = gtk_ctree_get_arg;
376 ctree_signals[TREE_SELECT_ROW] =
377 gtk_signal_new ("tree_select_row",
380 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
381 gtk_marshal_NONE__POINTER_INT,
382 GTK_TYPE_NONE, 2, GTK_TYPE_CTREE_NODE, GTK_TYPE_INT);
383 ctree_signals[TREE_UNSELECT_ROW] =
384 gtk_signal_new ("tree_unselect_row",
387 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
388 gtk_marshal_NONE__POINTER_INT,
389 GTK_TYPE_NONE, 2, GTK_TYPE_CTREE_NODE, GTK_TYPE_INT);
390 ctree_signals[TREE_EXPAND] =
391 gtk_signal_new ("tree_expand",
394 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
395 gtk_marshal_NONE__POINTER,
396 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_NODE);
397 ctree_signals[TREE_COLLAPSE] =
398 gtk_signal_new ("tree_collapse",
401 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
402 gtk_marshal_NONE__POINTER,
403 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
404 ctree_signals[TREE_MOVE] =
405 gtk_signal_new ("tree_move",
408 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
409 gtk_marshal_NONE__POINTER_POINTER_POINTER,
410 GTK_TYPE_NONE, 3, GTK_TYPE_CTREE_NODE,
411 GTK_TYPE_CTREE_NODE, GTK_TYPE_CTREE_NODE);
412 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
413 gtk_signal_new ("change_focus_row_expansion",
414 GTK_RUN_LAST | GTK_RUN_ACTION,
416 GTK_SIGNAL_OFFSET (GtkCTreeClass,
417 change_focus_row_expansion),
418 gtk_marshal_NONE__ENUM,
419 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_EXPANSION_TYPE);
420 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
422 widget_class->realize = gtk_ctree_realize;
423 widget_class->unrealize = gtk_ctree_unrealize;
424 widget_class->button_press_event = gtk_ctree_button_press;
425 widget_class->button_release_event = gtk_ctree_button_release;
426 widget_class->motion_notify_event = gtk_ctree_button_motion;
428 clist_class->select_row = real_select_row;
429 clist_class->unselect_row = real_unselect_row;
430 clist_class->row_move = real_row_move;
431 clist_class->undo_selection = real_undo_selection;
432 clist_class->resync_selection = resync_selection;
433 clist_class->selection_find = selection_find;
434 clist_class->click_column = NULL;
435 clist_class->draw_row = draw_row;
436 clist_class->clear = real_clear;
437 clist_class->select_all = real_select_all;
438 clist_class->unselect_all = real_unselect_all;
439 clist_class->fake_unselect_all = fake_unselect_all;
440 clist_class->insert_row = real_insert_row;
441 clist_class->remove_row = real_remove_row;
442 clist_class->sort_list = real_sort_list;
443 clist_class->set_cell_contents = set_cell_contents;
444 clist_class->cell_size_request = cell_size_request;
446 klass->tree_select_row = real_tree_select;
447 klass->tree_unselect_row = real_tree_unselect;
448 klass->tree_expand = real_tree_expand;
449 klass->tree_collapse = real_tree_collapse;
450 klass->tree_move = real_tree_move;
451 klass->change_focus_row_expansion = change_focus_row_expansion;
454 GtkBindingSet *binding_set;
456 binding_set = gtk_binding_set_by_class (klass);
457 gtk_binding_entry_add_signal (binding_set,
459 "change_focus_row_expansion", 1,
460 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
461 gtk_binding_entry_add_signal (binding_set,
463 "change_focus_row_expansion", 1,
464 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
465 gtk_binding_entry_add_signal (binding_set,
466 GDK_KP_Add, GDK_CONTROL_MASK,
467 "change_focus_row_expansion", 1,
469 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
470 gtk_binding_entry_add_signal (binding_set,
472 "change_focus_row_expansion", 1,
473 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
474 gtk_binding_entry_add_signal (binding_set,
476 "change_focus_row_expansion", 1,
477 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
478 gtk_binding_entry_add_signal (binding_set,
479 GDK_KP_Subtract, GDK_CONTROL_MASK,
480 "change_focus_row_expansion", 1,
482 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
483 gtk_binding_entry_add_signal (binding_set,
485 "change_focus_row_expansion", 1,
486 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
487 gtk_binding_entry_add_signal (binding_set,
489 "change_focus_row_expansion", 1,
490 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
491 gtk_binding_entry_add_signal (binding_set,
492 GDK_KP_Multiply, GDK_CONTROL_MASK,
493 "change_focus_row_expansion", 1,
495 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
501 gtk_ctree_set_arg (GtkObject *object,
507 ctree = GTK_CTREE (object);
511 case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
512 if (ctree->tree_column)
513 gtk_ctree_construct (ctree,
514 MAX (1, GTK_VALUE_UINT (*arg)),
515 ctree->tree_column, NULL);
517 GTK_CLIST (ctree)->columns = MAX (1, GTK_VALUE_UINT (*arg));
519 case ARG_TREE_COLUMN: /* construct-only arg, only set when !GTK_CONSTRUCTED */
520 if (GTK_CLIST (ctree)->columns)
521 gtk_ctree_construct (ctree,
522 GTK_CLIST (ctree)->columns,
523 MAX (1, GTK_VALUE_UINT (*arg)),
526 ctree->tree_column = MAX (1, GTK_VALUE_UINT (*arg));
529 gtk_ctree_set_indent (ctree, GTK_VALUE_UINT (*arg));
532 gtk_ctree_set_spacing (ctree, GTK_VALUE_UINT (*arg));
535 gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg));
537 case ARG_REORDERABLE:
538 gtk_ctree_set_reorderable (ctree, GTK_VALUE_BOOL (*arg));
540 case ARG_USE_DRAG_ICONS:
541 gtk_ctree_set_use_drag_icons (ctree, GTK_VALUE_BOOL (*arg));
544 gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg));
546 case ARG_EXPANDER_STYLE:
547 gtk_ctree_set_expander_style (ctree, GTK_VALUE_ENUM (*arg));
555 gtk_ctree_get_arg (GtkObject *object,
561 ctree = GTK_CTREE (object);
566 GTK_VALUE_UINT (*arg) = GTK_CLIST (ctree)->columns;
568 case ARG_TREE_COLUMN:
569 GTK_VALUE_UINT (*arg) = ctree->tree_column;
572 GTK_VALUE_UINT (*arg) = ctree->tree_indent;
575 GTK_VALUE_UINT (*arg) = ctree->tree_spacing;
578 GTK_VALUE_BOOL (*arg) = ctree->show_stub;
580 case ARG_REORDERABLE:
581 GTK_VALUE_BOOL (*arg) = ctree->reorderable;
583 case ARG_USE_DRAG_ICONS:
584 GTK_VALUE_BOOL (*arg) = ctree->use_icons;
587 GTK_VALUE_ENUM (*arg) = ctree->line_style;
589 case ARG_EXPANDER_STYLE:
590 GTK_VALUE_ENUM (*arg) = ctree->expander_style;
593 arg->type = GTK_TYPE_INVALID;
599 gtk_ctree_init (GtkCTree *ctree)
601 ctree->drag_icon = NULL;
602 ctree->tree_indent = 20;
603 ctree->tree_spacing = 5;
604 ctree->tree_column = 0;
605 ctree->drag_row = -1;
606 ctree->drag_source = NULL;
607 ctree->drag_target = NULL;
608 ctree->insert_pos = GTK_CTREE_POS_AS_CHILD;
609 ctree->reorderable = FALSE;
610 ctree->use_icons = TRUE;
611 ctree->in_drag = FALSE;
612 ctree->drag_rect = FALSE;
613 ctree->line_style = GTK_CTREE_LINES_SOLID;
614 ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE;
615 ctree->drag_compare = NULL;
616 ctree->show_stub = TRUE;
620 ctree_attach_styles (GtkCTree *ctree,
627 clist = GTK_CLIST (ctree);
629 if (GTK_CTREE_ROW (node)->row.style)
630 GTK_CTREE_ROW (node)->row.style =
631 gtk_style_attach (GTK_CTREE_ROW (node)->row.style, clist->clist_window);
633 if (GTK_CTREE_ROW (node)->row.fg_set || GTK_CTREE_ROW (node)->row.bg_set)
635 GdkColormap *colormap;
637 colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
638 if (GTK_CTREE_ROW (node)->row.fg_set)
639 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.foreground));
640 if (GTK_CTREE_ROW (node)->row.bg_set)
641 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.background));
644 for (i = 0; i < clist->columns; i++)
645 if (GTK_CTREE_ROW (node)->row.cell[i].style)
646 GTK_CTREE_ROW (node)->row.cell[i].style =
647 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[i].style,
648 clist->clist_window);
652 ctree_detach_styles (GtkCTree *ctree,
659 clist = GTK_CLIST (ctree);
661 if (GTK_CTREE_ROW (node)->row.style)
662 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
663 for (i = 0; i < clist->columns; i++)
664 if (GTK_CTREE_ROW (node)->row.cell[i].style)
665 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[i].style);
669 gtk_ctree_realize (GtkWidget *widget)
678 g_return_if_fail (widget != NULL);
679 g_return_if_fail (GTK_IS_CTREE (widget));
681 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
683 ctree = GTK_CTREE (widget);
684 clist = GTK_CLIST (widget);
686 node = GTK_CTREE_NODE (clist->row_list);
687 for (i = 0; i < clist->rows; i++)
689 if (GTK_CTREE_ROW (node)->children && !GTK_CTREE_ROW (node)->expanded)
690 for (child = GTK_CTREE_ROW (node)->children; child;
691 child = GTK_CTREE_ROW (child)->sibling)
692 gtk_ctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
693 node = GTK_CTREE_NODE_NEXT (node);
696 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
697 values.background = widget->style->bg[GTK_STATE_NORMAL];
698 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
699 values.line_style = GDK_LINE_SOLID;
700 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
707 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
709 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
710 GDK_LINE_ON_OFF_DASH, None, None);
711 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
716 gtk_ctree_unrealize (GtkWidget *widget)
721 g_return_if_fail (widget != NULL);
722 g_return_if_fail (GTK_IS_CTREE (widget));
724 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
726 ctree = GTK_CTREE (widget);
727 clist = GTK_CLIST (widget);
729 if (GTK_WIDGET_REALIZED (widget))
735 node = GTK_CTREE_NODE (clist->row_list);
736 for (i = 0; i < clist->rows; i++)
738 if (GTK_CTREE_ROW (node)->children &&
739 !GTK_CTREE_ROW (node)->expanded)
740 for (child = GTK_CTREE_ROW (node)->children; child;
741 child = GTK_CTREE_ROW (child)->sibling)
742 gtk_ctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
743 node = GTK_CTREE_NODE_NEXT (node);
747 gdk_gc_destroy (ctree->lines_gc);
751 gtk_ctree_button_press (GtkWidget *widget,
752 GdkEventButton *event)
757 g_return_val_if_fail (widget != NULL, FALSE);
758 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
759 g_return_val_if_fail (event != NULL, FALSE);
761 ctree = GTK_CTREE (widget);
762 clist = GTK_CLIST (widget);
764 if (event->window == clist->clist_window)
766 gboolean collapse_expand = FALSE;
776 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
779 if (event->button == 2)
780 ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y);
782 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
784 if (ctree->reorderable && event->button == 2 && !ctree->in_drag &&
787 gdk_pointer_grab (event->window, FALSE,
788 GDK_POINTER_MOTION_HINT_MASK |
789 GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
790 NULL, NULL, event->time);
791 gtk_grab_add (widget);
792 ctree->in_drag = TRUE;
793 ctree->drag_source = work;
794 ctree->drag_target = NULL;
795 gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH,
797 gdk_gc_set_dashes (clist->xor_gc, 0, "\2\2", 2);
800 else if (event->button == 1 &&
801 (GTK_CTREE_ROW (work)->children &&
802 (event->type == GDK_2BUTTON_PRESS ||
803 ctree_is_hot_spot (ctree, work, row, x, y))))
805 if (GTK_CTREE_ROW (work)->expanded)
806 gtk_ctree_collapse (ctree, work);
808 gtk_ctree_expand (ctree, work);
810 collapse_expand = TRUE;
812 if (event->button == 1)
814 gint old_row = clist->focus_row;
815 gboolean no_focus_row = FALSE;
817 switch (clist->selection_mode)
819 case GTK_SELECTION_MULTIPLE:
820 case GTK_SELECTION_SINGLE:
821 if (!collapse_expand)
824 if (clist->focus_row == -1)
830 GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
831 gdk_pointer_grab (clist->clist_window, FALSE,
832 GDK_POINTER_MOTION_HINT_MASK |
833 GDK_BUTTON1_MOTION_MASK |
834 GDK_BUTTON_RELEASE_MASK,
835 NULL, NULL, event->time);
836 gtk_grab_add (widget);
838 if (GTK_CLIST_ADD_MODE (clist))
840 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
841 if (GTK_WIDGET_HAS_FOCUS (widget))
843 gtk_widget_draw_focus (widget);
844 gdk_gc_set_line_attributes (clist->xor_gc, 1,
845 GDK_LINE_SOLID, 0, 0);
846 clist->focus_row = row;
847 gtk_widget_draw_focus (widget);
851 gdk_gc_set_line_attributes (clist->xor_gc, 1,
852 GDK_LINE_SOLID, 0, 0);
853 clist->focus_row = row;
856 else if (row != clist->focus_row)
858 if (GTK_WIDGET_HAS_FOCUS (widget))
860 gtk_widget_draw_focus (widget);
861 clist->focus_row = row;
862 gtk_widget_draw_focus (widget);
865 clist->focus_row = row;
868 if (!GTK_WIDGET_HAS_FOCUS (widget))
869 gtk_widget_grab_focus (widget);
878 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
882 gtk_ctree_button_motion (GtkWidget *widget,
883 GdkEventMotion *event)
890 gint insert_pos = GTK_CTREE_POS_AS_CHILD;
892 g_return_val_if_fail (widget != NULL, FALSE);
893 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
894 g_return_val_if_fail (event != NULL, FALSE);
896 ctree = GTK_CTREE (widget);
897 clist = GTK_CLIST (widget);
899 if (GTK_CLIST_IN_DRAG (clist))
900 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
903 if (event->window == clist->clist_window &&
904 ctree->in_drag && ctree->reorderable)
906 GdkModifierType modmask;
913 gdk_window_get_pointer (event->window, &x, &y, NULL);
915 /* delayed drag start */
916 if (!ctree->drag_target &&
917 y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) &&
918 y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height)
920 GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
922 if (ctree->use_icons)
924 if (!ctree->drag_icon)
925 create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source));
928 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
929 gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2,
930 root_y - ctree->icon_height);
934 /* out of bounds check */
935 if (x < 0 || y < -3 || x > clist->clist_window_width ||
936 y > clist->clist_window_height + 3 ||
937 y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3)
939 if (ctree->drag_row >= 0)
941 if (ctree->drag_rect)
943 draw_xor_rect (ctree);
944 ctree->drag_rect = FALSE;
947 draw_xor_line (ctree);
948 ctree->drag_row = -1;
951 (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event)
955 row = ROW_FROM_YPIXEL (clist, y);
957 /* re-calculate target (mouse left the window) */
958 if (ctree->drag_target && ctree->drag_row == -1)
959 ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row));
961 if (y < 0 || y > clist->clist_window_height ||
962 ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height
963 || row >= clist->rows)
964 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event
967 if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4)
968 insert_pos = GTK_CTREE_POS_BEFORE;
969 else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y
970 < clist->row_height / 4)
971 insert_pos = GTK_CTREE_POS_AFTER;
973 if (row != ctree->drag_row ||
974 (row == ctree->drag_row && ctree->insert_pos != insert_pos))
976 if (insert_pos != GTK_CTREE_POS_AS_CHILD)
978 if (ctree->drag_row >= 0)
980 if (ctree->drag_rect)
982 draw_xor_rect (ctree);
983 ctree->drag_rect = FALSE;
986 draw_xor_line (ctree);
988 ctree->insert_pos = insert_pos;
990 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
991 ctree->drag_row = row;
992 draw_xor_line (ctree);
995 else if (ctree->drag_target &&
996 !GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
998 if (ctree->drag_row >= 0)
1000 if (ctree->drag_rect)
1001 draw_xor_rect (ctree);
1003 draw_xor_line (ctree);
1005 ctree->drag_rect = TRUE;
1006 ctree->insert_pos = insert_pos;
1007 ctree->drag_target =
1008 GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
1009 ctree->drag_row = row;
1010 draw_xor_rect (ctree);
1011 check_cursor(ctree);
1015 return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event);
1019 gtk_ctree_button_release (GtkWidget *widget,
1020 GdkEventButton *event)
1025 g_return_val_if_fail (widget != NULL, FALSE);
1026 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
1027 g_return_val_if_fail (event != NULL, FALSE);
1029 ctree = GTK_CTREE (widget);
1030 clist = GTK_CLIST (widget);
1032 if (event->button == 2 && clist->anchor == -1)
1034 gtk_grab_remove (widget);
1035 gdk_pointer_ungrab (event->time);
1037 ctree->in_drag = FALSE;
1039 set_mouse_cursor(ctree, TRUE);
1041 if (ctree->use_icons && ctree->drag_icon)
1043 gdk_window_destroy (ctree->drag_icon);
1044 ctree->drag_icon = NULL;
1047 if (ctree->drag_row >= 0)
1049 if (ctree->drag_rect)
1051 draw_xor_rect (ctree);
1052 ctree->drag_rect = FALSE;
1055 draw_xor_line (ctree);
1056 ctree->drag_row = -1;
1059 if (GTK_CLIST_ADD_MODE (clist))
1060 gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
1062 gdk_gc_set_line_attributes (clist->xor_gc, 1,
1063 GDK_LINE_SOLID, 0, 0);
1065 /* nop if out of bounds / source == target */
1066 if (event->x < 0 || event->y < -3 ||
1067 event->x > clist->clist_window_width ||
1068 event->y > clist->clist_window_height + 3 ||
1069 ctree->drag_target == ctree->drag_source ||
1070 !ctree->drag_target)
1071 return GTK_WIDGET_CLASS (parent_class)->button_release_event
1074 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
1075 !gtk_ctree_is_ancestor (ctree, ctree->drag_source,
1076 ctree->drag_target))
1078 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
1080 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
1082 if (!ctree->drag_compare ||
1083 ctree->drag_compare (ctree,
1085 GTK_CTREE_ROW (ctree->drag_target)->parent,
1086 GTK_CTREE_ROW (ctree->drag_target)->sibling))
1087 gtk_signal_emit (GTK_OBJECT (ctree),
1088 ctree_signals[TREE_MOVE],
1090 GTK_CTREE_ROW (ctree->drag_target)->parent,
1091 GTK_CTREE_ROW (ctree->drag_target)->sibling);
1093 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
1095 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
1097 if (!ctree->drag_compare ||
1098 ctree->drag_compare (ctree,
1100 GTK_CTREE_ROW (ctree->drag_target)->parent,
1101 ctree->drag_target))
1102 gtk_signal_emit (GTK_OBJECT (ctree),
1103 ctree_signals[TREE_MOVE],
1105 GTK_CTREE_ROW (ctree->drag_target)->parent,
1106 ctree->drag_target);
1108 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
1110 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
1112 if (!ctree->drag_compare ||
1113 ctree->drag_compare (ctree,
1116 GTK_CTREE_ROW (ctree->drag_target)->children))
1117 gtk_signal_emit (GTK_OBJECT (ctree),
1118 ctree_signals[TREE_MOVE],
1121 GTK_CTREE_ROW (ctree->drag_target)->children);
1124 ctree->drag_source = NULL;
1125 ctree->drag_target = NULL;
1127 else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) &&
1128 (clist->selection_mode == GTK_SELECTION_SINGLE ||
1129 clist->selection_mode == GTK_SELECTION_MULTIPLE))
1135 if (gtk_clist_get_selection_info
1136 (clist, event->x, event->y, &row, &column))
1138 if (clist->anchor == clist->focus_row &&
1139 (work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row))))
1140 tree_toggle_selection (ctree, work, column);
1144 return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event);
1148 create_drag_icon (GtkCTree *ctree,
1153 GdkWindow *window = NULL;
1154 GdkWindowAttr attributes;
1155 gint attributes_mask;
1158 GdkModifierType modmask;
1162 clist = GTK_CLIST (ctree);
1163 widget = GTK_WIDGET (ctree);
1165 if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap))
1167 mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask;
1169 gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask);
1170 gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height);
1172 attributes.window_type = GDK_WINDOW_TEMP;
1173 attributes.x = root_x - ctree->icon_width / 2;
1174 attributes.y = root_y - ctree->icon_height;
1175 attributes.width = ctree->icon_width;
1176 attributes.height = ctree->icon_height;
1177 attributes.wclass = GDK_INPUT_OUTPUT;
1178 attributes.visual = gtk_widget_get_visual (widget);
1179 attributes.colormap = gtk_widget_get_colormap (widget);
1180 attributes.event_mask = gtk_widget_get_events (widget);
1182 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1184 window = gdk_window_new (widget->window, &attributes, attributes_mask);
1185 gdk_window_set_back_pixmap (window, pixmap, FALSE);
1187 gdk_window_shape_combine_mask (window, mask, 0, 0);
1188 gdk_window_show (window);
1190 ctree->drag_icon = window;
1194 draw_xor_line (GtkCTree *ctree)
1200 clist = GTK_CLIST (ctree);
1202 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1204 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
1205 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1207 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1;
1209 if (clist->column[ctree->tree_column].visible)
1210 switch (clist->column[ctree->tree_column].justification)
1212 case GTK_JUSTIFY_CENTER:
1213 case GTK_JUSTIFY_FILL:
1214 case GTK_JUSTIFY_LEFT:
1215 if (ctree->tree_column > 0)
1216 gdk_draw_line (clist->clist_window, clist->xor_gc,
1217 COLUMN_LEFT_XPIXEL(clist, 0), y,
1218 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1219 clist->column[ctree->tree_column - 1].area.width, y);
1221 gdk_draw_line (clist->clist_window, clist->xor_gc,
1222 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1223 ctree->tree_indent * level -
1224 (ctree->tree_indent - PM_SIZE) / 2, y,
1225 GTK_WIDGET (ctree)->allocation.width, y);
1227 case GTK_JUSTIFY_RIGHT:
1228 if (ctree->tree_column < clist->columns - 1)
1229 gdk_draw_line (clist->clist_window, clist->xor_gc,
1230 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y,
1231 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
1232 clist->column[clist->columns - 1].area.width, y);
1234 gdk_draw_line (clist->clist_window, clist->xor_gc,
1235 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
1236 + clist->column[ctree->tree_column].area.width -
1237 ctree->tree_indent * level +
1238 (ctree->tree_indent - PM_SIZE) / 2, y);
1242 gdk_draw_line (clist->clist_window, clist->xor_gc,
1243 0, y, clist->clist_window_width, y);
1247 draw_xor_rect (GtkCTree *ctree)
1255 clist = GTK_CLIST (ctree);
1257 level = GTK_CTREE_ROW (ctree->drag_target)->level;
1259 y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height;
1261 if (clist->column[ctree->tree_column].visible)
1262 switch (clist->column[ctree->tree_column].justification)
1264 case GTK_JUSTIFY_CENTER:
1265 case GTK_JUSTIFY_FILL:
1266 case GTK_JUSTIFY_LEFT:
1267 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
1268 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
1270 points[3].x = points[0].x;
1271 points[3].y = y - clist->row_height - 1;
1272 points[1].x = clist->clist_window_width - 1;
1273 points[1].y = points[0].y;
1274 points[2].x = points[1].x;
1275 points[2].y = points[3].y;
1277 for (i = 0; i < 3; i++)
1278 gdk_draw_line (clist->clist_window, clist->xor_gc,
1279 points[i].x, points[i].y,
1280 points[i+1].x, points[i+1].y);
1282 if (ctree->tree_column > 0)
1284 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) +
1285 clist->column[ctree->tree_column - 1].area.width ;
1287 points[3].x = points[0].x;
1288 points[3].y = y - clist->row_height - 1;
1290 points[1].y = points[0].y;
1292 points[2].y = points[3].y;
1294 for (i = 0; i < 3; i++)
1295 gdk_draw_line (clist->clist_window, clist->xor_gc,
1296 points[i].x, points[i].y, points[i+1].x,
1300 case GTK_JUSTIFY_RIGHT:
1301 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
1302 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
1303 clist->column[ctree->tree_column].area.width;
1305 points[3].x = points[0].x;
1306 points[3].y = y - clist->row_height - 1;
1308 points[1].y = points[0].y;
1310 points[2].y = points[3].y;
1312 for (i = 0; i < 3; i++)
1313 gdk_draw_line (clist->clist_window, clist->xor_gc,
1314 points[i].x, points[i].y,
1315 points[i+1].x, points[i+1].y);
1317 if (ctree->tree_column < clist->columns - 1)
1319 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1);
1321 points[3].x = points[0].x;
1322 points[3].y = y - clist->row_height - 1;
1323 points[1].x = clist->clist_window_width - 1;
1324 points[1].y = points[0].y;
1325 points[2].x = points[1].x;
1326 points[2].y = points[3].y;
1328 for (i = 0; i < 3; i++)
1329 gdk_draw_line (clist->clist_window, clist->xor_gc,
1330 points[i].x, points[i].y,
1331 points[i+1].x, points[i+1].y);
1336 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1337 0, y - clist->row_height,
1338 clist->clist_window_width - 1, clist->row_height);
1342 draw_cell_pixmap (GdkWindow *window,
1343 GdkRectangle *clip_rectangle,
1357 gdk_gc_set_clip_mask (fg_gc, mask);
1358 gdk_gc_set_clip_origin (fg_gc, x, y);
1360 if (x < clip_rectangle->x)
1362 xsrc = clip_rectangle->x - x;
1364 x = clip_rectangle->x;
1366 if (x + width > clip_rectangle->x + clip_rectangle->width)
1367 width = clip_rectangle->x + clip_rectangle->width - x;
1369 if (y < clip_rectangle->y)
1371 ysrc = clip_rectangle->y - y;
1373 y = clip_rectangle->y;
1375 if (y + height > clip_rectangle->y + clip_rectangle->height)
1376 height = clip_rectangle->y + clip_rectangle->height - y;
1378 if (width > 0 && height > 0)
1379 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
1381 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1383 return x + MAX (width, 0);
1387 get_cell_style (GtkCList *clist,
1388 GtkCListRow *clist_row,
1395 if (clist_row->cell[column].style)
1398 *style = clist_row->cell[column].style;
1400 *fg_gc = clist_row->cell[column].style->fg_gc[state];
1402 *bg_gc = clist_row->cell[column].style->bg_gc[state];
1404 else if (clist_row->style)
1407 *style = clist_row->style;
1409 *fg_gc = clist_row->style->fg_gc[state];
1411 *bg_gc = clist_row->style->bg_gc[state];
1416 *style = GTK_WIDGET (clist)->style;
1418 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[state];
1420 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1422 if (state != GTK_STATE_SELECTED)
1424 if (fg_gc && clist_row->fg_set)
1425 *fg_gc = clist->fg_gc;
1426 if (bg_gc && clist_row->bg_set)
1427 *bg_gc = clist->bg_gc;
1433 gtk_ctree_draw_expander (GtkCTree *ctree,
1434 GtkCTreeRow *ctree_row,
1436 GdkRectangle *clip_rectangle,
1441 gint justification_factor;
1444 if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
1447 clist = GTK_CLIST (ctree);
1448 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
1449 justification_factor = -1;
1451 justification_factor = 1;
1452 y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
1453 (clip_rectangle->height + 1) % 2);
1455 if (!ctree_row->children)
1457 switch (ctree->expander_style)
1459 case GTK_CTREE_EXPANDER_NONE:
1461 case GTK_CTREE_EXPANDER_TRIANGLE:
1462 return x + justification_factor * (PM_SIZE + 3);
1463 case GTK_CTREE_EXPANDER_SQUARE:
1464 case GTK_CTREE_EXPANDER_CIRCULAR:
1465 return x + justification_factor * (PM_SIZE + 1);
1469 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle);
1470 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle);
1472 switch (ctree->expander_style)
1474 case GTK_CTREE_EXPANDER_NONE:
1476 case GTK_CTREE_EXPANDER_TRIANGLE:
1477 if (ctree_row->expanded)
1480 points[0].y = y + (PM_SIZE + 2) / 6;
1481 points[1].x = points[0].x + justification_factor * (PM_SIZE + 2);
1482 points[1].y = points[0].y;
1483 points[2].x = (points[0].x +
1484 justification_factor * (PM_SIZE + 2) / 2);
1485 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
1489 points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2);
1490 points[0].y = y - 1;
1491 points[1].x = points[0].x;
1492 points[1].y = points[0].y + (PM_SIZE + 2);
1493 points[2].x = (points[0].x +
1494 justification_factor * (2 * (PM_SIZE + 2) / 3 - 1));
1495 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
1498 gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1500 gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1503 x += justification_factor * (PM_SIZE + 3);
1505 case GTK_CTREE_EXPANDER_SQUARE:
1506 case GTK_CTREE_EXPANDER_CIRCULAR:
1507 if (justification_factor == -1)
1508 x += justification_factor * (PM_SIZE + 1);
1510 if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
1512 gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1513 TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1514 gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1515 FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1519 gdk_draw_rectangle (clist->clist_window,
1520 style->base_gc[GTK_STATE_NORMAL], TRUE,
1521 x, y, PM_SIZE, PM_SIZE);
1522 gdk_draw_rectangle (clist->clist_window,
1523 style->fg_gc[GTK_STATE_NORMAL], FALSE,
1524 x, y, PM_SIZE, PM_SIZE);
1527 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1528 x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
1530 if (!ctree_row->expanded)
1531 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1532 x + PM_SIZE / 2, y + 2,
1533 x + PM_SIZE / 2, y + PM_SIZE - 2);
1535 if (justification_factor == 1)
1536 x += justification_factor * (PM_SIZE + 1);
1540 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
1541 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
1548 gtk_ctree_draw_lines (GtkCTree *ctree,
1549 GtkCTreeRow *ctree_row,
1553 GdkRectangle *clip_rectangle,
1554 GdkRectangle *cell_rectangle,
1555 GdkRectangle *crect,
1561 GtkCTreeNode *parent;
1562 GdkRectangle tree_rectangle;
1563 GdkRectangle tc_rectangle;
1574 gint justification_factor;
1576 clist = GTK_CLIST (ctree);
1577 ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
1578 justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
1582 offset = (clip_rectangle->x + clip_rectangle->width - 1 -
1583 ctree->tree_indent * (ctree_row->level - 1));
1584 justification_factor = -1;
1588 offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1);
1589 justification_factor = 1;
1592 switch (ctree->line_style)
1594 case GTK_CTREE_LINES_NONE:
1596 case GTK_CTREE_LINES_TABBED:
1597 xcenter = offset + justification_factor * TAB_SIZE;
1599 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1600 clist->column[ctree->tree_column].area.width +
1602 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1603 COLUMN_INSET - CELL_SPACING);
1607 tree_rectangle.y = crect->y;
1608 tree_rectangle.height = crect->height;
1612 tree_rectangle.x = xcenter;
1613 tree_rectangle.width = column_right - xcenter;
1617 tree_rectangle.x = column_left;
1618 tree_rectangle.width = xcenter - column_left;
1621 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1623 offset += justification_factor * 3;
1628 gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
1630 next_level = ctree_row->level;
1632 if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
1634 node = gtk_ctree_find_node_ptr (ctree, ctree_row);
1635 if (GTK_CTREE_NODE_NEXT (node))
1636 next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level;
1641 if (ctree->tree_indent > 0)
1643 node = ctree_row->parent;
1646 xcenter -= (justification_factor * ctree->tree_indent);
1648 if ((justify_right && xcenter < column_left) ||
1649 (!justify_right && xcenter > column_right))
1651 node = GTK_CTREE_ROW (node)->parent;
1655 tree_rectangle.y = cell_rectangle->y;
1656 tree_rectangle.height = cell_rectangle->height;
1659 tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1,
1661 tree_rectangle.width = MIN (xcenter - column_left,
1662 ctree->tree_indent);
1666 tree_rectangle.x = xcenter;
1667 tree_rectangle.width = MIN (column_right - xcenter,
1668 ctree->tree_indent);
1671 if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
1674 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1675 state, column, NULL, NULL, &bg_gc);
1677 if (bg_gc == clist->bg_gc)
1678 gdk_gc_set_foreground
1679 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1682 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1685 tree_rectangle.width,
1686 tree_rectangle.height);
1688 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1692 tc_rectangle.height);
1694 if (next_level > GTK_CTREE_ROW (node)->level)
1695 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1697 xcenter, crect->y + crect->height);
1702 offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1703 width = offset_x / 2 + offset_x % 2;
1705 parent = GTK_CTREE_ROW (node)->parent;
1707 tree_rectangle.y = ycenter;
1708 tree_rectangle.height = (cell_rectangle->y - ycenter +
1709 cell_rectangle->height);
1713 tree_rectangle.x = MAX(xcenter + 1 - width, column_left);
1714 tree_rectangle.width = MIN (xcenter + 1 - column_left,
1719 tree_rectangle.x = xcenter;
1720 tree_rectangle.width = MIN (column_right - xcenter,
1725 gdk_rectangle_intersect (area, &tree_rectangle,
1730 get_cell_style (clist, >K_CTREE_ROW (parent)->row,
1731 state, column, NULL, NULL, &bg_gc);
1732 if (bg_gc == clist->bg_gc)
1733 gdk_gc_set_foreground
1735 >K_CTREE_ROW (parent)->row.background);
1737 else if (state == GTK_STATE_SELECTED)
1738 bg_gc = style->bg_gc[state];
1740 bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1743 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1746 tree_rectangle.width,
1747 tree_rectangle.height);
1749 gdk_draw_rectangle (clist->clist_window,
1754 tc_rectangle.height);
1757 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1758 state, column, NULL, NULL, &bg_gc);
1759 if (bg_gc == clist->bg_gc)
1760 gdk_gc_set_foreground
1761 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1763 gdk_gc_set_clip_rectangle (bg_gc, crect);
1764 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1765 xcenter - (justify_right * offset_x),
1767 offset_x, clist->row_height,
1768 (180 + (justify_right * 90)) * 64, 90 * 64);
1769 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1771 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1772 xcenter, cell_rectangle->y, xcenter, ycenter);
1775 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1776 xcenter - offset_x, cell_rectangle->y,
1777 offset_x, clist->row_height,
1780 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1781 xcenter, cell_rectangle->y,
1782 offset_x, clist->row_height,
1785 node = GTK_CTREE_ROW (node)->parent;
1789 if (state != GTK_STATE_SELECTED)
1791 tree_rectangle.y = clip_rectangle->y;
1792 tree_rectangle.height = clip_rectangle->height;
1793 tree_rectangle.width = COLUMN_INSET + CELL_SPACING +
1794 MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET,
1798 tree_rectangle.x = MAX (xcenter + 1, column_left);
1800 tree_rectangle.x = column_left;
1803 gdk_draw_rectangle (clist->clist_window,
1805 (ctree)->style->bg_gc[GTK_STATE_PRELIGHT],
1809 tree_rectangle.width,
1810 tree_rectangle.height);
1811 else if (gdk_rectangle_intersect (area, &tree_rectangle,
1813 gdk_draw_rectangle (clist->clist_window,
1815 (ctree)->style->bg_gc[GTK_STATE_PRELIGHT],
1820 tc_rectangle.height);
1823 xcenter = offset + (justification_factor * ctree->tree_indent / 2);
1825 get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL,
1827 if (bg_gc == clist->bg_gc)
1828 gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background);
1830 gdk_gc_set_clip_rectangle (bg_gc, crect);
1831 if (ctree_row->is_leaf)
1835 points[0].x = offset + justification_factor * TAB_SIZE;
1836 points[0].y = cell_rectangle->y;
1838 points[1].x = points[0].x - justification_factor * 4;
1839 points[1].y = points[0].y;
1841 points[2].x = points[1].x - justification_factor * 2;
1842 points[2].y = points[1].y + 3;
1844 points[3].x = points[2].x;
1845 points[3].y = points[2].y + clist->row_height - 5;
1847 points[4].x = points[3].x + justification_factor * 2;
1848 points[4].y = points[3].y + 3;
1850 points[5].x = points[4].x + justification_factor * 4;
1851 points[5].y = points[4].y;
1853 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6);
1854 gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6);
1858 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1859 offset - (justify_right * 2 * TAB_SIZE),
1861 2 * TAB_SIZE, clist->row_height,
1862 (90 + (180 * justify_right)) * 64, 180 * 64);
1863 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1864 offset - (justify_right * 2 * TAB_SIZE),
1866 2 * TAB_SIZE, clist->row_height,
1867 (90 + (180 * justify_right)) * 64, 180 * 64);
1869 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1870 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1872 offset += justification_factor * 3;
1875 xcenter = offset + justification_factor * PM_SIZE / 2;
1879 tree_rectangle.y = crect->y;
1880 tree_rectangle.height = crect->height;
1884 tree_rectangle.x = xcenter - PM_SIZE / 2 - 2;
1885 tree_rectangle.width = (clip_rectangle->x +
1886 clip_rectangle->width -tree_rectangle.x);
1890 tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2;
1891 tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 -
1895 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1901 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1903 offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
1904 offset_y = abs((cell_rectangle->y + clist->voffset) % 2);
1907 clip_rectangle->y--;
1908 clip_rectangle->height++;
1909 gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle);
1910 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1912 (ctree->show_stub || clist->row_list->data != ctree_row) ?
1913 cell_rectangle->y + offset_y : ycenter,
1915 (ctree_row->sibling) ? crect->y +crect->height : ycenter);
1917 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1918 xcenter + (justification_factor * offset_x), ycenter,
1919 xcenter + (justification_factor * (PM_SIZE / 2 + 2)),
1922 node = ctree_row->parent;
1925 xcenter -= (justification_factor * ctree->tree_indent);
1927 if (GTK_CTREE_ROW (node)->sibling)
1928 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1929 xcenter, cell_rectangle->y + offset_y,
1930 xcenter, crect->y + crect->height);
1931 node = GTK_CTREE_ROW (node)->parent;
1933 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1934 clip_rectangle->y++;
1935 clip_rectangle->height--;
1942 draw_row (GtkCList *clist,
1945 GtkCListRow *clist_row)
1950 GdkRectangle *crect;
1951 GdkRectangle row_rectangle;
1952 GdkRectangle cell_rectangle;
1953 GdkRectangle clip_rectangle;
1954 GdkRectangle intersect_rectangle;
1955 gint column_left = 0;
1956 gint column_right = 0;
1961 g_return_if_fail (clist != NULL);
1963 /* bail now if we arn't drawable yet */
1964 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
1967 widget = GTK_WIDGET (clist);
1968 ctree = GTK_CTREE (clist);
1970 /* if the function is passed the pointer to the row instead of null,
1971 * it avoids this expensive lookup */
1973 clist_row = (g_list_nth (clist->row_list, row))->data;
1975 /* rectangle of the entire row */
1976 row_rectangle.x = 0;
1977 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1978 row_rectangle.width = clist->clist_window_width;
1979 row_rectangle.height = clist->row_height;
1981 /* rectangle of the cell spacing above the row */
1982 cell_rectangle.x = 0;
1983 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1984 cell_rectangle.width = row_rectangle.width;
1985 cell_rectangle.height = CELL_SPACING;
1987 /* rectangle used to clip drawing operations, it's y and height
1988 * positions only need to be set once, so we set them once here.
1989 * the x and width are set withing the drawing loop below once per
1991 clip_rectangle.y = row_rectangle.y;
1992 clip_rectangle.height = row_rectangle.height;
1994 if (clist_row->state == GTK_STATE_NORMAL)
1996 state = GTK_STATE_PRELIGHT;
1997 if (clist_row->fg_set)
1998 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1999 if (clist_row->bg_set)
2000 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
2003 state = clist_row->state;
2005 gdk_gc_set_foreground (ctree->lines_gc,
2006 &widget->style->fg[clist_row->state]);
2008 /* draw the cell borders */
2011 rect = &intersect_rectangle;
2012 crect = &intersect_rectangle;
2014 if (gdk_rectangle_intersect (area, &cell_rectangle, crect))
2015 gdk_draw_rectangle (clist->clist_window,
2016 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2017 crect->x, crect->y, crect->width, crect->height);
2021 rect = &clip_rectangle;
2022 crect = &cell_rectangle;
2024 gdk_draw_rectangle (clist->clist_window,
2025 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2026 crect->x, crect->y, crect->width, crect->height);
2029 /* horizontal black lines */
2030 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2033 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
2034 clist->column[ctree->tree_column].area.width +
2036 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
2037 COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING);
2039 switch (clist->column[ctree->tree_column].justification)
2041 case GTK_JUSTIFY_CENTER:
2042 case GTK_JUSTIFY_FILL:
2043 case GTK_JUSTIFY_LEFT:
2044 offset = (column_left + ctree->tree_indent *
2045 (((GtkCTreeRow *)clist_row)->level - 1));
2047 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2048 MIN (offset + TAB_SIZE, column_right),
2050 clist->clist_window_width, cell_rectangle.y);
2052 case GTK_JUSTIFY_RIGHT:
2053 offset = (column_right - 1 - ctree->tree_indent *
2054 (((GtkCTreeRow *)clist_row)->level - 1));
2056 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2057 -1, cell_rectangle.y,
2058 MAX (offset - TAB_SIZE, column_left),
2064 /* the last row has to clear it's bottom cell spacing too */
2065 if (clist_row == clist->row_list_end->data)
2067 cell_rectangle.y += clist->row_height + CELL_SPACING;
2069 if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect))
2071 gdk_draw_rectangle (clist->clist_window,
2072 widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
2073 crect->x, crect->y, crect->width, crect->height);
2075 /* horizontal black lines */
2076 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2078 switch (clist->column[ctree->tree_column].justification)
2080 case GTK_JUSTIFY_CENTER:
2081 case GTK_JUSTIFY_FILL:
2082 case GTK_JUSTIFY_LEFT:
2083 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2084 MIN (column_left + TAB_SIZE + COLUMN_INSET +
2085 (((GtkCTreeRow *)clist_row)->level > 1) *
2086 MIN (ctree->tree_indent / 2, TAB_SIZE),
2089 clist->clist_window_width, cell_rectangle.y);
2091 case GTK_JUSTIFY_RIGHT:
2092 gdk_draw_line (clist->clist_window, ctree->lines_gc,
2093 -1, cell_rectangle.y,
2094 MAX (column_right - TAB_SIZE - 1 -
2096 (((GtkCTreeRow *)clist_row)->level > 1) *
2097 MIN (ctree->tree_indent / 2, TAB_SIZE),
2098 column_left - 1), cell_rectangle.y);
2105 /* iterate and draw all the columns (row cells) and draw their contents */
2106 for (i = 0; i < clist->columns; i++)
2117 gint row_center_offset;
2119 if (!clist->column[i].visible)
2122 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
2124 /* calculate clipping region */
2125 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
2126 clip_rectangle.width = clist->column[i].area.width;
2128 cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING;
2129 cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET +
2130 (1 + (i + 1 == clist->columns)) * CELL_SPACING);
2131 cell_rectangle.y = clip_rectangle.y;
2132 cell_rectangle.height = clip_rectangle.height;
2137 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
2138 &intersect_rectangle))
2140 if (i != ctree->tree_column)
2145 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
2146 crect->x, crect->y, crect->width, crect->height);
2148 /* calculate real width for column justification */
2149 switch (clist_row->cell[i].type)
2152 width = gdk_string_width
2153 (style->font, GTK_CELL_TEXT (clist_row->cell[i])->text);
2155 case GTK_CELL_PIXMAP:
2157 (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
2159 width = pixmap_width;
2161 case GTK_CELL_PIXTEXT:
2162 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
2164 (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2165 &pixmap_width, &height);
2167 width = (pixmap_width +
2168 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing);
2170 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
2172 string_width = gdk_string_width
2173 (style->font, GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2174 width += string_width;
2177 if (i == ctree->tree_column)
2178 width += (ctree->tree_indent *
2179 ((GtkCTreeRow *)clist_row)->level);
2186 switch (clist->column[i].justification)
2188 case GTK_JUSTIFY_LEFT:
2189 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
2191 case GTK_JUSTIFY_RIGHT:
2192 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
2193 clip_rectangle.width - width);
2195 case GTK_JUSTIFY_CENTER:
2196 case GTK_JUSTIFY_FILL:
2197 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
2198 (clip_rectangle.width / 2) - (width / 2));
2202 if (i != ctree->tree_column)
2204 offset += clist_row->cell[i].horizontal;
2205 switch (clist_row->cell[i].type)
2207 case GTK_CELL_PIXMAP:
2209 (clist->clist_window, &clip_rectangle, fg_gc,
2210 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
2211 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
2213 clip_rectangle.y + clist_row->cell[i].vertical +
2214 (clip_rectangle.height - height) / 2,
2215 pixmap_width, height);
2217 case GTK_CELL_PIXTEXT:
2218 offset = draw_cell_pixmap
2219 (clist->clist_window, &clip_rectangle, fg_gc,
2220 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2221 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
2223 clip_rectangle.y + clist_row->cell[i].vertical +
2224 (clip_rectangle.height - height) / 2,
2225 pixmap_width, height);
2226 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2228 if (style != GTK_WIDGET (clist)->style)
2229 row_center_offset = (((clist->row_height -
2230 style->font->ascent -
2231 style->font->descent - 1) / 2) +
2232 1.5 + style->font->ascent);
2234 row_center_offset = clist->row_center_offset;
2236 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
2238 (clist->clist_window, style->font, fg_gc,
2240 row_rectangle.y + row_center_offset +
2241 clist_row->cell[i].vertical,
2242 (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
2243 GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
2244 GTK_CELL_TEXT (clist_row->cell[i])->text);
2245 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2254 if (bg_gc == clist->bg_gc)
2255 gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
2257 /* draw ctree->tree_column */
2258 cell_rectangle.y -= CELL_SPACING;
2259 cell_rectangle.height += CELL_SPACING;
2261 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
2262 &intersect_rectangle))
2266 offset = gtk_ctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
2267 state, &clip_rectangle, &cell_rectangle,
2268 crect, area, style);
2271 offset = gtk_ctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
2272 style, &clip_rectangle, offset);
2274 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2275 offset -= ctree->tree_spacing;
2277 offset += ctree->tree_spacing;
2279 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2280 offset -= (pixmap_width + clist_row->cell[i].horizontal);
2282 offset += clist_row->cell[i].horizontal;
2284 old_offset = offset;
2285 offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
2286 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
2287 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
2289 clip_rectangle.y + clist_row->cell[i].vertical
2290 + (clip_rectangle.height - height) / 2,
2291 pixmap_width, height);
2295 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
2296 offset = (old_offset - string_width -
2297 GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing);
2299 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
2301 if (style != GTK_WIDGET (clist)->style)
2302 row_center_offset = (((clist->row_height - style->font->ascent -
2303 style->font->descent - 1) / 2) +
2304 1.5 + style->font->ascent);
2306 row_center_offset = clist->row_center_offset;
2308 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
2309 gdk_draw_string (clist->clist_window, style->font, fg_gc, offset,
2310 row_rectangle.y + row_center_offset +
2311 clist_row->cell[i].vertical,
2312 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
2314 gdk_gc_set_clip_rectangle (fg_gc, NULL);
2317 /* draw focus rectangle */
2318 if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
2321 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2322 row_rectangle.x, row_rectangle.y,
2323 row_rectangle.width - 1, row_rectangle.height - 1);
2324 else if (gdk_rectangle_intersect (area, &row_rectangle,
2325 &intersect_rectangle))
2327 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
2328 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
2329 row_rectangle.x, row_rectangle.y,
2330 row_rectangle.width - 1,
2331 row_rectangle.height - 1);
2332 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
2338 tree_draw_node (GtkCTree *ctree,
2343 clist = GTK_CLIST (ctree);
2345 if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
2350 work = GTK_CTREE_NODE (clist->row_list);
2351 while (work && work != node)
2353 work = GTK_CTREE_NODE_NEXT (work);
2356 if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
2357 GTK_CLIST_CLASS_FW (clist)->draw_row
2358 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2362 static GtkCTreeNode *
2363 gtk_ctree_last_visible (GtkCTree *ctree,
2371 work = GTK_CTREE_ROW (node)->children;
2373 if (!work || !GTK_CTREE_ROW (node)->expanded)
2376 while (GTK_CTREE_ROW (work)->sibling)
2377 work = GTK_CTREE_ROW (work)->sibling;
2379 return gtk_ctree_last_visible (ctree, work);
2383 gtk_ctree_link (GtkCTree *ctree,
2385 GtkCTreeNode *parent,
2386 GtkCTreeNode *sibling,
2387 gboolean update_focus_row)
2393 gboolean visible = FALSE;
2397 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
2398 g_return_if_fail (node != NULL);
2399 g_return_if_fail (node != sibling);
2400 g_return_if_fail (node != parent);
2402 clist = GTK_CLIST (ctree);
2404 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2406 if (clist->anchor != -1)
2407 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2409 g_list_free (clist->undo_selection);
2410 g_list_free (clist->undo_unselection);
2411 clist->undo_selection = NULL;
2412 clist->undo_unselection = NULL;
2415 for (rows = 1, list_end = (GList *)node; list_end->next;
2416 list_end = list_end->next)
2419 GTK_CTREE_ROW (node)->parent = parent;
2420 GTK_CTREE_ROW (node)->sibling = sibling;
2422 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
2423 GTK_CTREE_ROW (parent)->expanded)))
2426 clist->rows += rows;
2430 work = (GList *)(GTK_CTREE_ROW (parent)->children);
2432 work = clist->row_list;
2436 if (work != (GList *)sibling)
2438 while (GTK_CTREE_ROW (work)->sibling != sibling)
2439 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2440 GTK_CTREE_ROW (work)->sibling = node;
2443 if (sibling == GTK_CTREE_NODE (clist->row_list))
2444 clist->row_list = (GList *) node;
2445 if (GTK_CTREE_NODE_PREV (sibling) &&
2446 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2448 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
2449 list->next = (GList *)node;
2452 list = (GList *)node;
2453 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
2454 list_end->next = (GList *)sibling;
2455 list = (GList *)sibling;
2456 list->prev = list_end;
2457 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2458 GTK_CTREE_ROW (parent)->children = node;
2465 while (GTK_CTREE_ROW (work)->sibling)
2466 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2467 GTK_CTREE_ROW (work)->sibling = node;
2469 /* find last visible child of sibling */
2470 work = (GList *) gtk_ctree_last_visible (ctree,
2471 GTK_CTREE_NODE (work));
2473 list_end->next = work->next;
2475 list = work->next->prev = list_end;
2476 work->next = (GList *)node;
2477 list = (GList *)node;
2484 GTK_CTREE_ROW (parent)->children = node;
2485 list = (GList *)node;
2486 list->prev = (GList *)parent;
2487 if (GTK_CTREE_ROW (parent)->expanded)
2489 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
2490 if (GTK_CTREE_NODE_NEXT(parent))
2492 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
2493 list->prev = list_end;
2495 list = (GList *)parent;
2496 list->next = (GList *)node;
2499 list_end->next = NULL;
2503 clist->row_list = (GList *)node;
2504 list = (GList *)node;
2506 list_end->next = NULL;
2511 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2513 if (clist->row_list_end == NULL ||
2514 clist->row_list_end->next == (GList *)node)
2515 clist->row_list_end = list_end;
2517 if (visible && update_focus_row)
2521 pos = g_list_position (clist->row_list, (GList *)node);
2523 if (pos <= clist->focus_row)
2525 clist->focus_row += rows;
2526 clist->undo_anchor = clist->focus_row;
2532 gtk_ctree_unlink (GtkCTree *ctree,
2534 gboolean update_focus_row)
2541 GtkCTreeNode *parent;
2544 g_return_if_fail (ctree != NULL);
2545 g_return_if_fail (GTK_IS_CTREE (ctree));
2546 g_return_if_fail (node != NULL);
2548 clist = GTK_CLIST (ctree);
2550 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2552 if (clist->anchor != -1)
2553 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2555 g_list_free (clist->undo_selection);
2556 g_list_free (clist->undo_unselection);
2557 clist->undo_selection = NULL;
2558 clist->undo_unselection = NULL;
2561 visible = gtk_ctree_is_viewable (ctree, node);
2563 /* clist->row_list_end unlinked ? */
2565 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2566 (GTK_CTREE_ROW (node)->children &&
2567 gtk_ctree_is_ancestor (ctree, node,
2568 GTK_CTREE_NODE (clist->row_list_end)))))
2569 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
2573 level = GTK_CTREE_ROW (node)->level;
2574 work = GTK_CTREE_NODE_NEXT (node);
2575 while (work && GTK_CTREE_ROW (work)->level > level)
2577 work = GTK_CTREE_NODE_NEXT (work);
2583 clist->rows -= (rows + 1);
2585 if (update_focus_row)
2589 pos = g_list_position (clist->row_list, (GList *)node);
2590 if (pos + rows < clist->focus_row)
2591 clist->focus_row -= (rows + 1);
2592 else if (pos <= clist->focus_row)
2594 if (!GTK_CTREE_ROW (node)->sibling)
2595 clist->focus_row = MAX (pos - 1, 0);
2597 clist->focus_row = pos;
2599 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
2601 clist->undo_anchor = clist->focus_row;
2607 list = (GList *)GTK_CTREE_NODE_PREV (work);
2609 list = (GList *)work;
2610 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
2613 if (GTK_CTREE_NODE_PREV (node) &&
2614 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2616 list = (GList *)GTK_CTREE_NODE_PREV (node);
2617 list->next = (GList *)work;
2621 parent = GTK_CTREE_ROW (node)->parent;
2624 if (GTK_CTREE_ROW (parent)->children == node)
2626 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2627 if (!GTK_CTREE_ROW (parent)->children)
2628 gtk_ctree_collapse (ctree, parent);
2632 GtkCTreeNode *sibling;
2634 sibling = GTK_CTREE_ROW (parent)->children;
2635 while (GTK_CTREE_ROW (sibling)->sibling != node)
2636 sibling = GTK_CTREE_ROW (sibling)->sibling;
2637 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2642 if (clist->row_list == (GList *)node)
2643 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
2646 GtkCTreeNode *sibling;
2648 sibling = GTK_CTREE_NODE (clist->row_list);
2649 while (GTK_CTREE_ROW (sibling)->sibling != node)
2650 sibling = GTK_CTREE_ROW (sibling)->sibling;
2651 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2657 real_row_move (GtkCList *clist,
2664 g_return_if_fail (clist != NULL);
2665 g_return_if_fail (GTK_IS_CTREE (clist));
2667 if (GTK_CLIST_AUTO_SORT (clist))
2670 if (source_row < 0 || source_row >= clist->rows ||
2671 dest_row < 0 || dest_row >= clist->rows ||
2672 source_row == dest_row)
2675 ctree = GTK_CTREE (clist);
2676 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, source_row));
2678 if (source_row < dest_row)
2683 work = GTK_CTREE_ROW (node)->children;
2685 while (work && GTK_CTREE_ROW (work)->level > GTK_CTREE_ROW (node)->level)
2687 work = GTK_CTREE_NODE_NEXT (work);
2691 if (dest_row > clist->rows)
2692 dest_row = clist->rows;
2695 if (dest_row < clist->rows)
2697 GtkCTreeNode *sibling;
2699 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, dest_row));
2700 gtk_ctree_move (ctree, node, GTK_CTREE_ROW (sibling)->parent, sibling);
2703 gtk_ctree_move (ctree, node, NULL, NULL);
2707 real_tree_move (GtkCTree *ctree,
2709 GtkCTreeNode *new_parent,
2710 GtkCTreeNode *new_sibling)
2714 gboolean visible = FALSE;
2716 g_return_if_fail (ctree != NULL);
2717 g_return_if_fail (node != NULL);
2718 g_return_if_fail (!new_sibling ||
2719 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2721 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2724 /* new_parent != child of child */
2725 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2729 clist = GTK_CLIST (ctree);
2731 visible = gtk_ctree_is_viewable (ctree, node);
2733 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2735 if (clist->anchor != -1)
2736 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2738 g_list_free (clist->undo_selection);
2739 g_list_free (clist->undo_unselection);
2740 clist->undo_selection = NULL;
2741 clist->undo_unselection = NULL;
2744 if (GTK_CLIST_AUTO_SORT (clist))
2746 if (new_parent == GTK_CTREE_ROW (node)->parent)
2750 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2752 new_sibling = GTK_CTREE_NODE (clist->row_list);
2754 while (new_sibling && clist->compare
2755 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
2756 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2759 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2760 new_sibling == GTK_CTREE_ROW (node)->sibling)
2763 gtk_clist_freeze (clist);
2766 if (gtk_ctree_is_viewable (ctree, node) ||
2767 gtk_ctree_is_viewable (ctree, new_sibling))
2768 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2770 gtk_ctree_unlink (ctree, node, FALSE);
2771 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2775 while (work && !gtk_ctree_is_viewable (ctree, work))
2776 work = GTK_CTREE_ROW (work)->parent;
2777 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2778 clist->undo_anchor = clist->focus_row;
2781 if (clist->column[ctree->tree_column].auto_resize &&
2782 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
2783 (visible || gtk_ctree_is_viewable (ctree, node)))
2784 gtk_clist_set_column_width
2785 (clist, ctree->tree_column,
2786 gtk_clist_optimal_column_width (clist, ctree->tree_column));
2788 gtk_clist_thaw (clist);
2792 change_focus_row_expansion (GtkCTree *ctree,
2793 GtkCTreeExpansionType action)
2798 g_return_if_fail (ctree != NULL);
2799 g_return_if_fail (GTK_IS_CTREE (ctree));
2801 clist = GTK_CLIST (ctree);
2803 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2807 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2808 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2813 case GTK_CTREE_EXPANSION_EXPAND:
2814 gtk_ctree_expand (ctree, node);
2816 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2817 gtk_ctree_expand_recursive (ctree, node);
2819 case GTK_CTREE_EXPANSION_COLLAPSE:
2820 gtk_ctree_collapse (ctree, node);
2822 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2823 gtk_ctree_collapse_recursive (ctree, node);
2825 case GTK_CTREE_EXPANSION_TOGGLE:
2826 gtk_ctree_toggle_expansion (ctree, node);
2828 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2829 gtk_ctree_toggle_expansion_recursive (ctree, node);
2835 real_tree_expand (GtkCTree *ctree,
2840 GtkRequisition requisition;
2844 g_return_if_fail (ctree != NULL);
2845 g_return_if_fail (GTK_IS_CTREE (ctree));
2847 if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
2850 clist = GTK_CLIST (ctree);
2852 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2853 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2855 GTK_CTREE_ROW (node)->expanded = TRUE;
2856 level = GTK_CTREE_ROW (node)->level;
2858 visible = gtk_ctree_is_viewable (ctree, node);
2859 /* get cell width if tree_column is auto resized */
2860 if (visible && clist->column[ctree->tree_column].auto_resize &&
2861 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2862 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2863 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2865 /* unref/unset closed pixmap */
2866 if (GTK_CELL_PIXTEXT
2867 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2871 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2874 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2876 if (GTK_CELL_PIXTEXT
2877 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2881 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2883 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2887 /* set/ref opened pixmap */
2888 if (GTK_CTREE_ROW (node)->pixmap_opened)
2891 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2892 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
2894 if (GTK_CTREE_ROW (node)->mask_opened)
2896 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2897 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
2901 work = GTK_CTREE_ROW (node)->children;
2905 gint *cell_width = NULL;
2910 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2912 cell_width = g_new0 (gint, clist->columns);
2913 if (clist->column[ctree->tree_column].auto_resize)
2914 cell_width[ctree->tree_column] = requisition.width;
2917 while (GTK_CTREE_NODE_NEXT (work))
2919 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2921 /* search maximum cell widths of auto_resize columns */
2922 for (i = 0; i < clist->columns; i++)
2923 if (clist->column[i].auto_resize)
2925 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2926 (clist, >K_CTREE_ROW (work)->row, i, &requisition);
2927 cell_width[i] = MAX (requisition.width, cell_width[i]);
2931 work = GTK_CTREE_NODE_NEXT (work);
2935 list = (GList *)work;
2936 list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
2938 if (GTK_CTREE_NODE_NEXT (node))
2940 list = (GList *)GTK_CTREE_NODE_NEXT (node);
2941 list->prev = (GList *)work;
2944 clist->row_list_end = (GList *)work;
2946 list = (GList *)node;
2947 list->next = (GList *)(GTK_CTREE_ROW (node)->children);
2951 /* resize auto_resize columns if needed */
2952 for (i = 0; i < clist->columns; i++)
2953 if (clist->column[i].auto_resize &&
2954 cell_width[i] > clist->column[i].width)
2955 gtk_clist_set_column_width (clist, i, cell_width[i]);
2956 g_free (cell_width);
2958 /* update focus_row position */
2959 row = g_list_position (clist->row_list, (GList *)node);
2960 if (row < clist->focus_row)
2961 clist->focus_row += tmp + 1;
2963 clist->rows += tmp + 1;
2964 CLIST_REFRESH (clist);
2967 else if (visible && clist->column[ctree->tree_column].auto_resize)
2968 /* resize tree_column if needed */
2969 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2974 real_tree_collapse (GtkCTree *ctree,
2979 GtkRequisition requisition;
2983 g_return_if_fail (ctree != NULL);
2984 g_return_if_fail (GTK_IS_CTREE (ctree));
2986 if (!node || !GTK_CTREE_ROW (node)->expanded ||
2987 GTK_CTREE_ROW (node)->is_leaf)
2990 clist = GTK_CLIST (ctree);
2992 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2993 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2995 GTK_CTREE_ROW (node)->expanded = FALSE;
2996 level = GTK_CTREE_ROW (node)->level;
2998 visible = gtk_ctree_is_viewable (ctree, node);
2999 /* get cell width if tree_column is auto resized */
3000 if (visible && clist->column[ctree->tree_column].auto_resize &&
3001 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3002 GTK_CLIST_CLASS_FW (clist)->cell_size_request
3003 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
3005 /* unref/unset opened pixmap */
3006 if (GTK_CELL_PIXTEXT
3007 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
3011 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
3014 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
3016 if (GTK_CELL_PIXTEXT
3017 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
3021 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
3023 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
3027 /* set/ref closed pixmap */
3028 if (GTK_CTREE_ROW (node)->pixmap_closed)
3031 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
3032 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed);
3034 if (GTK_CTREE_ROW (node)->mask_closed)
3036 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
3037 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed);
3040 work = GTK_CTREE_ROW (node)->children;
3047 while (work && GTK_CTREE_ROW (work)->level > level)
3049 work = GTK_CTREE_NODE_NEXT (work);
3055 list = (GList *)node;
3056 list->next = (GList *)work;
3057 list = (GList *)GTK_CTREE_NODE_PREV (work);
3059 list = (GList *)work;
3060 list->prev = (GList *)node;
3064 list = (GList *)node;
3066 clist->row_list_end = (GList *)node;
3071 /* resize auto_resize columns if needed */
3072 auto_resize_columns (clist);
3074 row = g_list_position (clist->row_list, (GList *)node);
3075 if (row < clist->focus_row)
3076 clist->focus_row -= tmp;
3078 CLIST_REFRESH (clist);
3081 else if (visible && clist->column[ctree->tree_column].auto_resize &&
3082 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3083 /* resize tree_column if needed */
3084 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
3090 column_auto_resize (GtkCList *clist,
3091 GtkCListRow *clist_row,
3095 /* resize column if needed for auto_resize */
3096 GtkRequisition requisition;
3098 if (!clist->column[column].auto_resize ||
3099 GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3103 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3104 column, &requisition);
3106 requisition.width = 0;
3108 if (requisition.width > clist->column[column].width)
3109 gtk_clist_set_column_width (clist, column, requisition.width);
3110 else if (requisition.width < old_width &&
3111 old_width == clist->column[column].width)
3116 /* run a "gtk_clist_optimal_column_width" but break, if
3117 * the column doesn't shrink */
3118 if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
3119 new_width = (clist->column[column].button->requisition.width -
3120 (CELL_SPACING + (2 * COLUMN_INSET)));
3124 for (list = clist->row_list; list; list = list->next)
3126 GTK_CLIST_CLASS_FW (clist)->cell_size_request
3127 (clist, GTK_CLIST_ROW (list), column, &requisition);
3128 new_width = MAX (new_width, requisition.width);
3129 if (new_width == clist->column[column].width)
3132 if (new_width < clist->column[column].width)
3133 gtk_clist_set_column_width (clist, column, new_width);
3138 auto_resize_columns (GtkCList *clist)
3142 if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3145 for (i = 0; i < clist->columns; i++)
3146 column_auto_resize (clist, NULL, i, clist->column[i].width);
3150 cell_size_request (GtkCList *clist,
3151 GtkCListRow *clist_row,
3153 GtkRequisition *requisition)
3160 g_return_if_fail (clist != NULL);
3161 g_return_if_fail (GTK_IS_CTREE (clist));
3162 g_return_if_fail (requisition != NULL);
3164 ctree = GTK_CTREE (clist);
3166 get_cell_style (clist, clist_row, GTK_STATE_PRELIGHT, column, &style,
3169 switch (clist_row->cell[column].type)
3172 requisition->width =
3173 gdk_string_width (style->font,
3174 GTK_CELL_TEXT (clist_row->cell[column])->text);
3175 requisition->height = style->font->ascent + style->font->descent;
3177 case GTK_CELL_PIXTEXT:
3178 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
3180 gdk_window_get_size (GTK_CELL_PIXTEXT
3181 (clist_row->cell[column])->pixmap,
3183 width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
3188 requisition->width = width +
3189 gdk_string_width (style->font,
3190 GTK_CELL_TEXT (clist_row->cell[column])->text);
3192 requisition->height = MAX (style->font->ascent + style->font->descent,
3194 if (column == ctree->tree_column)
3196 requisition->width += (ctree->tree_spacing + ctree->tree_indent *
3197 (((GtkCTreeRow *) clist_row)->level - 1));
3198 switch (ctree->expander_style)
3200 case GTK_CTREE_EXPANDER_NONE:
3202 case GTK_CTREE_EXPANDER_TRIANGLE:
3203 requisition->width += PM_SIZE + 3;
3205 case GTK_CTREE_EXPANDER_SQUARE:
3206 case GTK_CTREE_EXPANDER_CIRCULAR:
3207 requisition->width += PM_SIZE + 1;
3210 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
3211 requisition->width += 3;
3214 case GTK_CELL_PIXMAP:
3215 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
3217 requisition->width = width;
3218 requisition->height = height;
3221 requisition->width = 0;
3222 requisition->height = 0;
3226 requisition->width += clist_row->cell[column].horizontal;
3227 requisition->height += clist_row->cell[column].vertical;
3231 set_cell_contents (GtkCList *clist,
3232 GtkCListRow *clist_row,
3240 gboolean visible = FALSE;
3242 GtkRequisition requisition;
3244 g_return_if_fail (clist != NULL);
3245 g_return_if_fail (GTK_IS_CTREE (clist));
3246 g_return_if_fail (clist_row != NULL);
3248 ctree = GTK_CTREE (clist);
3250 if (clist->column[column].auto_resize &&
3251 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3253 GtkCTreeNode *parent;
3255 parent = ((GtkCTreeRow *)clist_row)->parent;
3256 if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded &&
3257 gtk_ctree_is_viewable (ctree, parent)))
3260 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
3261 column, &requisition);
3265 switch (clist_row->cell[column].type)
3267 case GTK_CELL_EMPTY:
3271 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
3273 case GTK_CELL_PIXMAP:
3274 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
3275 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
3276 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
3278 case GTK_CELL_PIXTEXT:
3279 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
3280 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
3281 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
3284 (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
3285 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
3287 (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
3290 case GTK_CELL_WIDGET:
3298 clist_row->cell[column].type = GTK_CELL_EMPTY;
3299 if (column == ctree->tree_column && type != GTK_CELL_EMPTY)
3300 type = GTK_CELL_PIXTEXT;
3307 clist_row->cell[column].type = GTK_CELL_TEXT;
3308 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
3311 case GTK_CELL_PIXMAP:
3314 clist_row->cell[column].type = GTK_CELL_PIXMAP;
3315 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
3316 /* We set the mask even if it is NULL */
3317 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
3320 case GTK_CELL_PIXTEXT:
3321 if (column == ctree->tree_column)
3323 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3324 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3326 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3328 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL;
3331 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3332 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3336 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
3337 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
3340 else if (text && pixmap)
3342 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3343 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3344 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3345 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3346 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3353 if (visible && clist->column[column].auto_resize &&
3354 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3355 column_auto_resize (clist, clist_row, column, requisition.width);
3359 set_node_info (GtkCTree *ctree,
3363 GdkPixmap *pixmap_closed,
3364 GdkBitmap *mask_closed,
3365 GdkPixmap *pixmap_opened,
3366 GdkBitmap *mask_opened,
3370 if (GTK_CTREE_ROW (node)->pixmap_opened)
3372 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3373 if (GTK_CTREE_ROW (node)->mask_opened)
3374 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3376 if (GTK_CTREE_ROW (node)->pixmap_closed)
3378 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3379 if (GTK_CTREE_ROW (node)->mask_closed)
3380 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3383 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3384 GTK_CTREE_ROW (node)->mask_opened = NULL;
3385 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3386 GTK_CTREE_ROW (node)->mask_closed = NULL;
3390 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3392 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3396 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3398 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3401 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3402 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3404 if (GTK_CTREE_ROW (node)->expanded)
3405 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3406 text, spacing, pixmap_opened, mask_opened);
3408 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3409 text, spacing, pixmap_closed, mask_closed);
3413 tree_delete (GtkCTree *ctree,
3419 clist = GTK_CLIST (ctree);
3421 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3425 work = g_list_find (clist->selection, node);
3428 if (clist->selection_end && clist->selection_end == work)
3429 clist->selection_end = clist->selection_end->prev;
3430 clist->selection = g_list_remove (clist->selection, node);
3434 row_delete (ctree, GTK_CTREE_ROW (node));
3435 g_list_free_1 ((GList *)node);
3439 tree_delete_row (GtkCTree *ctree,
3443 row_delete (ctree, GTK_CTREE_ROW (node));
3444 g_list_free_1 ((GList *)node);
3448 tree_update_level (GtkCTree *ctree,
3455 if (GTK_CTREE_ROW (node)->parent)
3456 GTK_CTREE_ROW (node)->level =
3457 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3459 GTK_CTREE_ROW (node)->level = 1;
3463 tree_select (GtkCTree *ctree,
3467 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
3468 GTK_CTREE_ROW (node)->row.selectable)
3469 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3474 tree_unselect (GtkCTree *ctree,
3478 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3479 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3484 tree_expand (GtkCTree *ctree,
3488 if (node && !GTK_CTREE_ROW (node)->expanded)
3489 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3493 tree_collapse (GtkCTree *ctree,
3497 if (node && GTK_CTREE_ROW (node)->expanded)
3498 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3502 tree_collapse_to_depth (GtkCTree *ctree,
3506 if (node && GTK_CTREE_ROW (node)->level == depth)
3507 gtk_ctree_collapse_recursive (ctree, node);
3511 tree_toggle_expansion (GtkCTree *ctree,
3518 if (GTK_CTREE_ROW (node)->expanded)
3519 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3521 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3524 static GtkCTreeRow *
3525 row_new (GtkCTree *ctree)
3528 GtkCTreeRow *ctree_row;
3531 clist = GTK_CLIST (ctree);
3532 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3533 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3535 for (i = 0; i < clist->columns; i++)
3537 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3538 ctree_row->row.cell[i].vertical = 0;
3539 ctree_row->row.cell[i].horizontal = 0;
3540 ctree_row->row.cell[i].style = NULL;
3543 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3545 ctree_row->row.fg_set = FALSE;
3546 ctree_row->row.bg_set = FALSE;
3547 ctree_row->row.style = NULL;
3548 ctree_row->row.selectable = TRUE;
3549 ctree_row->row.state = GTK_STATE_NORMAL;
3550 ctree_row->row.data = NULL;
3551 ctree_row->row.destroy = NULL;
3553 ctree_row->level = 0;
3554 ctree_row->expanded = FALSE;
3555 ctree_row->parent = NULL;
3556 ctree_row->sibling = NULL;
3557 ctree_row->children = NULL;
3558 ctree_row->pixmap_closed = NULL;
3559 ctree_row->mask_closed = NULL;
3560 ctree_row->pixmap_opened = NULL;
3561 ctree_row->mask_opened = NULL;
3567 row_delete (GtkCTree *ctree,
3568 GtkCTreeRow *ctree_row)
3573 clist = GTK_CLIST (ctree);
3575 for (i = 0; i < clist->columns; i++)
3577 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3578 (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
3579 if (ctree_row->row.cell[i].style)
3581 if (GTK_WIDGET_REALIZED (ctree))
3582 gtk_style_detach (ctree_row->row.cell[i].style);
3583 gtk_style_unref (ctree_row->row.cell[i].style);
3587 if (ctree_row->row.style)
3589 if (GTK_WIDGET_REALIZED (ctree))
3590 gtk_style_detach (ctree_row->row.style);
3591 gtk_style_unref (ctree_row->row.style);
3594 if (ctree_row->pixmap_closed)
3596 gdk_pixmap_unref (ctree_row->pixmap_closed);
3597 if (ctree_row->mask_closed)
3598 gdk_bitmap_unref (ctree_row->mask_closed);
3601 if (ctree_row->pixmap_opened)
3603 gdk_pixmap_unref (ctree_row->pixmap_opened);
3604 if (ctree_row->mask_opened)
3605 gdk_bitmap_unref (ctree_row->mask_opened);
3608 if (ctree_row->row.destroy)
3609 ctree_row->row.destroy (ctree_row->row.data);
3611 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3612 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3616 real_select_row (GtkCList *clist,
3623 g_return_if_fail (clist != NULL);
3624 g_return_if_fail (GTK_IS_CTREE (clist));
3626 if ((node = g_list_nth (clist->row_list, row)) &&
3627 GTK_CTREE_ROW (node)->row.selectable)
3628 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3633 real_unselect_row (GtkCList *clist,
3640 g_return_if_fail (clist != NULL);
3641 g_return_if_fail (GTK_IS_CTREE (clist));
3643 if ((node = g_list_nth (clist->row_list, row)))
3644 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3649 real_tree_select (GtkCTree *ctree,
3655 GtkCTreeNode *sel_row;
3656 gboolean node_selected;
3658 g_return_if_fail (ctree != NULL);
3659 g_return_if_fail (GTK_IS_CTREE (ctree));
3661 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3662 !GTK_CTREE_ROW (node)->row.selectable)
3665 clist = GTK_CLIST (ctree);
3667 switch (clist->selection_mode)
3669 case GTK_SELECTION_SINGLE:
3670 case GTK_SELECTION_BROWSE:
3672 node_selected = FALSE;
3673 list = clist->selection;
3677 sel_row = list->data;
3680 if (node == sel_row)
3681 node_selected = TRUE;
3683 gtk_signal_emit (GTK_OBJECT (ctree),
3684 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3694 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3696 if (!clist->selection)
3698 clist->selection = g_list_append (clist->selection, node);
3699 clist->selection_end = clist->selection;
3702 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3704 tree_draw_node (ctree, node);
3708 real_tree_unselect (GtkCTree *ctree,
3714 g_return_if_fail (ctree != NULL);
3715 g_return_if_fail (GTK_IS_CTREE (ctree));
3717 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3720 clist = GTK_CLIST (ctree);
3722 if (clist->selection_end && clist->selection_end->data == node)
3723 clist->selection_end = clist->selection_end->prev;
3725 clist->selection = g_list_remove (clist->selection, node);
3727 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3729 tree_draw_node (ctree, node);
3733 tree_toggle_selection (GtkCTree *ctree,
3739 g_return_if_fail (ctree != NULL);
3740 g_return_if_fail (GTK_IS_CTREE (ctree));
3742 clist = GTK_CLIST (ctree);
3744 switch (clist->selection_mode)
3746 case GTK_SELECTION_SINGLE:
3747 case GTK_SELECTION_MULTIPLE:
3748 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3749 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3751 else if (node && GTK_CTREE_ROW (node)->row.selectable)
3752 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3756 case GTK_SELECTION_BROWSE:
3757 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL &&
3758 GTK_CTREE_ROW (node)->row.selectable)
3759 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3763 case GTK_SELECTION_EXTENDED:
3769 select_row_recursive (GtkCTree *ctree,
3773 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3774 !GTK_CTREE_ROW (node)->row.selectable)
3777 GTK_CLIST (ctree)->undo_unselection =
3778 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3779 gtk_ctree_select (ctree, node);
3783 real_select_all (GtkCList *clist)
3788 g_return_if_fail (clist != NULL);
3789 g_return_if_fail (GTK_IS_CTREE (clist));
3791 ctree = GTK_CTREE (clist);
3793 switch (clist->selection_mode)
3795 case GTK_SELECTION_SINGLE:
3796 case GTK_SELECTION_BROWSE:
3799 case GTK_SELECTION_EXTENDED:
3801 gtk_clist_freeze (clist);
3803 g_list_free (clist->undo_selection);
3804 g_list_free (clist->undo_unselection);
3805 clist->undo_selection = NULL;
3806 clist->undo_unselection = NULL;
3808 clist->anchor_state = GTK_STATE_SELECTED;
3810 clist->drag_pos = -1;
3811 clist->undo_anchor = clist->focus_row;
3813 for (node = GTK_CTREE_NODE (clist->row_list); node;
3814 node = GTK_CTREE_NODE_NEXT (node))
3815 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3817 gtk_clist_thaw (clist);
3820 case GTK_SELECTION_MULTIPLE:
3821 gtk_ctree_select_recursive (ctree, NULL);
3827 real_unselect_all (GtkCList *clist)
3833 g_return_if_fail (clist != NULL);
3834 g_return_if_fail (GTK_IS_CTREE (clist));
3836 ctree = GTK_CTREE (clist);
3838 switch (clist->selection_mode)
3840 case GTK_SELECTION_BROWSE:
3841 if (clist->focus_row >= 0)
3845 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3850 case GTK_SELECTION_EXTENDED:
3851 g_list_free (clist->undo_selection);
3852 g_list_free (clist->undo_unselection);
3853 clist->undo_selection = NULL;
3854 clist->undo_unselection = NULL;
3857 clist->drag_pos = -1;
3858 clist->undo_anchor = clist->focus_row;
3865 list = clist->selection;
3871 gtk_ctree_unselect (ctree, node);
3876 ctree_is_hot_spot (GtkCTree *ctree,
3882 GtkCTreeRow *tree_row;
3884 GtkCellPixText *cell;
3888 g_return_val_if_fail (ctree != NULL, FALSE);
3889 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3890 g_return_val_if_fail (node != NULL, FALSE);
3892 clist = GTK_CLIST (ctree);
3894 if (!clist->column[ctree->tree_column].visible ||
3895 ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
3898 tree_row = GTK_CTREE_ROW (node);
3900 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3902 yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
3903 (clist->row_height - 1) % 2);
3905 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3906 xl = (clist->column[ctree->tree_column].area.x +
3907 clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
3908 (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
3909 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3911 xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
3912 (tree_row->level - 1) * ctree->tree_indent +
3913 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3915 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3918 /***********************************************************
3919 ***********************************************************
3920 *** Public interface ***
3921 ***********************************************************
3922 ***********************************************************/
3925 /***********************************************************
3926 * Creation, insertion, deletion *
3927 ***********************************************************/
3930 gtk_ctree_construct (GtkCTree *ctree,
3937 g_return_if_fail (ctree != NULL);
3938 g_return_if_fail (GTK_IS_CTREE (ctree));
3939 g_return_if_fail (GTK_OBJECT_CONSTRUCTED (ctree) == FALSE);
3941 clist = GTK_CLIST (ctree);
3943 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
3944 sizeof (GtkCTreeRow),
3945 sizeof (GtkCTreeRow)
3946 * CLIST_OPTIMUM_SIZE,
3949 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
3950 sizeof (GtkCell) * columns,
3951 sizeof (GtkCell) * columns
3952 * CLIST_OPTIMUM_SIZE,
3955 ctree->tree_column = tree_column;
3957 gtk_clist_construct (clist, columns, titles);
3961 gtk_ctree_new_with_titles (gint columns,
3967 g_return_val_if_fail (columns > 0, NULL);
3968 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3970 widget = gtk_type_new (GTK_TYPE_CTREE);
3971 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
3977 gtk_ctree_new (gint columns,
3980 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3984 real_insert_row (GtkCList *clist,
3988 GtkCTreeNode *parent = NULL;
3989 GtkCTreeNode *sibling;
3992 g_return_val_if_fail (clist != NULL, -1);
3993 g_return_val_if_fail (GTK_IS_CTREE (clist), -1);
3995 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3997 parent = GTK_CTREE_ROW (sibling)->parent;
3999 node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5,
4000 NULL, NULL, NULL, NULL, TRUE, FALSE);
4002 if (GTK_CLIST_AUTO_SORT (clist) || !sibling)
4003 return g_list_position (clist->row_list, (GList *) node);
4009 gtk_ctree_insert_node (GtkCTree *ctree,
4010 GtkCTreeNode *parent,
4011 GtkCTreeNode *sibling,
4014 GdkPixmap *pixmap_closed,
4015 GdkBitmap *mask_closed,
4016 GdkPixmap *pixmap_opened,
4017 GdkBitmap *mask_opened,
4022 GtkCTreeRow *new_row;
4027 g_return_val_if_fail (ctree != NULL, NULL);
4028 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4030 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
4032 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
4035 clist = GTK_CLIST (ctree);
4037 /* create the row */
4038 new_row = row_new (ctree);
4039 list = g_list_alloc ();
4040 list->data = new_row;
4041 node = GTK_CTREE_NODE (list);
4044 for (i = 0; i < clist->columns; i++)
4045 if (text[i] && i != ctree->tree_column)
4046 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4047 (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
4049 set_node_info (ctree, node, text ?
4050 text[ctree->tree_column] : NULL, spacing, pixmap_closed,
4051 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
4053 /* sorted insertion */
4054 if (GTK_CLIST_AUTO_SORT (clist))
4057 sibling = GTK_CTREE_ROW (parent)->children;
4059 sibling = GTK_CTREE_NODE (clist->row_list);
4061 while (sibling && clist->compare
4062 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
4063 sibling = GTK_CTREE_ROW (sibling)->sibling;
4066 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
4068 if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
4069 gtk_ctree_is_viewable (ctree, node))
4071 for (i = 0; i < clist->columns; i++)
4072 if (clist->column[i].auto_resize)
4073 column_auto_resize (clist, &(new_row->row), i, 0);
4076 CLIST_REFRESH (clist);
4082 gtk_ctree_insert_gnode (GtkCTree *ctree,
4083 GtkCTreeNode *parent,
4084 GtkCTreeNode *sibling,
4086 GtkCTreeGNodeFunc func,
4090 GtkCTreeNode *cnode = NULL;
4091 GtkCTreeNode *child = NULL;
4092 GtkCTreeNode *new_child;
4097 g_return_val_if_fail (ctree != NULL, NULL);
4098 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4099 g_return_val_if_fail (gnode != NULL, NULL);
4100 g_return_val_if_fail (func != NULL, NULL);
4102 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
4104 clist = GTK_CLIST (ctree);
4107 depth = GTK_CTREE_ROW (parent)->level + 1;
4109 list = g_list_alloc ();
4110 list->data = row_new (ctree);
4111 cnode = GTK_CTREE_NODE (list);
4113 gtk_clist_freeze (clist);
4115 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
4117 if (!func (ctree, depth, gnode, cnode, data))
4119 tree_delete_row (ctree, cnode, NULL);
4123 if (GTK_CLIST_AUTO_SORT (clist))
4126 sibling = GTK_CTREE_ROW (parent)->children;
4128 sibling = GTK_CTREE_NODE (clist->row_list);
4130 while (sibling && clist->compare
4131 (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
4132 sibling = GTK_CTREE_ROW (sibling)->sibling;
4135 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
4137 for (work = g_node_last_child (gnode); work; work = work->prev)
4139 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
4145 gtk_clist_thaw (clist);
4151 gtk_ctree_export_to_gnode (GtkCTree *ctree,
4155 GtkCTreeGNodeFunc func,
4163 g_return_val_if_fail (ctree != NULL, NULL);
4164 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4165 g_return_val_if_fail (node != NULL, NULL);
4166 g_return_val_if_fail (func != NULL, NULL);
4169 g_return_val_if_fail (parent != NULL, NULL);
4170 g_return_val_if_fail (sibling->parent == parent, NULL);
4173 gnode = g_node_new (NULL);
4174 depth = g_node_depth (parent) + 1;
4176 if (!func (ctree, depth, gnode, node, data))
4178 g_node_destroy (gnode);
4183 g_node_insert_before (parent, sibling, gnode);
4185 for (work = GTK_CTREE_ROW (node)->children, new_sibling = NULL; work;
4186 work = GTK_CTREE_NODE_NEXT (work))
4188 sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling,
4191 new_sibling = sibling;
4193 g_node_reverse_children (gnode);
4199 real_remove_row (GtkCList *clist,
4204 g_return_if_fail (clist != NULL);
4205 g_return_if_fail (GTK_IS_CTREE (clist));
4207 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
4210 gtk_ctree_remove_node (GTK_CTREE (clist), node);
4214 gtk_ctree_remove_node (GtkCTree *ctree,
4219 g_return_if_fail (ctree != NULL);
4220 g_return_if_fail (GTK_IS_CTREE (ctree));
4222 clist = GTK_CLIST (ctree);
4224 gtk_clist_freeze (clist);
4230 visible = gtk_ctree_is_viewable (ctree, node);
4231 gtk_ctree_unlink (ctree, node, TRUE);
4232 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
4234 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
4235 clist->selection_mode == GTK_SELECTION_EXTENDED) &&
4236 !clist->selection && clist->focus_row >= 0)
4237 gtk_clist_select_row (clist, clist->focus_row, -1);
4239 auto_resize_columns (clist);
4242 gtk_clist_clear (clist);
4244 gtk_clist_thaw (clist);
4248 real_clear (GtkCList *clist)
4254 g_return_if_fail (clist != NULL);
4255 g_return_if_fail (GTK_IS_CTREE (clist));
4257 ctree = GTK_CTREE (clist);
4259 ctree->drag_row = -1;
4260 ctree->drag_rect = FALSE;
4261 ctree->in_drag = FALSE;
4262 ctree->drag_source = NULL;
4263 ctree->drag_target = NULL;
4264 ctree->drag_icon = NULL;
4266 /* remove all rows */
4267 work = GTK_CTREE_NODE (clist->row_list);
4268 clist->row_list = NULL;
4269 clist->row_list_end = NULL;
4271 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4275 work = GTK_CTREE_ROW (work)->sibling;
4276 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
4279 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4281 (parent_class->clear) (clist);
4285 /***********************************************************
4286 * Generic recursive functions, querying / finding tree *
4288 ***********************************************************/
4292 gtk_ctree_post_recursive (GtkCTree *ctree,
4300 g_return_if_fail (ctree != NULL);
4301 g_return_if_fail (GTK_IS_CTREE (ctree));
4302 g_return_if_fail (func != NULL);
4305 work = GTK_CTREE_ROW (node)->children;
4307 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4311 tmp = GTK_CTREE_ROW (work)->sibling;
4312 gtk_ctree_post_recursive (ctree, work, func, data);
4317 func (ctree, node, data);
4321 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
4330 g_return_if_fail (ctree != NULL);
4331 g_return_if_fail (GTK_IS_CTREE (ctree));
4332 g_return_if_fail (func != NULL);
4336 gtk_ctree_post_recursive (ctree, node, func, data);
4341 work = GTK_CTREE_ROW (node)->children;
4343 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4345 if (work && GTK_CTREE_ROW (work)->level <= depth)
4349 tmp = GTK_CTREE_ROW (work)->sibling;
4350 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
4355 if (node && GTK_CTREE_ROW (node)->level <= depth)
4356 func (ctree, node, data);
4360 gtk_ctree_pre_recursive (GtkCTree *ctree,
4368 g_return_if_fail (ctree != NULL);
4369 g_return_if_fail (GTK_IS_CTREE (ctree));
4370 g_return_if_fail (func != NULL);
4374 work = GTK_CTREE_ROW (node)->children;
4375 func (ctree, node, data);
4378 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4382 tmp = GTK_CTREE_ROW (work)->sibling;
4383 gtk_ctree_pre_recursive (ctree, work, func, data);
4389 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4398 g_return_if_fail (ctree != NULL);
4399 g_return_if_fail (GTK_IS_CTREE (ctree));
4400 g_return_if_fail (func != NULL);
4404 gtk_ctree_pre_recursive (ctree, node, func, data);
4410 work = GTK_CTREE_ROW (node)->children;
4411 if (GTK_CTREE_ROW (node)->level <= depth)
4412 func (ctree, node, data);
4415 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4417 if (work && GTK_CTREE_ROW (work)->level <= depth)
4421 tmp = GTK_CTREE_ROW (work)->sibling;
4422 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4429 gtk_ctree_is_viewable (GtkCTree *ctree,
4434 g_return_val_if_fail (ctree != NULL, FALSE);
4435 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4436 g_return_val_if_fail (node != NULL, FALSE);
4438 work = GTK_CTREE_ROW (node);
4440 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4441 work = GTK_CTREE_ROW (work->parent);
4450 gtk_ctree_last (GtkCTree *ctree,
4453 g_return_val_if_fail (ctree != NULL, NULL);
4454 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4459 while (GTK_CTREE_ROW (node)->sibling)
4460 node = GTK_CTREE_ROW (node)->sibling;
4462 if (GTK_CTREE_ROW (node)->children)
4463 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4469 gtk_ctree_find_node_ptr (GtkCTree *ctree,
4470 GtkCTreeRow *ctree_row)
4474 g_return_val_if_fail (ctree != NULL, FALSE);
4475 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4476 g_return_val_if_fail (ctree_row != NULL, FALSE);
4478 if (ctree_row->parent)
4479 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4481 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4483 while (GTK_CTREE_ROW (node) != ctree_row)
4484 node = GTK_CTREE_ROW (node)->sibling;
4490 gtk_ctree_node_nth (GtkCTree *ctree,
4493 g_return_val_if_fail (ctree != NULL, NULL);
4494 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4496 if ((row < 0) || (row >= GTK_CLIST(ctree)->rows))
4499 return GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
4503 gtk_ctree_find (GtkCTree *ctree,
4505 GtkCTreeNode *child)
4511 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4517 if (GTK_CTREE_ROW (node)->children)
4519 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4522 node = GTK_CTREE_ROW (node)->sibling;
4528 gtk_ctree_is_ancestor (GtkCTree *ctree,
4530 GtkCTreeNode *child)
4532 g_return_val_if_fail (node != NULL, FALSE);
4534 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4538 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4545 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4549 if (GTK_CTREE_ROW (node)->row.data == data)
4551 if (GTK_CTREE_ROW (node)->children &&
4552 (work = gtk_ctree_find_by_row_data
4553 (ctree, GTK_CTREE_ROW (node)->children, data)))
4555 node = GTK_CTREE_ROW (node)->sibling;
4561 gtk_ctree_find_all_by_row_data (GtkCTree *ctree,
4567 g_return_val_if_fail (ctree != NULL, NULL);
4568 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4570 /* if node == NULL then look in the whole tree */
4572 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4576 if (GTK_CTREE_ROW (node)->row.data == data)
4577 list = g_list_append (list, node);
4579 if (GTK_CTREE_ROW (node)->children)
4583 sub_list = gtk_ctree_find_all_by_row_data (ctree,
4587 list = g_list_concat (list, sub_list);
4589 node = GTK_CTREE_ROW (node)->sibling;
4595 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4602 g_return_val_if_fail (func != NULL, NULL);
4605 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4609 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4611 if (GTK_CTREE_ROW (node)->children &&
4612 (work = gtk_ctree_find_by_row_data_custom
4613 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4615 node = GTK_CTREE_ROW (node)->sibling;
4621 gtk_ctree_find_all_by_row_data_custom (GtkCTree *ctree,
4628 g_return_val_if_fail (ctree != NULL, NULL);
4629 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4630 g_return_val_if_fail (func != NULL, NULL);
4632 /* if node == NULL then look in the whole tree */
4634 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4638 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4639 list = g_list_append (list, node);
4641 if (GTK_CTREE_ROW (node)->children)
4645 sub_list = gtk_ctree_find_all_by_row_data_custom (ctree,
4650 list = g_list_concat (list, sub_list);
4652 node = GTK_CTREE_ROW (node)->sibling;
4658 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4666 g_return_val_if_fail (ctree != NULL, FALSE);
4667 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4669 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4670 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4671 return ctree_is_hot_spot (ctree, node, row, x, y);
4677 /***********************************************************
4678 * Tree signals : move, expand, collapse, (un)select *
4679 ***********************************************************/
4683 gtk_ctree_move (GtkCTree *ctree,
4685 GtkCTreeNode *new_parent,
4686 GtkCTreeNode *new_sibling)
4688 g_return_if_fail (ctree != NULL);
4689 g_return_if_fail (GTK_IS_CTREE (ctree));
4690 g_return_if_fail (node != NULL);
4692 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4693 new_parent, new_sibling);
4697 gtk_ctree_expand (GtkCTree *ctree,
4700 g_return_if_fail (ctree != NULL);
4701 g_return_if_fail (GTK_IS_CTREE (ctree));
4702 g_return_if_fail (node != NULL);
4704 if (GTK_CTREE_ROW (node)->is_leaf)
4707 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4711 gtk_ctree_expand_recursive (GtkCTree *ctree,
4715 gboolean thaw = FALSE;
4717 g_return_if_fail (ctree != NULL);
4718 g_return_if_fail (GTK_IS_CTREE (ctree));
4720 clist = GTK_CLIST (ctree);
4722 if (node && GTK_CTREE_ROW (node)->is_leaf)
4725 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4727 gtk_clist_freeze (clist);
4731 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4734 gtk_clist_thaw (clist);
4738 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4743 gboolean thaw = FALSE;
4745 g_return_if_fail (ctree != NULL);
4746 g_return_if_fail (GTK_IS_CTREE (ctree));
4748 clist = GTK_CLIST (ctree);
4750 if (node && GTK_CTREE_ROW (node)->is_leaf)
4753 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4755 gtk_clist_freeze (clist);
4759 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4760 GTK_CTREE_FUNC (tree_expand), NULL);
4763 gtk_clist_thaw (clist);
4767 gtk_ctree_collapse (GtkCTree *ctree,
4770 g_return_if_fail (ctree != NULL);
4771 g_return_if_fail (GTK_IS_CTREE (ctree));
4772 g_return_if_fail (node != NULL);
4774 if (GTK_CTREE_ROW (node)->is_leaf)
4777 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4781 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4785 gboolean thaw = FALSE;
4788 g_return_if_fail (ctree != NULL);
4789 g_return_if_fail (GTK_IS_CTREE (ctree));
4791 if (node && GTK_CTREE_ROW (node)->is_leaf)
4794 clist = GTK_CLIST (ctree);
4796 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4798 gtk_clist_freeze (clist);
4802 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4803 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4804 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4805 for (i = 0; i < clist->columns; i++)
4806 if (clist->column[i].auto_resize)
4807 gtk_clist_set_column_width (clist, i,
4808 gtk_clist_optimal_column_width (clist, i));
4811 gtk_clist_thaw (clist);
4815 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4820 gboolean thaw = FALSE;
4823 g_return_if_fail (ctree != NULL);
4824 g_return_if_fail (GTK_IS_CTREE (ctree));
4826 if (node && GTK_CTREE_ROW (node)->is_leaf)
4829 clist = GTK_CLIST (ctree);
4831 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4833 gtk_clist_freeze (clist);
4837 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4838 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4839 GTK_CTREE_FUNC (tree_collapse_to_depth),
4840 GINT_TO_POINTER (depth));
4841 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4842 for (i = 0; i < clist->columns; i++)
4843 if (clist->column[i].auto_resize)
4844 gtk_clist_set_column_width (clist, i,
4845 gtk_clist_optimal_column_width (clist, i));
4848 gtk_clist_thaw (clist);
4852 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4855 g_return_if_fail (ctree != NULL);
4856 g_return_if_fail (GTK_IS_CTREE (ctree));
4857 g_return_if_fail (node != NULL);
4859 if (GTK_CTREE_ROW (node)->is_leaf)
4862 tree_toggle_expansion (ctree, node, NULL);
4866 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4870 gboolean thaw = FALSE;
4872 g_return_if_fail (ctree != NULL);
4873 g_return_if_fail (GTK_IS_CTREE (ctree));
4875 if (node && GTK_CTREE_ROW (node)->is_leaf)
4878 clist = GTK_CLIST (ctree);
4880 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4882 gtk_clist_freeze (clist);
4886 gtk_ctree_post_recursive (ctree, node,
4887 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4890 gtk_clist_thaw (clist);
4894 gtk_ctree_select (GtkCTree *ctree,
4897 g_return_if_fail (ctree != NULL);
4898 g_return_if_fail (GTK_IS_CTREE (ctree));
4899 g_return_if_fail (node != NULL);
4901 if (GTK_CTREE_ROW (node)->row.selectable)
4902 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4907 gtk_ctree_unselect (GtkCTree *ctree,
4910 g_return_if_fail (ctree != NULL);
4911 g_return_if_fail (GTK_IS_CTREE (ctree));
4912 g_return_if_fail (node != NULL);
4914 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4919 gtk_ctree_select_recursive (GtkCTree *ctree,
4922 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4926 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4929 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4933 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4938 gboolean thaw = FALSE;
4940 g_return_if_fail (ctree != NULL);
4941 g_return_if_fail (GTK_IS_CTREE (ctree));
4943 clist = GTK_CLIST (ctree);
4946 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4947 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4948 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4951 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4953 gtk_clist_freeze (clist);
4957 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4959 if (clist->anchor != -1)
4960 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4962 g_list_free (clist->undo_selection);
4963 g_list_free (clist->undo_unselection);
4964 clist->undo_selection = NULL;
4965 clist->undo_unselection = NULL;
4969 gtk_ctree_post_recursive (ctree, node,
4970 GTK_CTREE_FUNC (tree_select), NULL);
4972 gtk_ctree_post_recursive (ctree, node,
4973 GTK_CTREE_FUNC (tree_unselect), NULL);
4976 gtk_clist_thaw (clist);
4980 /***********************************************************
4981 * Analogons of GtkCList functions *
4982 ***********************************************************/
4986 gtk_ctree_node_set_text (GtkCTree *ctree,
4993 g_return_if_fail (ctree != NULL);
4994 g_return_if_fail (GTK_IS_CTREE (ctree));
4995 g_return_if_fail (node != NULL);
4997 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5000 clist = GTK_CLIST (ctree);
5002 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
5003 (clist, &(GTK_CTREE_ROW(node)->row), column, GTK_CELL_TEXT,
5004 text, 0, NULL, NULL);
5006 tree_draw_node (ctree, node);
5010 gtk_ctree_node_set_pixmap (GtkCTree *ctree,
5018 g_return_if_fail (ctree != NULL);
5019 g_return_if_fail (GTK_IS_CTREE (ctree));
5020 g_return_if_fail (node != NULL);
5021 g_return_if_fail (pixmap != NULL);
5023 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5026 gdk_pixmap_ref (pixmap);
5028 gdk_pixmap_ref (mask);
5030 clist = GTK_CLIST (ctree);
5032 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
5033 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP,
5034 NULL, 0, pixmap, mask);
5036 tree_draw_node (ctree, node);
5040 gtk_ctree_node_set_pixtext (GtkCTree *ctree,
5050 g_return_if_fail (ctree != NULL);
5051 g_return_if_fail (GTK_IS_CTREE (ctree));
5052 g_return_if_fail (node != NULL);
5053 if (column != ctree->tree_column)
5054 g_return_if_fail (pixmap != NULL);
5055 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5058 clist = GTK_CLIST (ctree);
5062 gdk_pixmap_ref (pixmap);
5064 gdk_pixmap_ref (mask);
5067 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
5068 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT,
5069 text, spacing, pixmap, mask);
5071 tree_draw_node (ctree, node);
5075 gtk_ctree_set_node_info (GtkCTree *ctree,
5079 GdkPixmap *pixmap_closed,
5080 GdkBitmap *mask_closed,
5081 GdkPixmap *pixmap_opened,
5082 GdkBitmap *mask_opened,
5087 gboolean old_expanded;
5089 g_return_if_fail (ctree != NULL);
5090 g_return_if_fail (GTK_IS_CTREE (ctree));
5091 g_return_if_fail (node != NULL);
5093 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
5094 old_expanded = GTK_CTREE_ROW (node)->expanded;
5096 if (is_leaf && GTK_CTREE_ROW (node)->children)
5101 work = GTK_CTREE_ROW (node)->children;
5105 work = GTK_CTREE_ROW(work)->sibling;
5106 gtk_ctree_remove_node (ctree, ptr);
5110 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
5111 pixmap_opened, mask_opened, is_leaf, expanded);
5113 if (!is_leaf && !old_leaf)
5115 GTK_CTREE_ROW (node)->expanded = old_expanded;
5116 if (expanded && !old_expanded)
5117 gtk_ctree_expand (ctree, node);
5118 else if (!expanded && old_expanded)
5119 gtk_ctree_collapse (ctree, node);
5122 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
5124 tree_draw_node (ctree, node);
5128 gtk_ctree_node_set_shift (GtkCTree *ctree,
5135 GtkRequisition requisition;
5136 gboolean visible = FALSE;
5138 g_return_if_fail (ctree != NULL);
5139 g_return_if_fail (GTK_IS_CTREE (ctree));
5140 g_return_if_fail (node != NULL);
5142 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5145 clist = GTK_CLIST (ctree);
5147 if (clist->column[column].auto_resize &&
5148 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5150 visible = gtk_ctree_is_viewable (ctree, node);
5152 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5153 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5156 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
5157 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
5160 column_auto_resize (clist, >K_CTREE_ROW (node)->row,
5161 column, requisition.width);
5163 tree_draw_node (ctree, node);
5167 gtk_ctree_node_set_selectable (GtkCTree *ctree,
5169 gboolean selectable)
5171 g_return_if_fail (ctree != NULL);
5172 g_return_if_fail (GTK_IS_CTREE (ctree));
5173 g_return_if_fail (node != NULL);
5175 if (selectable == GTK_CTREE_ROW (node)->row.selectable)
5178 GTK_CTREE_ROW (node)->row.selectable = selectable;
5180 if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5184 clist = GTK_CLIST (ctree);
5186 if (clist->anchor >= 0 &&
5187 clist->selection_mode == GTK_SELECTION_EXTENDED)
5189 if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
5191 GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
5192 gtk_grab_remove (GTK_WIDGET (clist));
5193 gdk_pointer_ungrab (GDK_CURRENT_TIME);
5196 gtk_timeout_remove (clist->htimer);
5201 gtk_timeout_remove (clist->vtimer);
5205 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5207 gtk_ctree_unselect (ctree, node);
5212 gtk_ctree_node_get_selectable (GtkCTree *ctree,
5215 g_return_val_if_fail (node != NULL, FALSE);
5217 return GTK_CTREE_ROW (node)->row.selectable;
5221 gtk_ctree_node_get_cell_type (GtkCTree *ctree,
5225 g_return_val_if_fail (ctree != NULL, -1);
5226 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
5227 g_return_val_if_fail (node != NULL, -1);
5229 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5232 return GTK_CTREE_ROW (node)->row.cell[column].type;
5236 gtk_ctree_node_get_text (GtkCTree *ctree,
5241 g_return_val_if_fail (ctree != NULL, 0);
5242 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5243 g_return_val_if_fail (node != NULL, 0);
5245 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5248 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
5252 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
5258 gtk_ctree_node_get_pixmap (GtkCTree *ctree,
5264 g_return_val_if_fail (ctree != NULL, 0);
5265 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5266 g_return_val_if_fail (node != NULL, 0);
5268 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5271 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
5275 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
5277 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
5283 gtk_ctree_node_get_pixtext (GtkCTree *ctree,
5291 g_return_val_if_fail (ctree != NULL, 0);
5292 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5293 g_return_val_if_fail (node != NULL, 0);
5295 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5298 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
5302 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
5304 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
5305 (node)->row.cell[column])->spacing;
5307 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
5308 (node)->row.cell[column])->pixmap;
5310 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
5316 gtk_ctree_get_node_info (GtkCTree *ctree,
5320 GdkPixmap **pixmap_closed,
5321 GdkBitmap **mask_closed,
5322 GdkPixmap **pixmap_opened,
5323 GdkBitmap **mask_opened,
5327 g_return_val_if_fail (ctree != NULL, 0);
5328 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
5329 g_return_val_if_fail (node != NULL, 0);
5332 *text = GTK_CELL_PIXTEXT
5333 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
5335 *spacing = GTK_CELL_PIXTEXT
5336 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
5338 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
5340 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
5342 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
5344 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
5346 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
5348 *expanded = GTK_CTREE_ROW (node)->expanded;
5354 gtk_ctree_node_set_cell_style (GtkCTree *ctree,
5360 GtkRequisition requisition;
5361 gboolean visible = FALSE;
5363 g_return_if_fail (ctree != NULL);
5364 g_return_if_fail (GTK_IS_CTREE (ctree));
5365 g_return_if_fail (node != NULL);
5367 clist = GTK_CLIST (ctree);
5369 if (column < 0 || column >= clist->columns)
5372 if (GTK_CTREE_ROW (node)->row.cell[column].style == style)
5375 if (clist->column[column].auto_resize &&
5376 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5378 visible = gtk_ctree_is_viewable (ctree, node);
5380 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5381 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5384 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5386 if (GTK_WIDGET_REALIZED (ctree))
5387 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[column].style);
5388 gtk_style_unref (GTK_CTREE_ROW (node)->row.cell[column].style);
5391 GTK_CTREE_ROW (node)->row.cell[column].style = style;
5393 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5395 gtk_style_ref (GTK_CTREE_ROW (node)->row.cell[column].style);
5397 if (GTK_WIDGET_REALIZED (ctree))
5398 GTK_CTREE_ROW (node)->row.cell[column].style =
5399 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[column].style,
5400 clist->clist_window);
5404 column_auto_resize (clist, >K_CTREE_ROW (node)->row, column,
5407 tree_draw_node (ctree, node);
5411 gtk_ctree_node_get_cell_style (GtkCTree *ctree,
5415 g_return_val_if_fail (ctree != NULL, NULL);
5416 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5417 g_return_val_if_fail (node != NULL, NULL);
5419 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5422 return GTK_CTREE_ROW (node)->row.cell[column].style;
5426 gtk_ctree_node_set_row_style (GtkCTree *ctree,
5431 GtkRequisition requisition;
5433 gint *old_width = NULL;
5436 g_return_if_fail (ctree != NULL);
5437 g_return_if_fail (GTK_IS_CTREE (ctree));
5438 g_return_if_fail (node != NULL);
5440 clist = GTK_CLIST (ctree);
5442 if (GTK_CTREE_ROW (node)->row.style == style)
5445 visible = gtk_ctree_is_viewable (ctree, node);
5446 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5448 old_width = g_new (gint, clist->columns);
5449 for (i = 0; i < clist->columns; i++)
5450 if (clist->column[i].auto_resize)
5452 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5453 (clist, >K_CTREE_ROW (node)->row, i, &requisition);
5454 old_width[i] = requisition.width;
5458 if (GTK_CTREE_ROW (node)->row.style)
5460 if (GTK_WIDGET_REALIZED (ctree))
5461 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
5462 gtk_style_unref (GTK_CTREE_ROW (node)->row.style);
5465 GTK_CTREE_ROW (node)->row.style = style;
5467 if (GTK_CTREE_ROW (node)->row.style)
5469 gtk_style_ref (GTK_CTREE_ROW (node)->row.style);
5471 if (GTK_WIDGET_REALIZED (ctree))
5472 GTK_CTREE_ROW (node)->row.style =
5473 gtk_style_attach (GTK_CTREE_ROW (node)->row.style,
5474 clist->clist_window);
5477 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5479 for (i = 0; i < clist->columns; i++)
5480 if (clist->column[i].auto_resize)
5481 column_auto_resize (clist, >K_CTREE_ROW (node)->row, i,
5485 tree_draw_node (ctree, node);
5489 gtk_ctree_node_get_row_style (GtkCTree *ctree,
5492 g_return_val_if_fail (ctree != NULL, NULL);
5493 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5494 g_return_val_if_fail (node != NULL, NULL);
5496 return GTK_CTREE_ROW (node)->row.style;
5500 gtk_ctree_node_set_foreground (GtkCTree *ctree,
5504 g_return_if_fail (ctree != NULL);
5505 g_return_if_fail (GTK_IS_CTREE (ctree));
5506 g_return_if_fail (node != NULL);
5510 GTK_CTREE_ROW (node)->row.foreground = *color;
5511 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
5512 if (GTK_WIDGET_REALIZED (ctree))
5513 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5514 >K_CTREE_ROW (node)->row.foreground);
5517 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
5519 tree_draw_node (ctree, node);
5523 gtk_ctree_node_set_background (GtkCTree *ctree,
5527 g_return_if_fail (ctree != NULL);
5528 g_return_if_fail (GTK_IS_CTREE (ctree));
5529 g_return_if_fail (node != NULL);
5533 GTK_CTREE_ROW (node)->row.background = *color;
5534 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
5535 if (GTK_WIDGET_REALIZED (ctree))
5536 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5537 >K_CTREE_ROW (node)->row.background);
5540 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
5542 tree_draw_node (ctree, node);
5546 gtk_ctree_node_set_row_data (GtkCTree *ctree,
5550 gtk_ctree_node_set_row_data_full (ctree, node, data, NULL);
5554 gtk_ctree_node_set_row_data_full (GtkCTree *ctree,
5557 GtkDestroyNotify destroy)
5559 g_return_if_fail (ctree != NULL);
5560 g_return_if_fail (GTK_IS_CTREE (ctree));
5562 GTK_CTREE_ROW (node)->row.data = data;
5563 GTK_CTREE_ROW (node)->row.destroy = destroy;
5567 gtk_ctree_node_get_row_data (GtkCTree *ctree,
5570 g_return_val_if_fail (ctree != NULL, NULL);
5571 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5573 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
5577 gtk_ctree_node_moveto (GtkCTree *ctree,
5586 g_return_if_fail (ctree != NULL);
5587 g_return_if_fail (GTK_IS_CTREE (ctree));
5589 clist = GTK_CLIST (ctree);
5591 while (node && !gtk_ctree_is_viewable (ctree, node))
5592 node = GTK_CTREE_ROW (node)->parent;
5595 row = g_list_position (clist->row_list, (GList *)node);
5597 gtk_clist_moveto (clist, row, column, row_align, col_align);
5600 GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree,
5605 g_return_val_if_fail (ctree != NULL, 0);
5606 g_return_val_if_fail (node != NULL, 0);
5608 row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node);
5609 return gtk_clist_row_is_visible (GTK_CLIST (ctree), row);
5613 /***********************************************************
5614 * GtkCTree specific functions *
5615 ***********************************************************/
5618 gtk_ctree_set_indent (GtkCTree *ctree,
5623 g_return_if_fail (ctree != NULL);
5624 g_return_if_fail (GTK_IS_CTREE (ctree));
5625 g_return_if_fail (indent >= 0);
5627 if (indent == ctree->tree_indent)
5630 clist = GTK_CLIST (ctree);
5631 ctree->tree_indent = indent;
5633 if (clist->column[ctree->tree_column].auto_resize &&
5634 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5635 gtk_clist_set_column_width
5636 (clist, ctree->tree_column,
5637 gtk_clist_optimal_column_width (clist, ctree->tree_column));
5639 CLIST_REFRESH (ctree);
5643 gtk_ctree_set_spacing (GtkCTree *ctree,
5649 g_return_if_fail (ctree != NULL);
5650 g_return_if_fail (GTK_IS_CTREE (ctree));
5651 g_return_if_fail (spacing >= 0);
5653 if (spacing == ctree->tree_spacing)
5656 clist = GTK_CLIST (ctree);
5658 old_spacing = ctree->tree_spacing;
5659 ctree->tree_spacing = spacing;
5661 if (clist->column[ctree->tree_column].auto_resize &&
5662 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5663 gtk_clist_set_column_width (clist, ctree->tree_column,
5664 clist->column[ctree->tree_column].width +
5665 spacing - old_spacing);
5667 CLIST_REFRESH (ctree);
5671 gtk_ctree_show_stub (GtkCTree *ctree,
5674 g_message ("gtk_ctree_show_stub() is deprecated");
5675 gtk_ctree_set_show_stub (ctree, show_stub);
5679 gtk_ctree_set_show_stub (GtkCTree *ctree,
5682 g_return_if_fail (ctree != NULL);
5683 g_return_if_fail (GTK_IS_CTREE (ctree));
5685 show_stub = show_stub != FALSE;
5687 if (show_stub != ctree->show_stub)
5691 clist = GTK_CLIST (ctree);
5692 ctree->show_stub = show_stub;
5694 if (CLIST_UNFROZEN (clist) && clist->rows &&
5695 gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
5696 GTK_CLIST_CLASS_FW (clist)->draw_row
5697 (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list));
5702 gtk_ctree_set_reorderable (GtkCTree *ctree,
5703 gboolean reorderable)
5705 g_return_if_fail (ctree != NULL);
5706 g_return_if_fail (GTK_IS_CTREE (ctree));
5708 ctree->reorderable = reorderable;
5712 gtk_ctree_set_use_drag_icons (GtkCTree *ctree,
5715 g_return_if_fail (ctree != NULL);
5716 g_return_if_fail (GTK_IS_CTREE (ctree));
5718 if (ctree->use_icons == (use_icons != 0))
5721 ctree->use_icons = (use_icons != 0);
5725 gtk_ctree_set_line_style (GtkCTree *ctree,
5726 GtkCTreeLineStyle line_style)
5729 GtkCTreeLineStyle old_style;
5731 g_return_if_fail (ctree != NULL);
5732 g_return_if_fail (GTK_IS_CTREE (ctree));
5734 if (line_style == ctree->line_style)
5737 clist = GTK_CLIST (ctree);
5739 old_style = ctree->line_style;
5740 ctree->line_style = line_style;
5742 if (clist->column[ctree->tree_column].auto_resize &&
5743 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5745 if (old_style == GTK_CTREE_LINES_TABBED)
5746 gtk_clist_set_column_width
5747 (clist, ctree->tree_column,
5748 clist->column[ctree->tree_column].width - 3);
5749 else if (line_style == GTK_CTREE_LINES_TABBED)
5750 gtk_clist_set_column_width
5751 (clist, ctree->tree_column,
5752 clist->column[ctree->tree_column].width + 3);
5755 if (GTK_WIDGET_REALIZED (ctree))
5759 case GTK_CTREE_LINES_SOLID:
5760 if (GTK_WIDGET_REALIZED (ctree))
5761 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5764 case GTK_CTREE_LINES_DOTTED:
5765 if (GTK_WIDGET_REALIZED (ctree))
5766 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
5767 GDK_LINE_ON_OFF_DASH, None, None);
5768 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
5770 case GTK_CTREE_LINES_TABBED:
5771 if (GTK_WIDGET_REALIZED (ctree))
5772 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5775 case GTK_CTREE_LINES_NONE:
5780 CLIST_REFRESH (ctree);
5785 gtk_ctree_set_expander_style (GtkCTree *ctree,
5786 GtkCTreeExpanderStyle expander_style)
5789 GtkCTreeExpanderStyle old_style;
5791 g_return_if_fail (ctree != NULL);
5792 g_return_if_fail (GTK_IS_CTREE (ctree));
5794 if (expander_style == ctree->expander_style)
5797 clist = GTK_CLIST (ctree);
5799 old_style = ctree->expander_style;
5800 ctree->expander_style = expander_style;
5802 if (clist->column[ctree->tree_column].auto_resize &&
5803 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5807 new_width = clist->column[ctree->tree_column].width;
5810 case GTK_CTREE_EXPANDER_NONE:
5812 case GTK_CTREE_EXPANDER_TRIANGLE:
5813 new_width -= PM_SIZE + 3;
5815 case GTK_CTREE_EXPANDER_SQUARE:
5816 case GTK_CTREE_EXPANDER_CIRCULAR:
5817 new_width -= PM_SIZE + 1;
5821 switch (expander_style)
5823 case GTK_CTREE_EXPANDER_NONE:
5825 case GTK_CTREE_EXPANDER_TRIANGLE:
5826 new_width += PM_SIZE + 3;
5828 case GTK_CTREE_EXPANDER_SQUARE:
5829 case GTK_CTREE_EXPANDER_CIRCULAR:
5830 new_width += PM_SIZE + 1;
5834 gtk_clist_set_column_width (clist, ctree->tree_column, new_width);
5837 if (GTK_WIDGET_DRAWABLE (clist))
5838 CLIST_REFRESH (clist);
5842 /***********************************************************
5843 * Tree sorting functions *
5844 ***********************************************************/
5848 tree_sort (GtkCTree *ctree,
5852 GtkCTreeNode *list_start;
5857 clist = GTK_CLIST (ctree);
5860 list_start = GTK_CTREE_ROW (node)->children;
5862 list_start = GTK_CTREE_NODE (clist->row_list);
5867 work = GTK_CTREE_ROW (cmp)->sibling;
5870 if (clist->sort_type == GTK_SORT_ASCENDING)
5873 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0)
5879 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0)
5882 work = GTK_CTREE_ROW (work)->sibling;
5884 if (cmp == list_start)
5885 list_start = GTK_CTREE_ROW (cmp)->sibling;
5888 gtk_ctree_unlink (ctree, cmp, FALSE);
5889 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5895 gtk_ctree_sort_recursive (GtkCTree *ctree,
5899 GtkCTreeNode *focus_node = NULL;
5901 g_return_if_fail (ctree != NULL);
5902 g_return_if_fail (GTK_IS_CTREE (ctree));
5904 clist = GTK_CLIST (ctree);
5906 gtk_clist_freeze (clist);
5908 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5910 if (clist->anchor != -1)
5911 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5913 g_list_free (clist->undo_selection);
5914 g_list_free (clist->undo_unselection);
5915 clist->undo_selection = NULL;
5916 clist->undo_unselection = NULL;
5919 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5921 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5923 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5926 tree_sort (ctree, NULL, NULL);
5930 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5931 clist->undo_anchor = clist->focus_row;
5934 gtk_clist_thaw (clist);
5938 real_sort_list (GtkCList *clist)
5940 gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL);
5944 gtk_ctree_sort_node (GtkCTree *ctree,
5948 GtkCTreeNode *focus_node = NULL;
5950 g_return_if_fail (ctree != NULL);
5951 g_return_if_fail (GTK_IS_CTREE (ctree));
5953 clist = GTK_CLIST (ctree);
5955 gtk_clist_freeze (clist);
5957 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5959 if (clist->anchor != -1)
5960 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5962 g_list_free (clist->undo_selection);
5963 g_list_free (clist->undo_unselection);
5964 clist->undo_selection = NULL;
5965 clist->undo_unselection = NULL;
5968 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5969 focus_node = GTK_CTREE_NODE
5970 (g_list_nth (clist->row_list, clist->focus_row));
5972 tree_sort (ctree, node, NULL);
5976 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5977 clist->undo_anchor = clist->focus_row;
5980 gtk_clist_thaw (clist);
5983 /************************************************************************/
5986 fake_unselect_all (GtkCList *clist,
5990 GList *focus_node = NULL;
5992 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5994 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
5995 GTK_CTREE_ROW (focus_node)->row.selectable)
5997 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5999 if (CLIST_UNFROZEN (clist) &&
6000 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
6001 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
6002 GTK_CLIST_ROW (focus_node));
6006 clist->undo_selection = clist->selection;
6007 clist->selection = NULL;
6008 clist->selection_end = NULL;
6010 for (list = clist->undo_selection; list; list = list->next)
6012 if (list->data == focus_node)
6015 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
6016 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
6021 selection_find (GtkCList *clist,
6023 GList *row_list_element)
6025 return g_list_find (clist->selection, row_list_element);
6029 resync_selection (GtkCList *clist, GdkEvent *event)
6039 g_return_if_fail (clist != NULL);
6040 g_return_if_fail (GTK_IS_CTREE (clist));
6042 if (clist->anchor < 0)
6045 ctree = GTK_CTREE (clist);
6047 clist->freeze_count++;
6049 i = MIN (clist->anchor, clist->drag_pos);
6050 e = MAX (clist->anchor, clist->drag_pos);
6052 if (clist->undo_selection)
6054 list = clist->selection;
6055 clist->selection = clist->undo_selection;
6056 clist->selection_end = g_list_last (clist->selection);
6057 clist->undo_selection = list;
6058 list = clist->selection;
6067 if (gtk_ctree_is_viewable (ctree, node))
6069 row = g_list_position (clist->row_list, (GList *)node);
6070 if (row >= i && row <= e)
6073 if (unselect && GTK_CTREE_ROW (node)->row.selectable)
6075 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
6076 gtk_ctree_unselect (ctree, node);
6077 clist->undo_selection = g_list_prepend (clist->undo_selection,
6084 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
6085 i++, node = GTK_CTREE_NODE_NEXT (node))
6086 if (GTK_CTREE_ROW (node)->row.selectable)
6088 if (g_list_find (clist->selection, node))
6090 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
6092 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
6093 gtk_ctree_unselect (ctree, node);
6094 clist->undo_selection = g_list_prepend (clist->undo_selection,
6098 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
6100 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
6101 clist->undo_unselection = g_list_prepend (clist->undo_unselection,
6106 for (list = clist->undo_unselection; list; list = list->next)
6107 gtk_ctree_select (ctree, list->data);
6110 clist->drag_pos = -1;
6112 if (!CLIST_UNFROZEN (clist))
6113 clist->freeze_count--;
6117 real_undo_selection (GtkCList *clist)
6122 g_return_if_fail (clist != NULL);
6123 g_return_if_fail (GTK_IS_CTREE (clist));
6125 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
6128 if (!(clist->undo_selection || clist->undo_unselection))
6130 gtk_clist_unselect_all (clist);
6134 ctree = GTK_CTREE (clist);
6136 for (work = clist->undo_selection; work; work = work->next)
6137 if (GTK_CTREE_ROW (work->data)->row.selectable)
6138 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
6140 for (work = clist->undo_unselection; work; work = work->next)
6141 if (GTK_CTREE_ROW (work->data)->row.selectable)
6142 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
6144 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
6146 gtk_widget_draw_focus (GTK_WIDGET (clist));
6147 clist->focus_row = clist->undo_anchor;
6148 gtk_widget_draw_focus (GTK_WIDGET (clist));
6151 clist->focus_row = clist->undo_anchor;
6153 clist->undo_anchor = -1;
6155 g_list_free (clist->undo_selection);
6156 g_list_free (clist->undo_unselection);
6157 clist->undo_selection = NULL;
6158 clist->undo_unselection = NULL;
6160 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
6161 clist->clist_window_height)
6162 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
6163 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
6164 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
6169 gtk_ctree_set_drag_compare_func (GtkCTree *ctree,
6170 GtkCTreeCompareDragFunc cmp_func)
6172 g_return_if_fail (ctree != NULL);
6173 g_return_if_fail (GTK_IS_CTREE (ctree));
6175 ctree->drag_compare = cmp_func;
6179 set_mouse_cursor (GtkCTree *ctree,
6184 g_return_if_fail (ctree != NULL);
6185 g_return_if_fail (GTK_IS_CTREE (ctree));
6188 cursor = gdk_cursor_new (GDK_LEFT_PTR);
6190 cursor = gdk_cursor_new (GDK_CIRCLE);
6192 gdk_window_set_cursor (GTK_CLIST (ctree)->clist_window, cursor);
6193 gdk_cursor_destroy (cursor);
6197 check_cursor (GtkCTree *ctree)
6199 g_return_if_fail (ctree != NULL);
6200 g_return_if_fail (GTK_IS_CTREE (ctree));
6202 if (!GTK_CTREE_ROW (ctree->drag_source)->children ||
6203 !gtk_ctree_is_ancestor (ctree, ctree->drag_source, ctree->drag_target))
6205 if (ctree->insert_pos == GTK_CTREE_POS_AFTER)
6207 if (GTK_CTREE_ROW (ctree->drag_target)->sibling !=
6211 (!ctree->drag_compare ||
6215 GTK_CTREE_ROW (ctree->drag_target)->parent,
6216 GTK_CTREE_ROW (ctree->drag_target)->sibling)));
6218 else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE)
6220 if (GTK_CTREE_ROW (ctree->drag_source)->sibling !=
6224 (!ctree->drag_compare ||
6228 GTK_CTREE_ROW (ctree->drag_target)->parent,
6229 ctree->drag_target)));
6231 else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf)
6233 if (GTK_CTREE_ROW (ctree->drag_target)->children !=
6237 (!ctree->drag_compare ||
6242 GTK_CTREE_ROW (ctree->drag_target)->children)));
6246 set_mouse_cursor(ctree, FALSE);