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"
30 #include <gdk/gdkkeysyms.h>
33 #define TAB_SIZE (PM_SIZE + 6)
34 #define CELL_SPACING 1
35 #define CLIST_OPTIMUM_SIZE 64
36 #define COLUMN_INSET 3
39 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
40 (((row) + 1) * CELL_SPACING) + \
42 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
43 ((clist)->row_height + CELL_SPACING))
44 #define COLUMN_LEFT_XPIXEL(clist, col) ((clist)->column[(col)].area.x \
46 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
49 COLUMN_FROM_XPIXEL (GtkCList * clist,
54 for (i = 0; i < clist->columns; i++)
55 if (clist->column[i].visible)
57 cx = clist->column[i].area.x + clist->hoffset;
59 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
60 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
68 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
69 #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
70 #define CLIST_REFRESH(clist) G_STMT_START { \
71 if (CLIST_UNFROZEN (clist)) \
72 GTK_CLIST_CLASS_FW (clist)->refresh ((GtkCList*) (clist)); \
88 static void gtk_ctree_class_init (GtkCTreeClass *klass);
89 static void gtk_ctree_init (GtkCTree *ctree);
90 static void gtk_ctree_set_arg (GtkObject *object,
93 static void gtk_ctree_get_arg (GtkObject *object,
96 static void gtk_ctree_realize (GtkWidget *widget);
97 static void gtk_ctree_unrealize (GtkWidget *widget);
98 static gint gtk_ctree_button_press (GtkWidget *widget,
99 GdkEventButton *event);
100 static void ctree_attach_styles (GtkCTree *ctree,
103 static void ctree_detach_styles (GtkCTree *ctree,
106 static gint draw_cell_pixmap (GdkWindow *window,
107 GdkRectangle *clip_rectangle,
115 static void get_cell_style (GtkCList *clist,
116 GtkCListRow *clist_row,
122 static gint gtk_ctree_draw_expander (GtkCTree *ctree,
123 GtkCTreeRow *ctree_row,
125 GdkRectangle *clip_rectangle,
127 static gint gtk_ctree_draw_lines (GtkCTree *ctree,
128 GtkCTreeRow *ctree_row,
132 GdkRectangle *clip_rectangle,
133 GdkRectangle *cell_rectangle,
137 static void draw_row (GtkCList *clist,
140 GtkCListRow *clist_row);
141 static void draw_drag_highlight (GtkCList *clist,
142 GtkCListRow *dest_row,
143 gint dest_row_number,
144 GtkCListDragPos drag_pos);
145 static void tree_draw_node (GtkCTree *ctree,
147 static void set_cell_contents (GtkCList *clist,
148 GtkCListRow *clist_row,
155 static void set_node_info (GtkCTree *ctree,
159 GdkPixmap *pixmap_closed,
160 GdkBitmap *mask_closed,
161 GdkPixmap *pixmap_opened,
162 GdkBitmap *mask_opened,
165 static GtkCTreeRow *row_new (GtkCTree *ctree);
166 static void row_delete (GtkCTree *ctree,
167 GtkCTreeRow *ctree_row);
168 static void tree_delete (GtkCTree *ctree,
171 static void tree_delete_row (GtkCTree *ctree,
174 static void real_clear (GtkCList *clist);
175 static void tree_update_level (GtkCTree *ctree,
178 static void tree_select (GtkCTree *ctree,
181 static void tree_unselect (GtkCTree *ctree,
184 static void real_select_all (GtkCList *clist);
185 static void real_unselect_all (GtkCList *clist);
186 static void tree_expand (GtkCTree *ctree,
189 static void tree_collapse (GtkCTree *ctree,
192 static void tree_collapse_to_depth (GtkCTree *ctree,
195 static void tree_toggle_expansion (GtkCTree *ctree,
198 static void change_focus_row_expansion (GtkCTree *ctree,
199 GtkCTreeExpansionType expansion);
200 static void real_select_row (GtkCList *clist,
204 static void real_unselect_row (GtkCList *clist,
208 static void real_tree_select (GtkCTree *ctree,
211 static void real_tree_unselect (GtkCTree *ctree,
214 static void real_tree_expand (GtkCTree *ctree,
216 static void real_tree_collapse (GtkCTree *ctree,
218 static void real_tree_move (GtkCTree *ctree,
220 GtkCTreeNode *new_parent,
221 GtkCTreeNode *new_sibling);
222 static void real_row_move (GtkCList *clist,
225 static void gtk_ctree_link (GtkCTree *ctree,
227 GtkCTreeNode *parent,
228 GtkCTreeNode *sibling,
229 gboolean update_focus_row);
230 static void gtk_ctree_unlink (GtkCTree *ctree,
232 gboolean update_focus_row);
233 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
235 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
240 static void tree_sort (GtkCTree *ctree,
243 static void fake_unselect_all (GtkCList *clist,
245 static GList * selection_find (GtkCList *clist,
247 GList *row_list_element);
248 static void resync_selection (GtkCList *clist,
250 static void real_undo_selection (GtkCList *clist);
251 static void select_row_recursive (GtkCTree *ctree,
254 static gint real_insert_row (GtkCList *clist,
257 static void real_remove_row (GtkCList *clist,
259 static void real_sort_list (GtkCList *clist);
260 static void cell_size_request (GtkCList *clist,
261 GtkCListRow *clist_row,
263 GtkRequisition *requisition);
264 static void column_auto_resize (GtkCList *clist,
265 GtkCListRow *clist_row,
268 static void auto_resize_columns (GtkCList *clist);
271 static gboolean check_drag (GtkCTree *ctree,
272 GtkCTreeNode *drag_source,
273 GtkCTreeNode *drag_target,
274 GtkCListDragPos insert_pos);
275 static void gtk_ctree_drag_begin (GtkWidget *widget,
276 GdkDragContext *context);
277 static gint gtk_ctree_drag_motion (GtkWidget *widget,
278 GdkDragContext *context,
282 static void gtk_ctree_drag_data_received (GtkWidget *widget,
283 GdkDragContext *context,
286 GtkSelectionData *selection_data,
289 static void remove_grab (GtkCList *clist);
299 CHANGE_FOCUS_ROW_EXPANSION,
303 static GtkCListClass *parent_class = NULL;
304 static GtkContainerClass *container_class = NULL;
305 static guint ctree_signals[LAST_SIGNAL] = {0};
309 gtk_ctree_get_type (void)
311 static GtkType ctree_type = 0;
315 static const GtkTypeInfo ctree_info =
319 sizeof (GtkCTreeClass),
320 (GtkClassInitFunc) gtk_ctree_class_init,
321 (GtkObjectInitFunc) gtk_ctree_init,
322 /* reserved_1 */ NULL,
323 /* reserved_2 */ NULL,
324 (GtkClassInitFunc) NULL,
327 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
334 gtk_ctree_class_init (GtkCTreeClass *klass)
336 GtkObjectClass *object_class;
337 GtkWidgetClass *widget_class;
338 GtkCListClass *clist_class;
339 GtkBindingSet *binding_set;
341 object_class = (GtkObjectClass *) klass;
342 widget_class = (GtkWidgetClass *) klass;
343 container_class = (GtkContainerClass *) klass;
344 clist_class = (GtkCListClass *) klass;
346 parent_class = gtk_type_class (GTK_TYPE_CLIST);
347 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
349 gtk_object_add_arg_type ("GtkCTree::n_columns",
351 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
353 gtk_object_add_arg_type ("GtkCTree::tree_column",
355 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
357 gtk_object_add_arg_type ("GtkCTree::indent",
361 gtk_object_add_arg_type ("GtkCTree::spacing",
365 gtk_object_add_arg_type ("GtkCTree::show_stub",
369 gtk_object_add_arg_type ("GtkCTree::line_style",
370 GTK_TYPE_CTREE_LINE_STYLE,
373 gtk_object_add_arg_type ("GtkCTree::expander_style",
374 GTK_TYPE_CTREE_EXPANDER_STYLE,
377 object_class->set_arg = gtk_ctree_set_arg;
378 object_class->get_arg = gtk_ctree_get_arg;
380 ctree_signals[TREE_SELECT_ROW] =
381 gtk_signal_new ("tree_select_row",
384 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
385 gtk_marshal_NONE__POINTER_INT,
386 GTK_TYPE_NONE, 2, GTK_TYPE_CTREE_NODE, GTK_TYPE_INT);
387 ctree_signals[TREE_UNSELECT_ROW] =
388 gtk_signal_new ("tree_unselect_row",
391 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
392 gtk_marshal_NONE__POINTER_INT,
393 GTK_TYPE_NONE, 2, GTK_TYPE_CTREE_NODE, GTK_TYPE_INT);
394 ctree_signals[TREE_EXPAND] =
395 gtk_signal_new ("tree_expand",
398 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
399 gtk_marshal_NONE__POINTER,
400 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_NODE);
401 ctree_signals[TREE_COLLAPSE] =
402 gtk_signal_new ("tree_collapse",
405 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
406 gtk_marshal_NONE__POINTER,
407 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_NODE);
408 ctree_signals[TREE_MOVE] =
409 gtk_signal_new ("tree_move",
412 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
413 gtk_marshal_NONE__POINTER_POINTER_POINTER,
414 GTK_TYPE_NONE, 3, GTK_TYPE_CTREE_NODE,
415 GTK_TYPE_CTREE_NODE, GTK_TYPE_CTREE_NODE);
416 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
417 gtk_signal_new ("change_focus_row_expansion",
418 GTK_RUN_LAST | GTK_RUN_ACTION,
420 GTK_SIGNAL_OFFSET (GtkCTreeClass,
421 change_focus_row_expansion),
422 gtk_marshal_NONE__ENUM,
423 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_EXPANSION_TYPE);
424 gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL);
426 widget_class->realize = gtk_ctree_realize;
427 widget_class->unrealize = gtk_ctree_unrealize;
428 widget_class->button_press_event = gtk_ctree_button_press;
430 widget_class->drag_begin = gtk_ctree_drag_begin;
431 widget_class->drag_motion = gtk_ctree_drag_motion;
432 widget_class->drag_data_received = gtk_ctree_drag_data_received;
434 clist_class->select_row = real_select_row;
435 clist_class->unselect_row = real_unselect_row;
436 clist_class->row_move = real_row_move;
437 clist_class->undo_selection = real_undo_selection;
438 clist_class->resync_selection = resync_selection;
439 clist_class->selection_find = selection_find;
440 clist_class->click_column = NULL;
441 clist_class->draw_row = draw_row;
442 clist_class->draw_drag_highlight = draw_drag_highlight;
443 clist_class->clear = real_clear;
444 clist_class->select_all = real_select_all;
445 clist_class->unselect_all = real_unselect_all;
446 clist_class->fake_unselect_all = fake_unselect_all;
447 clist_class->insert_row = real_insert_row;
448 clist_class->remove_row = real_remove_row;
449 clist_class->sort_list = real_sort_list;
450 clist_class->set_cell_contents = set_cell_contents;
451 clist_class->cell_size_request = cell_size_request;
453 klass->tree_select_row = real_tree_select;
454 klass->tree_unselect_row = real_tree_unselect;
455 klass->tree_expand = real_tree_expand;
456 klass->tree_collapse = real_tree_collapse;
457 klass->tree_move = real_tree_move;
458 klass->change_focus_row_expansion = change_focus_row_expansion;
460 binding_set = gtk_binding_set_by_class (klass);
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,
467 "change_focus_row_expansion", 1,
468 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
469 gtk_binding_entry_add_signal (binding_set,
470 GDK_KP_Add, GDK_CONTROL_MASK,
471 "change_focus_row_expansion", 1,
473 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
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,
480 "change_focus_row_expansion", 1,
481 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
482 gtk_binding_entry_add_signal (binding_set,
483 GDK_KP_Subtract, GDK_CONTROL_MASK,
484 "change_focus_row_expansion", 1,
486 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
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,
493 "change_focus_row_expansion", 1,
494 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
495 gtk_binding_entry_add_signal (binding_set,
496 GDK_KP_Multiply, GDK_CONTROL_MASK,
497 "change_focus_row_expansion", 1,
499 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
503 gtk_ctree_set_arg (GtkObject *object,
509 ctree = GTK_CTREE (object);
513 case ARG_N_COLUMNS: /* construct-only arg, only set when !GTK_CONSTRUCTED */
514 if (ctree->tree_column)
515 gtk_ctree_construct (ctree,
516 MAX (1, GTK_VALUE_UINT (*arg)),
517 ctree->tree_column, NULL);
519 GTK_CLIST (ctree)->columns = MAX (1, GTK_VALUE_UINT (*arg));
521 case ARG_TREE_COLUMN: /* construct-only arg, only set when !GTK_CONSTRUCTED */
522 if (GTK_CLIST (ctree)->columns)
523 gtk_ctree_construct (ctree,
524 GTK_CLIST (ctree)->columns,
525 MAX (1, GTK_VALUE_UINT (*arg)),
528 ctree->tree_column = MAX (1, GTK_VALUE_UINT (*arg));
531 gtk_ctree_set_indent (ctree, GTK_VALUE_UINT (*arg));
534 gtk_ctree_set_spacing (ctree, GTK_VALUE_UINT (*arg));
537 gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg));
540 gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg));
542 case ARG_EXPANDER_STYLE:
543 gtk_ctree_set_expander_style (ctree, GTK_VALUE_ENUM (*arg));
551 gtk_ctree_get_arg (GtkObject *object,
557 ctree = GTK_CTREE (object);
562 GTK_VALUE_UINT (*arg) = GTK_CLIST (ctree)->columns;
564 case ARG_TREE_COLUMN:
565 GTK_VALUE_UINT (*arg) = ctree->tree_column;
568 GTK_VALUE_UINT (*arg) = ctree->tree_indent;
571 GTK_VALUE_UINT (*arg) = ctree->tree_spacing;
574 GTK_VALUE_BOOL (*arg) = ctree->show_stub;
577 GTK_VALUE_ENUM (*arg) = ctree->line_style;
579 case ARG_EXPANDER_STYLE:
580 GTK_VALUE_ENUM (*arg) = ctree->expander_style;
583 arg->type = GTK_TYPE_INVALID;
589 gtk_ctree_init (GtkCTree *ctree)
593 GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_RECT);
594 GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_LINE);
596 clist = GTK_CLIST (ctree);
598 ctree->tree_indent = 20;
599 ctree->tree_spacing = 5;
600 ctree->tree_column = 0;
601 ctree->line_style = GTK_CTREE_LINES_SOLID;
602 ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE;
603 ctree->drag_compare = NULL;
604 ctree->show_stub = TRUE;
606 clist->button_actions[0] |= GTK_BUTTON_EXPANDS;
610 ctree_attach_styles (GtkCTree *ctree,
617 clist = GTK_CLIST (ctree);
619 if (GTK_CTREE_ROW (node)->row.style)
620 GTK_CTREE_ROW (node)->row.style =
621 gtk_style_attach (GTK_CTREE_ROW (node)->row.style, clist->clist_window);
623 if (GTK_CTREE_ROW (node)->row.fg_set || GTK_CTREE_ROW (node)->row.bg_set)
625 GdkColormap *colormap;
627 colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
628 if (GTK_CTREE_ROW (node)->row.fg_set)
629 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.foreground));
630 if (GTK_CTREE_ROW (node)->row.bg_set)
631 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.background));
634 for (i = 0; i < clist->columns; i++)
635 if (GTK_CTREE_ROW (node)->row.cell[i].style)
636 GTK_CTREE_ROW (node)->row.cell[i].style =
637 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[i].style,
638 clist->clist_window);
642 ctree_detach_styles (GtkCTree *ctree,
649 clist = GTK_CLIST (ctree);
651 if (GTK_CTREE_ROW (node)->row.style)
652 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
653 for (i = 0; i < clist->columns; i++)
654 if (GTK_CTREE_ROW (node)->row.cell[i].style)
655 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[i].style);
659 gtk_ctree_realize (GtkWidget *widget)
668 g_return_if_fail (widget != NULL);
669 g_return_if_fail (GTK_IS_CTREE (widget));
671 GTK_WIDGET_CLASS (parent_class)->realize (widget);
673 ctree = GTK_CTREE (widget);
674 clist = GTK_CLIST (widget);
676 node = GTK_CTREE_NODE (clist->row_list);
677 for (i = 0; i < clist->rows; i++)
679 if (GTK_CTREE_ROW (node)->children && !GTK_CTREE_ROW (node)->expanded)
680 for (child = GTK_CTREE_ROW (node)->children; child;
681 child = GTK_CTREE_ROW (child)->sibling)
682 gtk_ctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
683 node = GTK_CTREE_NODE_NEXT (node);
686 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
687 values.background = widget->style->base[GTK_STATE_NORMAL];
688 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
689 values.line_style = GDK_LINE_SOLID;
690 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
697 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
699 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
700 GDK_LINE_ON_OFF_DASH, None, None);
701 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
706 gtk_ctree_unrealize (GtkWidget *widget)
711 g_return_if_fail (widget != NULL);
712 g_return_if_fail (GTK_IS_CTREE (widget));
714 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
716 ctree = GTK_CTREE (widget);
717 clist = GTK_CLIST (widget);
719 if (GTK_WIDGET_REALIZED (widget))
725 node = GTK_CTREE_NODE (clist->row_list);
726 for (i = 0; i < clist->rows; i++)
728 if (GTK_CTREE_ROW (node)->children &&
729 !GTK_CTREE_ROW (node)->expanded)
730 for (child = GTK_CTREE_ROW (node)->children; child;
731 child = GTK_CTREE_ROW (child)->sibling)
732 gtk_ctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
733 node = GTK_CTREE_NODE_NEXT (node);
737 gdk_gc_destroy (ctree->lines_gc);
741 gtk_ctree_button_press (GtkWidget *widget,
742 GdkEventButton *event)
748 g_return_val_if_fail (widget != NULL, FALSE);
749 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
750 g_return_val_if_fail (event != NULL, FALSE);
752 ctree = GTK_CTREE (widget);
753 clist = GTK_CLIST (widget);
755 button_actions = clist->button_actions[event->button - 1];
757 if (button_actions == GTK_BUTTON_IGNORED)
760 if (event->window == clist->clist_window)
771 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
774 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
776 if (button_actions & GTK_BUTTON_EXPANDS &&
777 (GTK_CTREE_ROW (work)->children && !GTK_CTREE_ROW (work)->is_leaf &&
778 (event->type == GDK_2BUTTON_PRESS ||
779 ctree_is_hot_spot (ctree, work, row, x, y))))
781 if (GTK_CTREE_ROW (work)->expanded)
782 gtk_ctree_collapse (ctree, work);
784 gtk_ctree_expand (ctree, work);
789 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
793 draw_drag_highlight (GtkCList *clist,
794 GtkCListRow *dest_row,
795 gint dest_row_number,
796 GtkCListDragPos drag_pos)
804 g_return_if_fail (clist != NULL);
805 g_return_if_fail (GTK_IS_CTREE (clist));
807 ctree = GTK_CTREE (clist);
809 level = ((GtkCTreeRow *)(dest_row))->level;
811 y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
815 case GTK_CLIST_DRAG_NONE:
817 case GTK_CLIST_DRAG_AFTER:
818 y += clist->row_height + 1;
819 case GTK_CLIST_DRAG_BEFORE:
821 if (clist->column[ctree->tree_column].visible)
822 switch (clist->column[ctree->tree_column].justification)
824 case GTK_JUSTIFY_CENTER:
825 case GTK_JUSTIFY_FILL:
826 case GTK_JUSTIFY_LEFT:
827 if (ctree->tree_column > 0)
828 gdk_draw_line (clist->clist_window, clist->xor_gc,
829 COLUMN_LEFT_XPIXEL(clist, 0), y,
830 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+
831 clist->column[ctree->tree_column - 1].area.width,
834 gdk_draw_line (clist->clist_window, clist->xor_gc,
835 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
836 ctree->tree_indent * level -
837 (ctree->tree_indent - PM_SIZE) / 2, y,
838 GTK_WIDGET (ctree)->allocation.width, y);
840 case GTK_JUSTIFY_RIGHT:
841 if (ctree->tree_column < clist->columns - 1)
842 gdk_draw_line (clist->clist_window, clist->xor_gc,
843 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1),
845 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
846 clist->column[clist->columns - 1].area.width, y);
848 gdk_draw_line (clist->clist_window, clist->xor_gc,
849 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
850 + clist->column[ctree->tree_column].area.width -
851 ctree->tree_indent * level +
852 (ctree->tree_indent - PM_SIZE) / 2, y);
856 gdk_draw_line (clist->clist_window, clist->xor_gc,
857 0, y, clist->clist_window_width, y);
859 case GTK_CLIST_DRAG_INTO:
860 y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height;
862 if (clist->column[ctree->tree_column].visible)
863 switch (clist->column[ctree->tree_column].justification)
865 case GTK_JUSTIFY_CENTER:
866 case GTK_JUSTIFY_FILL:
867 case GTK_JUSTIFY_LEFT:
868 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
869 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
871 points[3].x = points[0].x;
872 points[3].y = y - clist->row_height - 1;
873 points[1].x = clist->clist_window_width - 1;
874 points[1].y = points[0].y;
875 points[2].x = points[1].x;
876 points[2].y = points[3].y;
878 for (i = 0; i < 3; i++)
879 gdk_draw_line (clist->clist_window, clist->xor_gc,
880 points[i].x, points[i].y,
881 points[i+1].x, points[i+1].y);
883 if (ctree->tree_column > 0)
885 points[0].x = COLUMN_LEFT_XPIXEL(clist,
886 ctree->tree_column - 1) +
887 clist->column[ctree->tree_column - 1].area.width ;
889 points[3].x = points[0].x;
890 points[3].y = y - clist->row_height - 1;
892 points[1].y = points[0].y;
894 points[2].y = points[3].y;
896 for (i = 0; i < 3; i++)
897 gdk_draw_line (clist->clist_window, clist->xor_gc,
898 points[i].x, points[i].y, points[i+1].x,
902 case GTK_JUSTIFY_RIGHT:
903 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
904 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
905 clist->column[ctree->tree_column].area.width;
907 points[3].x = points[0].x;
908 points[3].y = y - clist->row_height - 1;
910 points[1].y = points[0].y;
912 points[2].y = points[3].y;
914 for (i = 0; i < 3; i++)
915 gdk_draw_line (clist->clist_window, clist->xor_gc,
916 points[i].x, points[i].y,
917 points[i+1].x, points[i+1].y);
919 if (ctree->tree_column < clist->columns - 1)
921 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1);
923 points[3].x = points[0].x;
924 points[3].y = y - clist->row_height - 1;
925 points[1].x = clist->clist_window_width - 1;
926 points[1].y = points[0].y;
927 points[2].x = points[1].x;
928 points[2].y = points[3].y;
930 for (i = 0; i < 3; i++)
931 gdk_draw_line (clist->clist_window, clist->xor_gc,
932 points[i].x, points[i].y,
933 points[i+1].x, points[i+1].y);
938 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
939 0, y - clist->row_height,
940 clist->clist_window_width - 1, clist->row_height);
946 draw_cell_pixmap (GdkWindow *window,
947 GdkRectangle *clip_rectangle,
961 gdk_gc_set_clip_mask (fg_gc, mask);
962 gdk_gc_set_clip_origin (fg_gc, x, y);
964 if (x < clip_rectangle->x)
966 xsrc = clip_rectangle->x - x;
968 x = clip_rectangle->x;
970 if (x + width > clip_rectangle->x + clip_rectangle->width)
971 width = clip_rectangle->x + clip_rectangle->width - x;
973 if (y < clip_rectangle->y)
975 ysrc = clip_rectangle->y - y;
977 y = clip_rectangle->y;
979 if (y + height > clip_rectangle->y + clip_rectangle->height)
980 height = clip_rectangle->y + clip_rectangle->height - y;
982 if (width > 0 && height > 0)
983 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
985 gdk_gc_set_clip_origin (fg_gc, 0, 0);
987 return x + MAX (width, 0);
991 get_cell_style (GtkCList *clist,
992 GtkCListRow *clist_row,
1001 if ((state == GTK_STATE_NORMAL) &&
1002 (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
1003 fg_state = GTK_STATE_INSENSITIVE;
1007 if (clist_row->cell[column].style)
1010 *style = clist_row->cell[column].style;
1012 *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
1014 if (state == GTK_STATE_SELECTED)
1015 *bg_gc = clist_row->cell[column].style->bg_gc[state];
1017 *bg_gc = clist_row->cell[column].style->base_gc[state];
1020 else if (clist_row->style)
1023 *style = clist_row->style;
1025 *fg_gc = clist_row->style->fg_gc[fg_state];
1027 if (state == GTK_STATE_SELECTED)
1028 *bg_gc = clist_row->style->bg_gc[state];
1030 *bg_gc = clist_row->style->base_gc[state];
1036 *style = GTK_WIDGET (clist)->style;
1038 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
1040 if (state == GTK_STATE_SELECTED)
1041 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1043 *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
1046 if (state != GTK_STATE_SELECTED)
1048 if (fg_gc && clist_row->fg_set)
1049 *fg_gc = clist->fg_gc;
1050 if (bg_gc && clist_row->bg_set)
1051 *bg_gc = clist->bg_gc;
1057 gtk_ctree_draw_expander (GtkCTree *ctree,
1058 GtkCTreeRow *ctree_row,
1060 GdkRectangle *clip_rectangle,
1065 gint justification_factor;
1068 if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
1071 clist = GTK_CLIST (ctree);
1072 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
1073 justification_factor = -1;
1075 justification_factor = 1;
1076 y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
1077 (clip_rectangle->height + 1) % 2);
1079 if (!ctree_row->children)
1081 switch (ctree->expander_style)
1083 case GTK_CTREE_EXPANDER_NONE:
1085 case GTK_CTREE_EXPANDER_TRIANGLE:
1086 return x + justification_factor * (PM_SIZE + 3);
1087 case GTK_CTREE_EXPANDER_SQUARE:
1088 case GTK_CTREE_EXPANDER_CIRCULAR:
1089 return x + justification_factor * (PM_SIZE + 1);
1093 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle);
1094 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle);
1096 switch (ctree->expander_style)
1098 case GTK_CTREE_EXPANDER_NONE:
1100 case GTK_CTREE_EXPANDER_TRIANGLE:
1101 if (ctree_row->expanded)
1104 points[0].y = y + (PM_SIZE + 2) / 6;
1105 points[1].x = points[0].x + justification_factor * (PM_SIZE + 2);
1106 points[1].y = points[0].y;
1107 points[2].x = (points[0].x +
1108 justification_factor * (PM_SIZE + 2) / 2);
1109 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
1113 points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2);
1114 points[0].y = y - 1;
1115 points[1].x = points[0].x;
1116 points[1].y = points[0].y + (PM_SIZE + 2);
1117 points[2].x = (points[0].x +
1118 justification_factor * (2 * (PM_SIZE + 2) / 3 - 1));
1119 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
1122 gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1124 gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1127 x += justification_factor * (PM_SIZE + 3);
1129 case GTK_CTREE_EXPANDER_SQUARE:
1130 case GTK_CTREE_EXPANDER_CIRCULAR:
1131 if (justification_factor == -1)
1132 x += justification_factor * (PM_SIZE + 1);
1134 if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
1136 gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1137 TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1138 gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1139 FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1143 gdk_draw_rectangle (clist->clist_window,
1144 style->base_gc[GTK_STATE_NORMAL], TRUE,
1145 x, y, PM_SIZE, PM_SIZE);
1146 gdk_draw_rectangle (clist->clist_window,
1147 style->fg_gc[GTK_STATE_NORMAL], FALSE,
1148 x, y, PM_SIZE, PM_SIZE);
1151 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1152 x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
1154 if (!ctree_row->expanded)
1155 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1156 x + PM_SIZE / 2, y + 2,
1157 x + PM_SIZE / 2, y + PM_SIZE - 2);
1159 if (justification_factor == 1)
1160 x += justification_factor * (PM_SIZE + 1);
1164 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
1165 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
1172 gtk_ctree_draw_lines (GtkCTree *ctree,
1173 GtkCTreeRow *ctree_row,
1177 GdkRectangle *clip_rectangle,
1178 GdkRectangle *cell_rectangle,
1179 GdkRectangle *crect,
1185 GtkCTreeNode *parent;
1186 GdkRectangle tree_rectangle;
1187 GdkRectangle tc_rectangle;
1198 gint justification_factor;
1200 clist = GTK_CLIST (ctree);
1201 ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
1202 justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
1206 offset = (clip_rectangle->x + clip_rectangle->width - 1 -
1207 ctree->tree_indent * (ctree_row->level - 1));
1208 justification_factor = -1;
1212 offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1);
1213 justification_factor = 1;
1216 switch (ctree->line_style)
1218 case GTK_CTREE_LINES_NONE:
1220 case GTK_CTREE_LINES_TABBED:
1221 xcenter = offset + justification_factor * TAB_SIZE;
1223 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1224 clist->column[ctree->tree_column].area.width +
1226 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1227 COLUMN_INSET - CELL_SPACING);
1231 tree_rectangle.y = crect->y;
1232 tree_rectangle.height = crect->height;
1236 tree_rectangle.x = xcenter;
1237 tree_rectangle.width = column_right - xcenter;
1241 tree_rectangle.x = column_left;
1242 tree_rectangle.width = xcenter - column_left;
1245 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1247 offset += justification_factor * 3;
1252 gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
1254 next_level = ctree_row->level;
1256 if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
1258 node = gtk_ctree_find_node_ptr (ctree, ctree_row);
1259 if (GTK_CTREE_NODE_NEXT (node))
1260 next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level;
1265 if (ctree->tree_indent > 0)
1267 node = ctree_row->parent;
1270 xcenter -= (justification_factor * ctree->tree_indent);
1272 if ((justify_right && xcenter < column_left) ||
1273 (!justify_right && xcenter > column_right))
1275 node = GTK_CTREE_ROW (node)->parent;
1279 tree_rectangle.y = cell_rectangle->y;
1280 tree_rectangle.height = cell_rectangle->height;
1283 tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1,
1285 tree_rectangle.width = MIN (xcenter - column_left,
1286 ctree->tree_indent);
1290 tree_rectangle.x = xcenter;
1291 tree_rectangle.width = MIN (column_right - xcenter,
1292 ctree->tree_indent);
1295 if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
1298 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1299 state, column, NULL, NULL, &bg_gc);
1301 if (bg_gc == clist->bg_gc)
1302 gdk_gc_set_foreground
1303 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1306 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1309 tree_rectangle.width,
1310 tree_rectangle.height);
1312 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1316 tc_rectangle.height);
1318 if (next_level > GTK_CTREE_ROW (node)->level)
1319 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1321 xcenter, crect->y + crect->height);
1326 offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1327 width = offset_x / 2 + offset_x % 2;
1329 parent = GTK_CTREE_ROW (node)->parent;
1331 tree_rectangle.y = ycenter;
1332 tree_rectangle.height = (cell_rectangle->y - ycenter +
1333 cell_rectangle->height);
1337 tree_rectangle.x = MAX(xcenter + 1 - width, column_left);
1338 tree_rectangle.width = MIN (xcenter + 1 - column_left,
1343 tree_rectangle.x = xcenter;
1344 tree_rectangle.width = MIN (column_right - xcenter,
1349 gdk_rectangle_intersect (area, &tree_rectangle,
1354 get_cell_style (clist, >K_CTREE_ROW (parent)->row,
1355 state, column, NULL, NULL, &bg_gc);
1356 if (bg_gc == clist->bg_gc)
1357 gdk_gc_set_foreground
1359 >K_CTREE_ROW (parent)->row.background);
1361 else if (state == GTK_STATE_SELECTED)
1362 bg_gc = style->base_gc[state];
1364 bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
1367 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1370 tree_rectangle.width,
1371 tree_rectangle.height);
1373 gdk_draw_rectangle (clist->clist_window,
1378 tc_rectangle.height);
1381 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1382 state, column, NULL, NULL, &bg_gc);
1383 if (bg_gc == clist->bg_gc)
1384 gdk_gc_set_foreground
1385 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1387 gdk_gc_set_clip_rectangle (bg_gc, crect);
1388 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1389 xcenter - (justify_right * offset_x),
1391 offset_x, clist->row_height,
1392 (180 + (justify_right * 90)) * 64, 90 * 64);
1393 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1395 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1396 xcenter, cell_rectangle->y, xcenter, ycenter);
1399 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1400 xcenter - offset_x, cell_rectangle->y,
1401 offset_x, clist->row_height,
1404 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1405 xcenter, cell_rectangle->y,
1406 offset_x, clist->row_height,
1409 node = GTK_CTREE_ROW (node)->parent;
1413 if (state != GTK_STATE_SELECTED)
1415 tree_rectangle.y = clip_rectangle->y;
1416 tree_rectangle.height = clip_rectangle->height;
1417 tree_rectangle.width = COLUMN_INSET + CELL_SPACING +
1418 MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET,
1422 tree_rectangle.x = MAX (xcenter + 1, column_left);
1424 tree_rectangle.x = column_left;
1427 gdk_draw_rectangle (clist->clist_window,
1429 (ctree)->style->base_gc[GTK_STATE_NORMAL],
1433 tree_rectangle.width,
1434 tree_rectangle.height);
1435 else if (gdk_rectangle_intersect (area, &tree_rectangle,
1437 gdk_draw_rectangle (clist->clist_window,
1439 (ctree)->style->base_gc[GTK_STATE_NORMAL],
1444 tc_rectangle.height);
1447 xcenter = offset + (justification_factor * ctree->tree_indent / 2);
1449 get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL,
1451 if (bg_gc == clist->bg_gc)
1452 gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background);
1454 gdk_gc_set_clip_rectangle (bg_gc, crect);
1455 if (ctree_row->is_leaf)
1459 points[0].x = offset + justification_factor * TAB_SIZE;
1460 points[0].y = cell_rectangle->y;
1462 points[1].x = points[0].x - justification_factor * 4;
1463 points[1].y = points[0].y;
1465 points[2].x = points[1].x - justification_factor * 2;
1466 points[2].y = points[1].y + 3;
1468 points[3].x = points[2].x;
1469 points[3].y = points[2].y + clist->row_height - 5;
1471 points[4].x = points[3].x + justification_factor * 2;
1472 points[4].y = points[3].y + 3;
1474 points[5].x = points[4].x + justification_factor * 4;
1475 points[5].y = points[4].y;
1477 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6);
1478 gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6);
1482 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1483 offset - (justify_right * 2 * TAB_SIZE),
1485 2 * TAB_SIZE, clist->row_height,
1486 (90 + (180 * justify_right)) * 64, 180 * 64);
1487 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1488 offset - (justify_right * 2 * TAB_SIZE),
1490 2 * TAB_SIZE, clist->row_height,
1491 (90 + (180 * justify_right)) * 64, 180 * 64);
1493 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1494 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1496 offset += justification_factor * 3;
1499 xcenter = offset + justification_factor * PM_SIZE / 2;
1503 tree_rectangle.y = crect->y;
1504 tree_rectangle.height = crect->height;
1508 tree_rectangle.x = xcenter - PM_SIZE / 2 - 2;
1509 tree_rectangle.width = (clip_rectangle->x +
1510 clip_rectangle->width -tree_rectangle.x);
1514 tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2;
1515 tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 -
1519 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1525 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1527 offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
1528 offset_y = abs((cell_rectangle->y + clist->voffset) % 2);
1531 clip_rectangle->y--;
1532 clip_rectangle->height++;
1533 gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle);
1534 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1536 (ctree->show_stub || clist->row_list->data != ctree_row) ?
1537 cell_rectangle->y + offset_y : ycenter,
1539 (ctree_row->sibling) ? crect->y +crect->height : ycenter);
1541 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1542 xcenter + (justification_factor * offset_x), ycenter,
1543 xcenter + (justification_factor * (PM_SIZE / 2 + 2)),
1546 node = ctree_row->parent;
1549 xcenter -= (justification_factor * ctree->tree_indent);
1551 if (GTK_CTREE_ROW (node)->sibling)
1552 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1553 xcenter, cell_rectangle->y + offset_y,
1554 xcenter, crect->y + crect->height);
1555 node = GTK_CTREE_ROW (node)->parent;
1557 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1558 clip_rectangle->y++;
1559 clip_rectangle->height--;
1566 draw_row (GtkCList *clist,
1569 GtkCListRow *clist_row)
1574 GdkRectangle *crect;
1575 GdkRectangle row_rectangle;
1576 GdkRectangle cell_rectangle;
1577 GdkRectangle clip_rectangle;
1578 GdkRectangle intersect_rectangle;
1580 gint column_left = 0;
1581 gint column_right = 0;
1586 g_return_if_fail (clist != NULL);
1588 /* bail now if we arn't drawable yet */
1589 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
1592 widget = GTK_WIDGET (clist);
1593 ctree = GTK_CTREE (clist);
1595 /* if the function is passed the pointer to the row instead of null,
1596 * it avoids this expensive lookup */
1598 clist_row = (g_list_nth (clist->row_list, row))->data;
1600 /* rectangle of the entire row */
1601 row_rectangle.x = 0;
1602 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1603 row_rectangle.width = clist->clist_window_width;
1604 row_rectangle.height = clist->row_height;
1606 /* rectangle of the cell spacing above the row */
1607 cell_rectangle.x = 0;
1608 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1609 cell_rectangle.width = row_rectangle.width;
1610 cell_rectangle.height = CELL_SPACING;
1612 /* rectangle used to clip drawing operations, it's y and height
1613 * positions only need to be set once, so we set them once here.
1614 * the x and width are set withing the drawing loop below once per
1616 clip_rectangle.y = row_rectangle.y;
1617 clip_rectangle.height = row_rectangle.height;
1619 if (clist_row->state == GTK_STATE_NORMAL)
1621 if (clist_row->fg_set)
1622 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1623 if (clist_row->bg_set)
1624 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1627 state = clist_row->state;
1629 gdk_gc_set_foreground (ctree->lines_gc,
1630 &widget->style->fg[clist_row->state]);
1632 /* draw the cell borders */
1635 rect = &intersect_rectangle;
1636 crect = &intersect_rectangle;
1638 if (gdk_rectangle_intersect (area, &cell_rectangle, crect))
1639 gdk_draw_rectangle (clist->clist_window,
1640 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1641 crect->x, crect->y, crect->width, crect->height);
1645 rect = &clip_rectangle;
1646 crect = &cell_rectangle;
1648 gdk_draw_rectangle (clist->clist_window,
1649 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1650 crect->x, crect->y, crect->width, crect->height);
1653 /* horizontal black lines */
1654 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1657 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1658 clist->column[ctree->tree_column].area.width +
1660 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1661 COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING);
1663 switch (clist->column[ctree->tree_column].justification)
1665 case GTK_JUSTIFY_CENTER:
1666 case GTK_JUSTIFY_FILL:
1667 case GTK_JUSTIFY_LEFT:
1668 offset = (column_left + ctree->tree_indent *
1669 (((GtkCTreeRow *)clist_row)->level - 1));
1671 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1672 MIN (offset + TAB_SIZE, column_right),
1674 clist->clist_window_width, cell_rectangle.y);
1676 case GTK_JUSTIFY_RIGHT:
1677 offset = (column_right - 1 - ctree->tree_indent *
1678 (((GtkCTreeRow *)clist_row)->level - 1));
1680 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1681 -1, cell_rectangle.y,
1682 MAX (offset - TAB_SIZE, column_left),
1688 /* the last row has to clear it's bottom cell spacing too */
1689 if (clist_row == clist->row_list_end->data)
1691 cell_rectangle.y += clist->row_height + CELL_SPACING;
1693 if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect))
1695 gdk_draw_rectangle (clist->clist_window,
1696 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1697 crect->x, crect->y, crect->width, crect->height);
1699 /* horizontal black lines */
1700 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1702 switch (clist->column[ctree->tree_column].justification)
1704 case GTK_JUSTIFY_CENTER:
1705 case GTK_JUSTIFY_FILL:
1706 case GTK_JUSTIFY_LEFT:
1707 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1708 MIN (column_left + TAB_SIZE + COLUMN_INSET +
1709 (((GtkCTreeRow *)clist_row)->level > 1) *
1710 MIN (ctree->tree_indent / 2, TAB_SIZE),
1713 clist->clist_window_width, cell_rectangle.y);
1715 case GTK_JUSTIFY_RIGHT:
1716 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1717 -1, cell_rectangle.y,
1718 MAX (column_right - TAB_SIZE - 1 -
1720 (((GtkCTreeRow *)clist_row)->level > 1) *
1721 MIN (ctree->tree_indent / 2, TAB_SIZE),
1722 column_left - 1), cell_rectangle.y);
1729 for (last_column = clist->columns - 1;
1730 last_column >= 0 && !clist->column[last_column].visible; last_column--)
1733 /* iterate and draw all the columns (row cells) and draw their contents */
1734 for (i = 0; i < clist->columns; i++)
1745 gint row_center_offset;
1747 if (!clist->column[i].visible)
1750 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
1752 /* calculate clipping region */
1753 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1754 clip_rectangle.width = clist->column[i].area.width;
1756 cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING;
1757 cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET +
1758 (1 + (i == last_column)) * CELL_SPACING);
1759 cell_rectangle.y = clip_rectangle.y;
1760 cell_rectangle.height = clip_rectangle.height;
1765 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
1766 &intersect_rectangle))
1768 if (i != ctree->tree_column)
1773 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1774 crect->x, crect->y, crect->width, crect->height);
1776 /* calculate real width for column justification */
1777 switch (clist_row->cell[i].type)
1780 width = gdk_string_width
1781 (style->font, GTK_CELL_TEXT (clist_row->cell[i])->text);
1783 case GTK_CELL_PIXMAP:
1785 (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
1787 width = pixmap_width;
1789 case GTK_CELL_PIXTEXT:
1790 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1792 (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1793 &pixmap_width, &height);
1795 width = pixmap_width;
1797 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text)
1799 string_width = gdk_string_width
1800 (style->font, GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1801 width += string_width;
1804 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text &&
1805 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1806 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1808 if (i == ctree->tree_column)
1809 width += (ctree->tree_indent *
1810 ((GtkCTreeRow *)clist_row)->level);
1817 switch (clist->column[i].justification)
1819 case GTK_JUSTIFY_LEFT:
1820 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
1822 case GTK_JUSTIFY_RIGHT:
1823 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
1824 clip_rectangle.width - width);
1826 case GTK_JUSTIFY_CENTER:
1827 case GTK_JUSTIFY_FILL:
1828 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
1829 (clip_rectangle.width / 2) - (width / 2));
1833 if (i != ctree->tree_column)
1835 offset += clist_row->cell[i].horizontal;
1836 switch (clist_row->cell[i].type)
1838 case GTK_CELL_PIXMAP:
1840 (clist->clist_window, &clip_rectangle, fg_gc,
1841 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1842 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
1844 clip_rectangle.y + clist_row->cell[i].vertical +
1845 (clip_rectangle.height - height) / 2,
1846 pixmap_width, height);
1848 case GTK_CELL_PIXTEXT:
1849 offset = draw_cell_pixmap
1850 (clist->clist_window, &clip_rectangle, fg_gc,
1851 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1852 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
1854 clip_rectangle.y + clist_row->cell[i].vertical +
1855 (clip_rectangle.height - height) / 2,
1856 pixmap_width, height);
1857 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1859 if (style != GTK_WIDGET (clist)->style)
1860 row_center_offset = (((clist->row_height -
1861 style->font->ascent -
1862 style->font->descent - 1) / 2) +
1863 1.5 + style->font->ascent);
1865 row_center_offset = clist->row_center_offset;
1867 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
1869 (clist->clist_window, style->font, fg_gc,
1871 row_rectangle.y + row_center_offset +
1872 clist_row->cell[i].vertical,
1873 (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
1874 GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
1875 GTK_CELL_TEXT (clist_row->cell[i])->text);
1876 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1885 if (bg_gc == clist->bg_gc)
1886 gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
1888 /* draw ctree->tree_column */
1889 cell_rectangle.y -= CELL_SPACING;
1890 cell_rectangle.height += CELL_SPACING;
1892 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
1893 &intersect_rectangle))
1897 offset = gtk_ctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
1898 state, &clip_rectangle, &cell_rectangle,
1899 crect, area, style);
1902 offset = gtk_ctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
1903 style, &clip_rectangle, offset);
1905 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1906 offset -= ctree->tree_spacing;
1908 offset += ctree->tree_spacing;
1910 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1911 offset -= (pixmap_width + clist_row->cell[i].horizontal);
1913 offset += clist_row->cell[i].horizontal;
1915 old_offset = offset;
1916 offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
1917 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1918 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
1920 clip_rectangle.y + clist_row->cell[i].vertical
1921 + (clip_rectangle.height - height) / 2,
1922 pixmap_width, height);
1926 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1928 offset = (old_offset - string_width);
1929 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1930 offset -= GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1934 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1935 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1938 if (style != GTK_WIDGET (clist)->style)
1939 row_center_offset = (((clist->row_height - style->font->ascent -
1940 style->font->descent - 1) / 2) +
1941 1.5 + style->font->ascent);
1943 row_center_offset = clist->row_center_offset;
1945 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
1946 gdk_draw_string (clist->clist_window, style->font, fg_gc, offset,
1947 row_rectangle.y + row_center_offset +
1948 clist_row->cell[i].vertical,
1949 GTK_CELL_PIXTEXT (clist_row->cell[i])->text);
1951 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1954 /* draw focus rectangle */
1955 if (clist->focus_row == row &&
1956 GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS (widget))
1959 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1960 row_rectangle.x, row_rectangle.y,
1961 row_rectangle.width - 1, row_rectangle.height - 1);
1962 else if (gdk_rectangle_intersect (area, &row_rectangle,
1963 &intersect_rectangle))
1965 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
1966 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1967 row_rectangle.x, row_rectangle.y,
1968 row_rectangle.width - 1,
1969 row_rectangle.height - 1);
1970 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
1976 tree_draw_node (GtkCTree *ctree,
1981 clist = GTK_CLIST (ctree);
1983 if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
1988 work = GTK_CTREE_NODE (clist->row_list);
1989 while (work && work != node)
1991 work = GTK_CTREE_NODE_NEXT (work);
1994 if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
1995 GTK_CLIST_CLASS_FW (clist)->draw_row
1996 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2000 static GtkCTreeNode *
2001 gtk_ctree_last_visible (GtkCTree *ctree,
2009 work = GTK_CTREE_ROW (node)->children;
2011 if (!work || !GTK_CTREE_ROW (node)->expanded)
2014 while (GTK_CTREE_ROW (work)->sibling)
2015 work = GTK_CTREE_ROW (work)->sibling;
2017 return gtk_ctree_last_visible (ctree, work);
2021 gtk_ctree_link (GtkCTree *ctree,
2023 GtkCTreeNode *parent,
2024 GtkCTreeNode *sibling,
2025 gboolean update_focus_row)
2031 gboolean visible = FALSE;
2035 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
2036 g_return_if_fail (node != NULL);
2037 g_return_if_fail (node != sibling);
2038 g_return_if_fail (node != parent);
2040 clist = GTK_CLIST (ctree);
2042 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2044 if (clist->anchor != -1)
2045 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2047 g_list_free (clist->undo_selection);
2048 g_list_free (clist->undo_unselection);
2049 clist->undo_selection = NULL;
2050 clist->undo_unselection = NULL;
2053 for (rows = 1, list_end = (GList *)node; list_end->next;
2054 list_end = list_end->next)
2057 GTK_CTREE_ROW (node)->parent = parent;
2058 GTK_CTREE_ROW (node)->sibling = sibling;
2060 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
2061 GTK_CTREE_ROW (parent)->expanded)))
2064 clist->rows += rows;
2068 work = (GList *)(GTK_CTREE_ROW (parent)->children);
2070 work = clist->row_list;
2074 if (work != (GList *)sibling)
2076 while (GTK_CTREE_ROW (work)->sibling != sibling)
2077 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2078 GTK_CTREE_ROW (work)->sibling = node;
2081 if (sibling == GTK_CTREE_NODE (clist->row_list))
2082 clist->row_list = (GList *) node;
2083 if (GTK_CTREE_NODE_PREV (sibling) &&
2084 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2086 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
2087 list->next = (GList *)node;
2090 list = (GList *)node;
2091 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
2092 list_end->next = (GList *)sibling;
2093 list = (GList *)sibling;
2094 list->prev = list_end;
2095 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2096 GTK_CTREE_ROW (parent)->children = node;
2103 while (GTK_CTREE_ROW (work)->sibling)
2104 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2105 GTK_CTREE_ROW (work)->sibling = node;
2107 /* find last visible child of sibling */
2108 work = (GList *) gtk_ctree_last_visible (ctree,
2109 GTK_CTREE_NODE (work));
2111 list_end->next = work->next;
2113 list = work->next->prev = list_end;
2114 work->next = (GList *)node;
2115 list = (GList *)node;
2122 GTK_CTREE_ROW (parent)->children = node;
2123 list = (GList *)node;
2124 list->prev = (GList *)parent;
2125 if (GTK_CTREE_ROW (parent)->expanded)
2127 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
2128 if (GTK_CTREE_NODE_NEXT(parent))
2130 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
2131 list->prev = list_end;
2133 list = (GList *)parent;
2134 list->next = (GList *)node;
2137 list_end->next = NULL;
2141 clist->row_list = (GList *)node;
2142 list = (GList *)node;
2144 list_end->next = NULL;
2149 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2151 if (clist->row_list_end == NULL ||
2152 clist->row_list_end->next == (GList *)node)
2153 clist->row_list_end = list_end;
2155 if (visible && update_focus_row)
2159 pos = g_list_position (clist->row_list, (GList *)node);
2161 if (pos <= clist->focus_row)
2163 clist->focus_row += rows;
2164 clist->undo_anchor = clist->focus_row;
2170 gtk_ctree_unlink (GtkCTree *ctree,
2172 gboolean update_focus_row)
2179 GtkCTreeNode *parent;
2182 g_return_if_fail (ctree != NULL);
2183 g_return_if_fail (GTK_IS_CTREE (ctree));
2184 g_return_if_fail (node != NULL);
2186 clist = GTK_CLIST (ctree);
2188 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2190 if (clist->anchor != -1)
2191 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2193 g_list_free (clist->undo_selection);
2194 g_list_free (clist->undo_unselection);
2195 clist->undo_selection = NULL;
2196 clist->undo_unselection = NULL;
2199 visible = gtk_ctree_is_viewable (ctree, node);
2201 /* clist->row_list_end unlinked ? */
2203 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2204 (GTK_CTREE_ROW (node)->children &&
2205 gtk_ctree_is_ancestor (ctree, node,
2206 GTK_CTREE_NODE (clist->row_list_end)))))
2207 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
2211 level = GTK_CTREE_ROW (node)->level;
2212 work = GTK_CTREE_NODE_NEXT (node);
2213 while (work && GTK_CTREE_ROW (work)->level > level)
2215 work = GTK_CTREE_NODE_NEXT (work);
2221 clist->rows -= (rows + 1);
2223 if (update_focus_row)
2227 pos = g_list_position (clist->row_list, (GList *)node);
2228 if (pos + rows < clist->focus_row)
2229 clist->focus_row -= (rows + 1);
2230 else if (pos <= clist->focus_row)
2232 if (!GTK_CTREE_ROW (node)->sibling)
2233 clist->focus_row = MAX (pos - 1, 0);
2235 clist->focus_row = pos;
2237 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
2239 clist->undo_anchor = clist->focus_row;
2245 list = (GList *)GTK_CTREE_NODE_PREV (work);
2247 list = (GList *)work;
2248 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
2251 if (GTK_CTREE_NODE_PREV (node) &&
2252 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2254 list = (GList *)GTK_CTREE_NODE_PREV (node);
2255 list->next = (GList *)work;
2259 parent = GTK_CTREE_ROW (node)->parent;
2262 if (GTK_CTREE_ROW (parent)->children == node)
2264 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2265 if (!GTK_CTREE_ROW (parent)->children)
2266 gtk_ctree_collapse (ctree, parent);
2270 GtkCTreeNode *sibling;
2272 sibling = GTK_CTREE_ROW (parent)->children;
2273 while (GTK_CTREE_ROW (sibling)->sibling != node)
2274 sibling = GTK_CTREE_ROW (sibling)->sibling;
2275 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2280 if (clist->row_list == (GList *)node)
2281 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
2284 GtkCTreeNode *sibling;
2286 sibling = GTK_CTREE_NODE (clist->row_list);
2287 while (GTK_CTREE_ROW (sibling)->sibling != node)
2288 sibling = GTK_CTREE_ROW (sibling)->sibling;
2289 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2295 real_row_move (GtkCList *clist,
2302 g_return_if_fail (clist != NULL);
2303 g_return_if_fail (GTK_IS_CTREE (clist));
2305 if (GTK_CLIST_AUTO_SORT (clist))
2308 if (source_row < 0 || source_row >= clist->rows ||
2309 dest_row < 0 || dest_row >= clist->rows ||
2310 source_row == dest_row)
2313 ctree = GTK_CTREE (clist);
2314 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, source_row));
2316 if (source_row < dest_row)
2321 work = GTK_CTREE_ROW (node)->children;
2323 while (work && GTK_CTREE_ROW (work)->level > GTK_CTREE_ROW (node)->level)
2325 work = GTK_CTREE_NODE_NEXT (work);
2329 if (dest_row > clist->rows)
2330 dest_row = clist->rows;
2333 if (dest_row < clist->rows)
2335 GtkCTreeNode *sibling;
2337 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, dest_row));
2338 gtk_ctree_move (ctree, node, GTK_CTREE_ROW (sibling)->parent, sibling);
2341 gtk_ctree_move (ctree, node, NULL, NULL);
2345 real_tree_move (GtkCTree *ctree,
2347 GtkCTreeNode *new_parent,
2348 GtkCTreeNode *new_sibling)
2352 gboolean visible = FALSE;
2354 g_return_if_fail (ctree != NULL);
2355 g_return_if_fail (node != NULL);
2356 g_return_if_fail (!new_sibling ||
2357 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2359 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2362 /* new_parent != child of child */
2363 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2367 clist = GTK_CLIST (ctree);
2369 visible = gtk_ctree_is_viewable (ctree, node);
2371 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2373 if (clist->anchor != -1)
2374 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2376 g_list_free (clist->undo_selection);
2377 g_list_free (clist->undo_unselection);
2378 clist->undo_selection = NULL;
2379 clist->undo_unselection = NULL;
2382 if (GTK_CLIST_AUTO_SORT (clist))
2384 if (new_parent == GTK_CTREE_ROW (node)->parent)
2388 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2390 new_sibling = GTK_CTREE_NODE (clist->row_list);
2392 while (new_sibling && clist->compare
2393 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
2394 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2397 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2398 new_sibling == GTK_CTREE_ROW (node)->sibling)
2401 gtk_clist_freeze (clist);
2404 if (gtk_ctree_is_viewable (ctree, node) ||
2405 gtk_ctree_is_viewable (ctree, new_sibling))
2406 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2408 gtk_ctree_unlink (ctree, node, FALSE);
2409 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2413 while (work && !gtk_ctree_is_viewable (ctree, work))
2414 work = GTK_CTREE_ROW (work)->parent;
2415 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2416 clist->undo_anchor = clist->focus_row;
2419 if (clist->column[ctree->tree_column].auto_resize &&
2420 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
2421 (visible || gtk_ctree_is_viewable (ctree, node)))
2422 gtk_clist_set_column_width
2423 (clist, ctree->tree_column,
2424 gtk_clist_optimal_column_width (clist, ctree->tree_column));
2426 gtk_clist_thaw (clist);
2430 change_focus_row_expansion (GtkCTree *ctree,
2431 GtkCTreeExpansionType action)
2436 g_return_if_fail (ctree != NULL);
2437 g_return_if_fail (GTK_IS_CTREE (ctree));
2439 clist = GTK_CLIST (ctree);
2441 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2445 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2446 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2451 case GTK_CTREE_EXPANSION_EXPAND:
2452 gtk_ctree_expand (ctree, node);
2454 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2455 gtk_ctree_expand_recursive (ctree, node);
2457 case GTK_CTREE_EXPANSION_COLLAPSE:
2458 gtk_ctree_collapse (ctree, node);
2460 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2461 gtk_ctree_collapse_recursive (ctree, node);
2463 case GTK_CTREE_EXPANSION_TOGGLE:
2464 gtk_ctree_toggle_expansion (ctree, node);
2466 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2467 gtk_ctree_toggle_expansion_recursive (ctree, node);
2473 real_tree_expand (GtkCTree *ctree,
2478 GtkRequisition requisition;
2482 g_return_if_fail (ctree != NULL);
2483 g_return_if_fail (GTK_IS_CTREE (ctree));
2485 if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
2488 clist = GTK_CLIST (ctree);
2490 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2491 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2493 GTK_CTREE_ROW (node)->expanded = TRUE;
2494 level = GTK_CTREE_ROW (node)->level;
2496 visible = gtk_ctree_is_viewable (ctree, node);
2497 /* get cell width if tree_column is auto resized */
2498 if (visible && clist->column[ctree->tree_column].auto_resize &&
2499 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2500 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2501 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2503 /* unref/unset closed pixmap */
2504 if (GTK_CELL_PIXTEXT
2505 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2509 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2512 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2514 if (GTK_CELL_PIXTEXT
2515 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2519 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2521 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2525 /* set/ref opened pixmap */
2526 if (GTK_CTREE_ROW (node)->pixmap_opened)
2529 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2530 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
2532 if (GTK_CTREE_ROW (node)->mask_opened)
2534 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2535 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
2539 work = GTK_CTREE_ROW (node)->children;
2542 GList *list = (GList *)work;
2543 gint *cell_width = NULL;
2548 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2550 cell_width = g_new0 (gint, clist->columns);
2551 if (clist->column[ctree->tree_column].auto_resize)
2552 cell_width[ctree->tree_column] = requisition.width;
2556 /* search maximum cell widths of auto_resize columns */
2557 for (i = 0; i < clist->columns; i++)
2558 if (clist->column[i].auto_resize)
2560 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2561 (clist, >K_CTREE_ROW (work)->row, i, &requisition);
2562 cell_width[i] = MAX (requisition.width, cell_width[i]);
2565 list = (GList *)work;
2566 work = GTK_CTREE_NODE_NEXT (work);
2573 list = (GList *)work;
2574 work = GTK_CTREE_NODE_NEXT (work);
2578 list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
2580 if (GTK_CTREE_NODE_NEXT (node))
2584 tmp_list = (GList *)GTK_CTREE_NODE_NEXT (node);
2585 tmp_list->prev = list;
2588 clist->row_list_end = list;
2590 list = (GList *)node;
2591 list->next = (GList *)(GTK_CTREE_ROW (node)->children);
2595 /* resize auto_resize columns if needed */
2596 for (i = 0; i < clist->columns; i++)
2597 if (clist->column[i].auto_resize &&
2598 cell_width[i] > clist->column[i].width)
2599 gtk_clist_set_column_width (clist, i, cell_width[i]);
2600 g_free (cell_width);
2602 /* update focus_row position */
2603 row = g_list_position (clist->row_list, (GList *)node);
2604 if (row < clist->focus_row)
2605 clist->focus_row += tmp;
2608 CLIST_REFRESH (clist);
2611 else if (visible && clist->column[ctree->tree_column].auto_resize)
2612 /* resize tree_column if needed */
2613 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2618 real_tree_collapse (GtkCTree *ctree,
2623 GtkRequisition requisition;
2627 g_return_if_fail (ctree != NULL);
2628 g_return_if_fail (GTK_IS_CTREE (ctree));
2630 if (!node || !GTK_CTREE_ROW (node)->expanded ||
2631 GTK_CTREE_ROW (node)->is_leaf)
2634 clist = GTK_CLIST (ctree);
2636 if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0)
2637 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
2639 GTK_CTREE_ROW (node)->expanded = FALSE;
2640 level = GTK_CTREE_ROW (node)->level;
2642 visible = gtk_ctree_is_viewable (ctree, node);
2643 /* get cell width if tree_column is auto resized */
2644 if (visible && clist->column[ctree->tree_column].auto_resize &&
2645 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2646 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2647 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2649 /* unref/unset opened pixmap */
2650 if (GTK_CELL_PIXTEXT
2651 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2655 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2658 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2660 if (GTK_CELL_PIXTEXT
2661 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2665 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2667 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2671 /* set/ref closed pixmap */
2672 if (GTK_CTREE_ROW (node)->pixmap_closed)
2675 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2676 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed);
2678 if (GTK_CTREE_ROW (node)->mask_closed)
2680 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2681 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed);
2684 work = GTK_CTREE_ROW (node)->children;
2691 while (work && GTK_CTREE_ROW (work)->level > level)
2693 work = GTK_CTREE_NODE_NEXT (work);
2699 list = (GList *)node;
2700 list->next = (GList *)work;
2701 list = (GList *)GTK_CTREE_NODE_PREV (work);
2703 list = (GList *)work;
2704 list->prev = (GList *)node;
2708 list = (GList *)node;
2710 clist->row_list_end = (GList *)node;
2715 /* resize auto_resize columns if needed */
2716 auto_resize_columns (clist);
2718 row = g_list_position (clist->row_list, (GList *)node);
2719 if (row < clist->focus_row)
2720 clist->focus_row -= tmp;
2722 CLIST_REFRESH (clist);
2725 else if (visible && clist->column[ctree->tree_column].auto_resize &&
2726 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2727 /* resize tree_column if needed */
2728 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2734 column_auto_resize (GtkCList *clist,
2735 GtkCListRow *clist_row,
2739 /* resize column if needed for auto_resize */
2740 GtkRequisition requisition;
2742 if (!clist->column[column].auto_resize ||
2743 GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2747 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2748 column, &requisition);
2750 requisition.width = 0;
2752 if (requisition.width > clist->column[column].width)
2753 gtk_clist_set_column_width (clist, column, requisition.width);
2754 else if (requisition.width < old_width &&
2755 old_width == clist->column[column].width)
2760 /* run a "gtk_clist_optimal_column_width" but break, if
2761 * the column doesn't shrink */
2762 if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
2763 new_width = (clist->column[column].button->requisition.width -
2764 (CELL_SPACING + (2 * COLUMN_INSET)));
2768 for (list = clist->row_list; list; list = list->next)
2770 GTK_CLIST_CLASS_FW (clist)->cell_size_request
2771 (clist, GTK_CLIST_ROW (list), column, &requisition);
2772 new_width = MAX (new_width, requisition.width);
2773 if (new_width == clist->column[column].width)
2776 if (new_width < clist->column[column].width)
2777 gtk_clist_set_column_width (clist, column, new_width);
2782 auto_resize_columns (GtkCList *clist)
2786 if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2789 for (i = 0; i < clist->columns; i++)
2790 column_auto_resize (clist, NULL, i, clist->column[i].width);
2794 cell_size_request (GtkCList *clist,
2795 GtkCListRow *clist_row,
2797 GtkRequisition *requisition)
2804 g_return_if_fail (clist != NULL);
2805 g_return_if_fail (GTK_IS_CTREE (clist));
2806 g_return_if_fail (requisition != NULL);
2808 ctree = GTK_CTREE (clist);
2810 get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
2813 switch (clist_row->cell[column].type)
2816 requisition->width =
2817 gdk_string_width (style->font,
2818 GTK_CELL_TEXT (clist_row->cell[column])->text);
2819 requisition->height = style->font->ascent + style->font->descent;
2821 case GTK_CELL_PIXTEXT:
2822 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
2824 gdk_window_get_size (GTK_CELL_PIXTEXT
2825 (clist_row->cell[column])->pixmap,
2827 width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2832 requisition->width = width +
2833 gdk_string_width (style->font,
2834 GTK_CELL_TEXT (clist_row->cell[column])->text);
2836 requisition->height = MAX (style->font->ascent + style->font->descent,
2838 if (column == ctree->tree_column)
2840 requisition->width += (ctree->tree_spacing + ctree->tree_indent *
2841 (((GtkCTreeRow *) clist_row)->level - 1));
2842 switch (ctree->expander_style)
2844 case GTK_CTREE_EXPANDER_NONE:
2846 case GTK_CTREE_EXPANDER_TRIANGLE:
2847 requisition->width += PM_SIZE + 3;
2849 case GTK_CTREE_EXPANDER_SQUARE:
2850 case GTK_CTREE_EXPANDER_CIRCULAR:
2851 requisition->width += PM_SIZE + 1;
2854 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2855 requisition->width += 3;
2858 case GTK_CELL_PIXMAP:
2859 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
2861 requisition->width = width;
2862 requisition->height = height;
2865 requisition->width = 0;
2866 requisition->height = 0;
2870 requisition->width += clist_row->cell[column].horizontal;
2871 requisition->height += clist_row->cell[column].vertical;
2875 set_cell_contents (GtkCList *clist,
2876 GtkCListRow *clist_row,
2884 gboolean visible = FALSE;
2886 GtkRequisition requisition;
2888 g_return_if_fail (clist != NULL);
2889 g_return_if_fail (GTK_IS_CTREE (clist));
2890 g_return_if_fail (clist_row != NULL);
2892 ctree = GTK_CTREE (clist);
2894 if (clist->column[column].auto_resize &&
2895 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2897 GtkCTreeNode *parent;
2899 parent = ((GtkCTreeRow *)clist_row)->parent;
2900 if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded &&
2901 gtk_ctree_is_viewable (ctree, parent)))
2904 GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
2905 column, &requisition);
2909 switch (clist_row->cell[column].type)
2911 case GTK_CELL_EMPTY:
2915 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2917 case GTK_CELL_PIXMAP:
2918 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2919 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
2920 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2922 case GTK_CELL_PIXTEXT:
2923 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
2924 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2925 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
2928 (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2929 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
2931 (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2934 case GTK_CELL_WIDGET:
2942 clist_row->cell[column].type = GTK_CELL_EMPTY;
2943 if (column == ctree->tree_column && type != GTK_CELL_EMPTY)
2944 type = GTK_CELL_PIXTEXT;
2951 clist_row->cell[column].type = GTK_CELL_TEXT;
2952 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2955 case GTK_CELL_PIXMAP:
2958 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2959 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2960 /* We set the mask even if it is NULL */
2961 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2964 case GTK_CELL_PIXTEXT:
2965 if (column == ctree->tree_column)
2967 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2968 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2970 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2972 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL;
2975 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2976 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2980 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
2981 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
2984 else if (text && pixmap)
2986 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2987 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2988 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2989 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2990 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
2997 if (visible && clist->column[column].auto_resize &&
2998 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2999 column_auto_resize (clist, clist_row, column, requisition.width);
3003 set_node_info (GtkCTree *ctree,
3007 GdkPixmap *pixmap_closed,
3008 GdkBitmap *mask_closed,
3009 GdkPixmap *pixmap_opened,
3010 GdkBitmap *mask_opened,
3014 if (GTK_CTREE_ROW (node)->pixmap_opened)
3016 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3017 if (GTK_CTREE_ROW (node)->mask_opened)
3018 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3020 if (GTK_CTREE_ROW (node)->pixmap_closed)
3022 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3023 if (GTK_CTREE_ROW (node)->mask_closed)
3024 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3027 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3028 GTK_CTREE_ROW (node)->mask_opened = NULL;
3029 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3030 GTK_CTREE_ROW (node)->mask_closed = NULL;
3034 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3036 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3040 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3042 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3045 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3046 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3048 if (GTK_CTREE_ROW (node)->expanded)
3049 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3050 text, spacing, pixmap_opened, mask_opened);
3052 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3053 text, spacing, pixmap_closed, mask_closed);
3057 tree_delete (GtkCTree *ctree,
3063 clist = GTK_CLIST (ctree);
3065 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3069 work = g_list_find (clist->selection, node);
3072 if (clist->selection_end && clist->selection_end == work)
3073 clist->selection_end = clist->selection_end->prev;
3074 clist->selection = g_list_remove_link (clist->selection, work);
3075 g_list_free_1 (work);
3079 row_delete (ctree, GTK_CTREE_ROW (node));
3080 g_list_free_1 ((GList *)node);
3084 tree_delete_row (GtkCTree *ctree,
3088 row_delete (ctree, GTK_CTREE_ROW (node));
3089 g_list_free_1 ((GList *)node);
3093 tree_update_level (GtkCTree *ctree,
3100 if (GTK_CTREE_ROW (node)->parent)
3101 GTK_CTREE_ROW (node)->level =
3102 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3104 GTK_CTREE_ROW (node)->level = 1;
3108 tree_select (GtkCTree *ctree,
3112 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
3113 GTK_CTREE_ROW (node)->row.selectable)
3114 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3119 tree_unselect (GtkCTree *ctree,
3123 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3124 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3129 tree_expand (GtkCTree *ctree,
3133 if (node && !GTK_CTREE_ROW (node)->expanded)
3134 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3138 tree_collapse (GtkCTree *ctree,
3142 if (node && GTK_CTREE_ROW (node)->expanded)
3143 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3147 tree_collapse_to_depth (GtkCTree *ctree,
3151 if (node && GTK_CTREE_ROW (node)->level == depth)
3152 gtk_ctree_collapse_recursive (ctree, node);
3156 tree_toggle_expansion (GtkCTree *ctree,
3163 if (GTK_CTREE_ROW (node)->expanded)
3164 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3166 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3169 static GtkCTreeRow *
3170 row_new (GtkCTree *ctree)
3173 GtkCTreeRow *ctree_row;
3176 clist = GTK_CLIST (ctree);
3177 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3178 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3180 for (i = 0; i < clist->columns; i++)
3182 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3183 ctree_row->row.cell[i].vertical = 0;
3184 ctree_row->row.cell[i].horizontal = 0;
3185 ctree_row->row.cell[i].style = NULL;
3188 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3190 ctree_row->row.fg_set = FALSE;
3191 ctree_row->row.bg_set = FALSE;
3192 ctree_row->row.style = NULL;
3193 ctree_row->row.selectable = TRUE;
3194 ctree_row->row.state = GTK_STATE_NORMAL;
3195 ctree_row->row.data = NULL;
3196 ctree_row->row.destroy = NULL;
3198 ctree_row->level = 0;
3199 ctree_row->expanded = FALSE;
3200 ctree_row->parent = NULL;
3201 ctree_row->sibling = NULL;
3202 ctree_row->children = NULL;
3203 ctree_row->pixmap_closed = NULL;
3204 ctree_row->mask_closed = NULL;
3205 ctree_row->pixmap_opened = NULL;
3206 ctree_row->mask_opened = NULL;
3212 row_delete (GtkCTree *ctree,
3213 GtkCTreeRow *ctree_row)
3218 clist = GTK_CLIST (ctree);
3220 for (i = 0; i < clist->columns; i++)
3222 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3223 (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
3224 if (ctree_row->row.cell[i].style)
3226 if (GTK_WIDGET_REALIZED (ctree))
3227 gtk_style_detach (ctree_row->row.cell[i].style);
3228 gtk_style_unref (ctree_row->row.cell[i].style);
3232 if (ctree_row->row.style)
3234 if (GTK_WIDGET_REALIZED (ctree))
3235 gtk_style_detach (ctree_row->row.style);
3236 gtk_style_unref (ctree_row->row.style);
3239 if (ctree_row->pixmap_closed)
3241 gdk_pixmap_unref (ctree_row->pixmap_closed);
3242 if (ctree_row->mask_closed)
3243 gdk_bitmap_unref (ctree_row->mask_closed);
3246 if (ctree_row->pixmap_opened)
3248 gdk_pixmap_unref (ctree_row->pixmap_opened);
3249 if (ctree_row->mask_opened)
3250 gdk_bitmap_unref (ctree_row->mask_opened);
3253 if (ctree_row->row.destroy)
3254 ctree_row->row.destroy (ctree_row->row.data);
3256 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3257 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3261 real_select_row (GtkCList *clist,
3268 g_return_if_fail (clist != NULL);
3269 g_return_if_fail (GTK_IS_CTREE (clist));
3271 if ((node = g_list_nth (clist->row_list, row)) &&
3272 GTK_CTREE_ROW (node)->row.selectable)
3273 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3278 real_unselect_row (GtkCList *clist,
3285 g_return_if_fail (clist != NULL);
3286 g_return_if_fail (GTK_IS_CTREE (clist));
3288 if ((node = g_list_nth (clist->row_list, row)))
3289 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3294 real_tree_select (GtkCTree *ctree,
3300 GtkCTreeNode *sel_row;
3301 gboolean node_selected;
3303 g_return_if_fail (ctree != NULL);
3304 g_return_if_fail (GTK_IS_CTREE (ctree));
3306 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3307 !GTK_CTREE_ROW (node)->row.selectable)
3310 clist = GTK_CLIST (ctree);
3312 switch (clist->selection_mode)
3314 case GTK_SELECTION_SINGLE:
3315 case GTK_SELECTION_BROWSE:
3317 node_selected = FALSE;
3318 list = clist->selection;
3322 sel_row = list->data;
3325 if (node == sel_row)
3326 node_selected = TRUE;
3328 gtk_signal_emit (GTK_OBJECT (ctree),
3329 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3339 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3341 if (!clist->selection)
3343 clist->selection = g_list_append (clist->selection, node);
3344 clist->selection_end = clist->selection;
3347 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3349 tree_draw_node (ctree, node);
3353 real_tree_unselect (GtkCTree *ctree,
3359 g_return_if_fail (ctree != NULL);
3360 g_return_if_fail (GTK_IS_CTREE (ctree));
3362 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3365 clist = GTK_CLIST (ctree);
3367 if (clist->selection_end && clist->selection_end->data == node)
3368 clist->selection_end = clist->selection_end->prev;
3370 clist->selection = g_list_remove (clist->selection, node);
3372 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3374 tree_draw_node (ctree, node);
3378 select_row_recursive (GtkCTree *ctree,
3382 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3383 !GTK_CTREE_ROW (node)->row.selectable)
3386 GTK_CLIST (ctree)->undo_unselection =
3387 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3388 gtk_ctree_select (ctree, node);
3392 real_select_all (GtkCList *clist)
3397 g_return_if_fail (clist != NULL);
3398 g_return_if_fail (GTK_IS_CTREE (clist));
3400 ctree = GTK_CTREE (clist);
3402 switch (clist->selection_mode)
3404 case GTK_SELECTION_SINGLE:
3405 case GTK_SELECTION_BROWSE:
3408 case GTK_SELECTION_EXTENDED:
3410 gtk_clist_freeze (clist);
3412 g_list_free (clist->undo_selection);
3413 g_list_free (clist->undo_unselection);
3414 clist->undo_selection = NULL;
3415 clist->undo_unselection = NULL;
3417 clist->anchor_state = GTK_STATE_SELECTED;
3419 clist->drag_pos = -1;
3420 clist->undo_anchor = clist->focus_row;
3422 for (node = GTK_CTREE_NODE (clist->row_list); node;
3423 node = GTK_CTREE_NODE_NEXT (node))
3424 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3426 gtk_clist_thaw (clist);
3429 case GTK_SELECTION_MULTIPLE:
3430 gtk_ctree_select_recursive (ctree, NULL);
3440 real_unselect_all (GtkCList *clist)
3446 g_return_if_fail (clist != NULL);
3447 g_return_if_fail (GTK_IS_CTREE (clist));
3449 ctree = GTK_CTREE (clist);
3451 switch (clist->selection_mode)
3453 case GTK_SELECTION_BROWSE:
3454 if (clist->focus_row >= 0)
3458 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3463 case GTK_SELECTION_EXTENDED:
3464 g_list_free (clist->undo_selection);
3465 g_list_free (clist->undo_unselection);
3466 clist->undo_selection = NULL;
3467 clist->undo_unselection = NULL;
3470 clist->drag_pos = -1;
3471 clist->undo_anchor = clist->focus_row;
3478 list = clist->selection;
3484 gtk_ctree_unselect (ctree, node);
3489 ctree_is_hot_spot (GtkCTree *ctree,
3495 GtkCTreeRow *tree_row;
3497 GtkCellPixText *cell;
3501 g_return_val_if_fail (ctree != NULL, FALSE);
3502 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3503 g_return_val_if_fail (node != NULL, FALSE);
3505 clist = GTK_CLIST (ctree);
3507 if (!clist->column[ctree->tree_column].visible ||
3508 ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
3511 tree_row = GTK_CTREE_ROW (node);
3513 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3515 yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
3516 (clist->row_height - 1) % 2);
3518 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3519 xl = (clist->column[ctree->tree_column].area.x +
3520 clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
3521 (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
3522 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3524 xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
3525 (tree_row->level - 1) * ctree->tree_indent +
3526 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3528 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3531 /***********************************************************
3532 ***********************************************************
3533 *** Public interface ***
3534 ***********************************************************
3535 ***********************************************************/
3538 /***********************************************************
3539 * Creation, insertion, deletion *
3540 ***********************************************************/
3543 gtk_ctree_construct (GtkCTree *ctree,
3550 g_return_if_fail (ctree != NULL);
3551 g_return_if_fail (GTK_IS_CTREE (ctree));
3552 g_return_if_fail (GTK_OBJECT_CONSTRUCTED (ctree) == FALSE);
3554 clist = GTK_CLIST (ctree);
3556 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
3557 sizeof (GtkCTreeRow),
3558 sizeof (GtkCTreeRow)
3559 * CLIST_OPTIMUM_SIZE,
3562 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
3563 sizeof (GtkCell) * columns,
3564 sizeof (GtkCell) * columns
3565 * CLIST_OPTIMUM_SIZE,
3568 ctree->tree_column = tree_column;
3570 gtk_clist_construct (clist, columns, titles);
3574 gtk_ctree_new_with_titles (gint columns,
3580 g_return_val_if_fail (columns > 0, NULL);
3581 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3583 widget = gtk_type_new (GTK_TYPE_CTREE);
3584 gtk_ctree_construct (GTK_CTREE (widget), columns, tree_column, titles);
3590 gtk_ctree_new (gint columns,
3593 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3597 real_insert_row (GtkCList *clist,
3601 GtkCTreeNode *parent = NULL;
3602 GtkCTreeNode *sibling;
3605 g_return_val_if_fail (clist != NULL, -1);
3606 g_return_val_if_fail (GTK_IS_CTREE (clist), -1);
3608 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3610 parent = GTK_CTREE_ROW (sibling)->parent;
3612 node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5,
3613 NULL, NULL, NULL, NULL, TRUE, FALSE);
3615 if (GTK_CLIST_AUTO_SORT (clist) || !sibling)
3616 return g_list_position (clist->row_list, (GList *) node);
3622 gtk_ctree_insert_node (GtkCTree *ctree,
3623 GtkCTreeNode *parent,
3624 GtkCTreeNode *sibling,
3627 GdkPixmap *pixmap_closed,
3628 GdkBitmap *mask_closed,
3629 GdkPixmap *pixmap_opened,
3630 GdkBitmap *mask_opened,
3635 GtkCTreeRow *new_row;
3640 g_return_val_if_fail (ctree != NULL, NULL);
3641 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3643 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3645 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
3648 clist = GTK_CLIST (ctree);
3650 /* create the row */
3651 new_row = row_new (ctree);
3652 list = g_list_alloc ();
3653 list->data = new_row;
3654 node = GTK_CTREE_NODE (list);
3657 for (i = 0; i < clist->columns; i++)
3658 if (text[i] && i != ctree->tree_column)
3659 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
3660 (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
3662 set_node_info (ctree, node, text ?
3663 text[ctree->tree_column] : NULL, spacing, pixmap_closed,
3664 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
3666 /* sorted insertion */
3667 if (GTK_CLIST_AUTO_SORT (clist))
3670 sibling = GTK_CTREE_ROW (parent)->children;
3672 sibling = GTK_CTREE_NODE (clist->row_list);
3674 while (sibling && clist->compare
3675 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
3676 sibling = GTK_CTREE_ROW (sibling)->sibling;
3679 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
3681 if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
3682 gtk_ctree_is_viewable (ctree, node))
3684 for (i = 0; i < clist->columns; i++)
3685 if (clist->column[i].auto_resize)
3686 column_auto_resize (clist, &(new_row->row), i, 0);
3689 if (clist->rows == 1)
3691 clist->focus_row = 0;
3692 if (clist->selection_mode == GTK_SELECTION_BROWSE)
3693 gtk_ctree_select (ctree, node);
3697 CLIST_REFRESH (clist);
3703 gtk_ctree_insert_gnode (GtkCTree *ctree,
3704 GtkCTreeNode *parent,
3705 GtkCTreeNode *sibling,
3707 GtkCTreeGNodeFunc func,
3711 GtkCTreeNode *cnode = NULL;
3712 GtkCTreeNode *child = NULL;
3713 GtkCTreeNode *new_child;
3718 g_return_val_if_fail (ctree != NULL, NULL);
3719 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3720 g_return_val_if_fail (gnode != NULL, NULL);
3721 g_return_val_if_fail (func != NULL, NULL);
3723 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3725 clist = GTK_CLIST (ctree);
3728 depth = GTK_CTREE_ROW (parent)->level + 1;
3730 list = g_list_alloc ();
3731 list->data = row_new (ctree);
3732 cnode = GTK_CTREE_NODE (list);
3734 gtk_clist_freeze (clist);
3736 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
3738 if (!func (ctree, depth, gnode, cnode, data))
3740 tree_delete_row (ctree, cnode, NULL);
3744 if (GTK_CLIST_AUTO_SORT (clist))
3747 sibling = GTK_CTREE_ROW (parent)->children;
3749 sibling = GTK_CTREE_NODE (clist->row_list);
3751 while (sibling && clist->compare
3752 (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
3753 sibling = GTK_CTREE_ROW (sibling)->sibling;
3756 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
3758 for (work = g_node_last_child (gnode); work; work = work->prev)
3760 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
3766 gtk_clist_thaw (clist);
3772 gtk_ctree_export_to_gnode (GtkCTree *ctree,
3776 GtkCTreeGNodeFunc func,
3783 g_return_val_if_fail (ctree != NULL, NULL);
3784 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3785 g_return_val_if_fail (node != NULL, NULL);
3786 g_return_val_if_fail (func != NULL, NULL);
3789 g_return_val_if_fail (parent != NULL, NULL);
3790 g_return_val_if_fail (sibling->parent == parent, NULL);
3793 gnode = g_node_new (NULL);
3794 depth = g_node_depth (parent) + 1;
3796 if (!func (ctree, depth, gnode, node, data))
3798 g_node_destroy (gnode);
3803 g_node_insert_before (parent, sibling, gnode);
3805 if (!GTK_CTREE_ROW (node)->is_leaf)
3807 GNode *new_sibling = NULL;
3809 for (work = GTK_CTREE_ROW (node)->children; work;
3810 work = GTK_CTREE_ROW (work)->sibling)
3811 new_sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling,
3814 g_node_reverse_children (gnode);
3821 real_remove_row (GtkCList *clist,
3826 g_return_if_fail (clist != NULL);
3827 g_return_if_fail (GTK_IS_CTREE (clist));
3829 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3832 gtk_ctree_remove_node (GTK_CTREE (clist), node);
3836 gtk_ctree_remove_node (GtkCTree *ctree,
3841 g_return_if_fail (ctree != NULL);
3842 g_return_if_fail (GTK_IS_CTREE (ctree));
3844 clist = GTK_CLIST (ctree);
3846 gtk_clist_freeze (clist);
3852 visible = gtk_ctree_is_viewable (ctree, node);
3853 gtk_ctree_unlink (ctree, node, TRUE);
3854 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
3856 if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
3857 clist->focus_row >= 0)
3858 gtk_clist_select_row (clist, clist->focus_row, -1);
3860 auto_resize_columns (clist);
3863 gtk_clist_clear (clist);
3865 gtk_clist_thaw (clist);
3869 real_clear (GtkCList *clist)
3875 g_return_if_fail (clist != NULL);
3876 g_return_if_fail (GTK_IS_CTREE (clist));
3878 ctree = GTK_CTREE (clist);
3880 /* remove all rows */
3881 work = GTK_CTREE_NODE (clist->row_list);
3882 clist->row_list = NULL;
3883 clist->row_list_end = NULL;
3885 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
3889 work = GTK_CTREE_ROW (work)->sibling;
3890 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
3893 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
3895 parent_class->clear (clist);
3899 /***********************************************************
3900 * Generic recursive functions, querying / finding tree *
3902 ***********************************************************/
3906 gtk_ctree_post_recursive (GtkCTree *ctree,
3914 g_return_if_fail (ctree != NULL);
3915 g_return_if_fail (GTK_IS_CTREE (ctree));
3916 g_return_if_fail (func != NULL);
3919 work = GTK_CTREE_ROW (node)->children;
3921 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3925 tmp = GTK_CTREE_ROW (work)->sibling;
3926 gtk_ctree_post_recursive (ctree, work, func, data);
3931 func (ctree, node, data);
3935 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
3944 g_return_if_fail (ctree != NULL);
3945 g_return_if_fail (GTK_IS_CTREE (ctree));
3946 g_return_if_fail (func != NULL);
3950 gtk_ctree_post_recursive (ctree, node, func, data);
3955 work = GTK_CTREE_ROW (node)->children;
3957 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3959 if (work && GTK_CTREE_ROW (work)->level <= depth)
3963 tmp = GTK_CTREE_ROW (work)->sibling;
3964 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
3969 if (node && GTK_CTREE_ROW (node)->level <= depth)
3970 func (ctree, node, data);
3974 gtk_ctree_pre_recursive (GtkCTree *ctree,
3982 g_return_if_fail (ctree != NULL);
3983 g_return_if_fail (GTK_IS_CTREE (ctree));
3984 g_return_if_fail (func != NULL);
3988 work = GTK_CTREE_ROW (node)->children;
3989 func (ctree, node, data);
3992 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3996 tmp = GTK_CTREE_ROW (work)->sibling;
3997 gtk_ctree_pre_recursive (ctree, work, func, data);
4003 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4012 g_return_if_fail (ctree != NULL);
4013 g_return_if_fail (GTK_IS_CTREE (ctree));
4014 g_return_if_fail (func != NULL);
4018 gtk_ctree_pre_recursive (ctree, node, func, data);
4024 work = GTK_CTREE_ROW (node)->children;
4025 if (GTK_CTREE_ROW (node)->level <= depth)
4026 func (ctree, node, data);
4029 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4031 if (work && GTK_CTREE_ROW (work)->level <= depth)
4035 tmp = GTK_CTREE_ROW (work)->sibling;
4036 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4043 gtk_ctree_is_viewable (GtkCTree *ctree,
4048 g_return_val_if_fail (ctree != NULL, FALSE);
4049 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4050 g_return_val_if_fail (node != NULL, FALSE);
4052 work = GTK_CTREE_ROW (node);
4054 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4055 work = GTK_CTREE_ROW (work->parent);
4064 gtk_ctree_last (GtkCTree *ctree,
4067 g_return_val_if_fail (ctree != NULL, NULL);
4068 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4073 while (GTK_CTREE_ROW (node)->sibling)
4074 node = GTK_CTREE_ROW (node)->sibling;
4076 if (GTK_CTREE_ROW (node)->children)
4077 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4083 gtk_ctree_find_node_ptr (GtkCTree *ctree,
4084 GtkCTreeRow *ctree_row)
4088 g_return_val_if_fail (ctree != NULL, FALSE);
4089 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4090 g_return_val_if_fail (ctree_row != NULL, FALSE);
4092 if (ctree_row->parent)
4093 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4095 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4097 while (GTK_CTREE_ROW (node) != ctree_row)
4098 node = GTK_CTREE_ROW (node)->sibling;
4104 gtk_ctree_node_nth (GtkCTree *ctree,
4107 g_return_val_if_fail (ctree != NULL, NULL);
4108 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4110 if ((row < 0) || (row >= GTK_CLIST(ctree)->rows))
4113 return GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
4117 gtk_ctree_find (GtkCTree *ctree,
4119 GtkCTreeNode *child)
4125 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4131 if (GTK_CTREE_ROW (node)->children)
4133 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4136 node = GTK_CTREE_ROW (node)->sibling;
4142 gtk_ctree_is_ancestor (GtkCTree *ctree,
4144 GtkCTreeNode *child)
4146 g_return_val_if_fail (node != NULL, FALSE);
4148 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4152 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4159 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4163 if (GTK_CTREE_ROW (node)->row.data == data)
4165 if (GTK_CTREE_ROW (node)->children &&
4166 (work = gtk_ctree_find_by_row_data
4167 (ctree, GTK_CTREE_ROW (node)->children, data)))
4169 node = GTK_CTREE_ROW (node)->sibling;
4175 gtk_ctree_find_all_by_row_data (GtkCTree *ctree,
4181 g_return_val_if_fail (ctree != NULL, NULL);
4182 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4184 /* if node == NULL then look in the whole tree */
4186 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4190 if (GTK_CTREE_ROW (node)->row.data == data)
4191 list = g_list_append (list, node);
4193 if (GTK_CTREE_ROW (node)->children)
4197 sub_list = gtk_ctree_find_all_by_row_data (ctree,
4201 list = g_list_concat (list, sub_list);
4203 node = GTK_CTREE_ROW (node)->sibling;
4209 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4216 g_return_val_if_fail (func != NULL, NULL);
4219 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4223 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4225 if (GTK_CTREE_ROW (node)->children &&
4226 (work = gtk_ctree_find_by_row_data_custom
4227 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4229 node = GTK_CTREE_ROW (node)->sibling;
4235 gtk_ctree_find_all_by_row_data_custom (GtkCTree *ctree,
4242 g_return_val_if_fail (ctree != NULL, NULL);
4243 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4244 g_return_val_if_fail (func != NULL, NULL);
4246 /* if node == NULL then look in the whole tree */
4248 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4252 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4253 list = g_list_append (list, node);
4255 if (GTK_CTREE_ROW (node)->children)
4259 sub_list = gtk_ctree_find_all_by_row_data_custom (ctree,
4264 list = g_list_concat (list, sub_list);
4266 node = GTK_CTREE_ROW (node)->sibling;
4272 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4280 g_return_val_if_fail (ctree != NULL, FALSE);
4281 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4283 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4284 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4285 return ctree_is_hot_spot (ctree, node, row, x, y);
4291 /***********************************************************
4292 * Tree signals : move, expand, collapse, (un)select *
4293 ***********************************************************/
4297 gtk_ctree_move (GtkCTree *ctree,
4299 GtkCTreeNode *new_parent,
4300 GtkCTreeNode *new_sibling)
4302 g_return_if_fail (ctree != NULL);
4303 g_return_if_fail (GTK_IS_CTREE (ctree));
4304 g_return_if_fail (node != NULL);
4306 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4307 new_parent, new_sibling);
4311 gtk_ctree_expand (GtkCTree *ctree,
4314 g_return_if_fail (ctree != NULL);
4315 g_return_if_fail (GTK_IS_CTREE (ctree));
4316 g_return_if_fail (node != NULL);
4318 if (GTK_CTREE_ROW (node)->is_leaf)
4321 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4325 gtk_ctree_expand_recursive (GtkCTree *ctree,
4329 gboolean thaw = FALSE;
4331 g_return_if_fail (ctree != NULL);
4332 g_return_if_fail (GTK_IS_CTREE (ctree));
4334 clist = GTK_CLIST (ctree);
4336 if (node && GTK_CTREE_ROW (node)->is_leaf)
4339 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4341 gtk_clist_freeze (clist);
4345 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4348 gtk_clist_thaw (clist);
4352 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4357 gboolean thaw = FALSE;
4359 g_return_if_fail (ctree != NULL);
4360 g_return_if_fail (GTK_IS_CTREE (ctree));
4362 clist = GTK_CLIST (ctree);
4364 if (node && GTK_CTREE_ROW (node)->is_leaf)
4367 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4369 gtk_clist_freeze (clist);
4373 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4374 GTK_CTREE_FUNC (tree_expand), NULL);
4377 gtk_clist_thaw (clist);
4381 gtk_ctree_collapse (GtkCTree *ctree,
4384 g_return_if_fail (ctree != NULL);
4385 g_return_if_fail (GTK_IS_CTREE (ctree));
4386 g_return_if_fail (node != NULL);
4388 if (GTK_CTREE_ROW (node)->is_leaf)
4391 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4395 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4399 gboolean thaw = FALSE;
4402 g_return_if_fail (ctree != NULL);
4403 g_return_if_fail (GTK_IS_CTREE (ctree));
4405 if (node && GTK_CTREE_ROW (node)->is_leaf)
4408 clist = GTK_CLIST (ctree);
4410 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4412 gtk_clist_freeze (clist);
4416 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4417 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4418 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4419 for (i = 0; i < clist->columns; i++)
4420 if (clist->column[i].auto_resize)
4421 gtk_clist_set_column_width (clist, i,
4422 gtk_clist_optimal_column_width (clist, i));
4425 gtk_clist_thaw (clist);
4429 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4434 gboolean thaw = FALSE;
4437 g_return_if_fail (ctree != NULL);
4438 g_return_if_fail (GTK_IS_CTREE (ctree));
4440 if (node && GTK_CTREE_ROW (node)->is_leaf)
4443 clist = GTK_CLIST (ctree);
4445 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4447 gtk_clist_freeze (clist);
4451 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4452 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4453 GTK_CTREE_FUNC (tree_collapse_to_depth),
4454 GINT_TO_POINTER (depth));
4455 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4456 for (i = 0; i < clist->columns; i++)
4457 if (clist->column[i].auto_resize)
4458 gtk_clist_set_column_width (clist, i,
4459 gtk_clist_optimal_column_width (clist, i));
4462 gtk_clist_thaw (clist);
4466 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4469 g_return_if_fail (ctree != NULL);
4470 g_return_if_fail (GTK_IS_CTREE (ctree));
4471 g_return_if_fail (node != NULL);
4473 if (GTK_CTREE_ROW (node)->is_leaf)
4476 tree_toggle_expansion (ctree, node, NULL);
4480 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4484 gboolean thaw = FALSE;
4486 g_return_if_fail (ctree != NULL);
4487 g_return_if_fail (GTK_IS_CTREE (ctree));
4489 if (node && GTK_CTREE_ROW (node)->is_leaf)
4492 clist = GTK_CLIST (ctree);
4494 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4496 gtk_clist_freeze (clist);
4500 gtk_ctree_post_recursive (ctree, node,
4501 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4504 gtk_clist_thaw (clist);
4508 gtk_ctree_select (GtkCTree *ctree,
4511 g_return_if_fail (ctree != NULL);
4512 g_return_if_fail (GTK_IS_CTREE (ctree));
4513 g_return_if_fail (node != NULL);
4515 if (GTK_CTREE_ROW (node)->row.selectable)
4516 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4521 gtk_ctree_unselect (GtkCTree *ctree,
4524 g_return_if_fail (ctree != NULL);
4525 g_return_if_fail (GTK_IS_CTREE (ctree));
4526 g_return_if_fail (node != NULL);
4528 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4533 gtk_ctree_select_recursive (GtkCTree *ctree,
4536 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4540 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4543 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4547 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4552 gboolean thaw = FALSE;
4554 g_return_if_fail (ctree != NULL);
4555 g_return_if_fail (GTK_IS_CTREE (ctree));
4557 clist = GTK_CLIST (ctree);
4560 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4561 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4562 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4565 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4567 gtk_clist_freeze (clist);
4571 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4573 if (clist->anchor != -1)
4574 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4576 g_list_free (clist->undo_selection);
4577 g_list_free (clist->undo_unselection);
4578 clist->undo_selection = NULL;
4579 clist->undo_unselection = NULL;
4583 gtk_ctree_post_recursive (ctree, node,
4584 GTK_CTREE_FUNC (tree_select), NULL);
4586 gtk_ctree_post_recursive (ctree, node,
4587 GTK_CTREE_FUNC (tree_unselect), NULL);
4590 gtk_clist_thaw (clist);
4594 /***********************************************************
4595 * Analogons of GtkCList functions *
4596 ***********************************************************/
4600 gtk_ctree_node_set_text (GtkCTree *ctree,
4607 g_return_if_fail (ctree != NULL);
4608 g_return_if_fail (GTK_IS_CTREE (ctree));
4609 g_return_if_fail (node != NULL);
4611 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4614 clist = GTK_CLIST (ctree);
4616 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4617 (clist, &(GTK_CTREE_ROW(node)->row), column, GTK_CELL_TEXT,
4618 text, 0, NULL, NULL);
4620 tree_draw_node (ctree, node);
4624 gtk_ctree_node_set_pixmap (GtkCTree *ctree,
4632 g_return_if_fail (ctree != NULL);
4633 g_return_if_fail (GTK_IS_CTREE (ctree));
4634 g_return_if_fail (node != NULL);
4635 g_return_if_fail (pixmap != NULL);
4637 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4640 gdk_pixmap_ref (pixmap);
4642 gdk_pixmap_ref (mask);
4644 clist = GTK_CLIST (ctree);
4646 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4647 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP,
4648 NULL, 0, pixmap, mask);
4650 tree_draw_node (ctree, node);
4654 gtk_ctree_node_set_pixtext (GtkCTree *ctree,
4664 g_return_if_fail (ctree != NULL);
4665 g_return_if_fail (GTK_IS_CTREE (ctree));
4666 g_return_if_fail (node != NULL);
4667 if (column != ctree->tree_column)
4668 g_return_if_fail (pixmap != NULL);
4669 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4672 clist = GTK_CLIST (ctree);
4676 gdk_pixmap_ref (pixmap);
4678 gdk_pixmap_ref (mask);
4681 GTK_CLIST_CLASS_FW (clist)->set_cell_contents
4682 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT,
4683 text, spacing, pixmap, mask);
4685 tree_draw_node (ctree, node);
4689 gtk_ctree_set_node_info (GtkCTree *ctree,
4693 GdkPixmap *pixmap_closed,
4694 GdkBitmap *mask_closed,
4695 GdkPixmap *pixmap_opened,
4696 GdkBitmap *mask_opened,
4701 gboolean old_expanded;
4703 g_return_if_fail (ctree != NULL);
4704 g_return_if_fail (GTK_IS_CTREE (ctree));
4705 g_return_if_fail (node != NULL);
4707 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
4708 old_expanded = GTK_CTREE_ROW (node)->expanded;
4710 if (is_leaf && GTK_CTREE_ROW (node)->children)
4715 work = GTK_CTREE_ROW (node)->children;
4719 work = GTK_CTREE_ROW(work)->sibling;
4720 gtk_ctree_remove_node (ctree, ptr);
4724 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
4725 pixmap_opened, mask_opened, is_leaf, expanded);
4727 if (!is_leaf && !old_leaf)
4729 GTK_CTREE_ROW (node)->expanded = old_expanded;
4730 if (expanded && !old_expanded)
4731 gtk_ctree_expand (ctree, node);
4732 else if (!expanded && old_expanded)
4733 gtk_ctree_collapse (ctree, node);
4736 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
4738 tree_draw_node (ctree, node);
4742 gtk_ctree_node_set_shift (GtkCTree *ctree,
4749 GtkRequisition requisition;
4750 gboolean visible = FALSE;
4752 g_return_if_fail (ctree != NULL);
4753 g_return_if_fail (GTK_IS_CTREE (ctree));
4754 g_return_if_fail (node != NULL);
4756 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4759 clist = GTK_CLIST (ctree);
4761 if (clist->column[column].auto_resize &&
4762 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
4764 visible = gtk_ctree_is_viewable (ctree, node);
4766 GTK_CLIST_CLASS_FW (clist)->cell_size_request
4767 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
4770 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
4771 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
4774 column_auto_resize (clist, >K_CTREE_ROW (node)->row,
4775 column, requisition.width);
4777 tree_draw_node (ctree, node);
4781 remove_grab (GtkCList *clist)
4783 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4785 gtk_grab_remove (GTK_WIDGET (clist));
4786 gdk_pointer_ungrab (GDK_CURRENT_TIME);
4791 gtk_timeout_remove (clist->htimer);
4797 gtk_timeout_remove (clist->vtimer);
4803 gtk_ctree_node_set_selectable (GtkCTree *ctree,
4805 gboolean selectable)
4807 g_return_if_fail (ctree != NULL);
4808 g_return_if_fail (GTK_IS_CTREE (ctree));
4809 g_return_if_fail (node != NULL);
4811 if (selectable == GTK_CTREE_ROW (node)->row.selectable)
4814 GTK_CTREE_ROW (node)->row.selectable = selectable;
4816 if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
4820 clist = GTK_CLIST (ctree);
4822 if (clist->anchor >= 0 &&
4823 clist->selection_mode == GTK_SELECTION_EXTENDED)
4825 clist->drag_button = 0;
4826 remove_grab (clist);
4828 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
4830 gtk_ctree_unselect (ctree, node);
4835 gtk_ctree_node_get_selectable (GtkCTree *ctree,
4838 g_return_val_if_fail (node != NULL, FALSE);
4840 return GTK_CTREE_ROW (node)->row.selectable;
4844 gtk_ctree_node_get_cell_type (GtkCTree *ctree,
4848 g_return_val_if_fail (ctree != NULL, -1);
4849 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
4850 g_return_val_if_fail (node != NULL, -1);
4852 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4855 return GTK_CTREE_ROW (node)->row.cell[column].type;
4859 gtk_ctree_node_get_text (GtkCTree *ctree,
4864 g_return_val_if_fail (ctree != NULL, 0);
4865 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4866 g_return_val_if_fail (node != NULL, 0);
4868 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4871 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
4875 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4881 gtk_ctree_node_get_pixmap (GtkCTree *ctree,
4887 g_return_val_if_fail (ctree != NULL, 0);
4888 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4889 g_return_val_if_fail (node != NULL, 0);
4891 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4894 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
4898 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
4900 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4906 gtk_ctree_node_get_pixtext (GtkCTree *ctree,
4914 g_return_val_if_fail (ctree != NULL, 0);
4915 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4916 g_return_val_if_fail (node != NULL, 0);
4918 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4921 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
4925 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4927 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4928 (node)->row.cell[column])->spacing;
4930 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4931 (node)->row.cell[column])->pixmap;
4933 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4939 gtk_ctree_get_node_info (GtkCTree *ctree,
4943 GdkPixmap **pixmap_closed,
4944 GdkBitmap **mask_closed,
4945 GdkPixmap **pixmap_opened,
4946 GdkBitmap **mask_opened,
4950 g_return_val_if_fail (ctree != NULL, 0);
4951 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4952 g_return_val_if_fail (node != NULL, 0);
4955 *text = GTK_CELL_PIXTEXT
4956 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
4958 *spacing = GTK_CELL_PIXTEXT
4959 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
4961 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
4963 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
4965 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
4967 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
4969 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
4971 *expanded = GTK_CTREE_ROW (node)->expanded;
4977 gtk_ctree_node_set_cell_style (GtkCTree *ctree,
4983 GtkRequisition requisition;
4984 gboolean visible = FALSE;
4986 g_return_if_fail (ctree != NULL);
4987 g_return_if_fail (GTK_IS_CTREE (ctree));
4988 g_return_if_fail (node != NULL);
4990 clist = GTK_CLIST (ctree);
4992 if (column < 0 || column >= clist->columns)
4995 if (GTK_CTREE_ROW (node)->row.cell[column].style == style)
4998 if (clist->column[column].auto_resize &&
4999 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5001 visible = gtk_ctree_is_viewable (ctree, node);
5003 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5004 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5007 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5009 if (GTK_WIDGET_REALIZED (ctree))
5010 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[column].style);
5011 gtk_style_unref (GTK_CTREE_ROW (node)->row.cell[column].style);
5014 GTK_CTREE_ROW (node)->row.cell[column].style = style;
5016 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5018 gtk_style_ref (GTK_CTREE_ROW (node)->row.cell[column].style);
5020 if (GTK_WIDGET_REALIZED (ctree))
5021 GTK_CTREE_ROW (node)->row.cell[column].style =
5022 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[column].style,
5023 clist->clist_window);
5027 column_auto_resize (clist, >K_CTREE_ROW (node)->row, column,
5030 tree_draw_node (ctree, node);
5034 gtk_ctree_node_get_cell_style (GtkCTree *ctree,
5038 g_return_val_if_fail (ctree != NULL, NULL);
5039 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5040 g_return_val_if_fail (node != NULL, NULL);
5042 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5045 return GTK_CTREE_ROW (node)->row.cell[column].style;
5049 gtk_ctree_node_set_row_style (GtkCTree *ctree,
5054 GtkRequisition requisition;
5056 gint *old_width = NULL;
5059 g_return_if_fail (ctree != NULL);
5060 g_return_if_fail (GTK_IS_CTREE (ctree));
5061 g_return_if_fail (node != NULL);
5063 clist = GTK_CLIST (ctree);
5065 if (GTK_CTREE_ROW (node)->row.style == style)
5068 visible = gtk_ctree_is_viewable (ctree, node);
5069 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5071 old_width = g_new (gint, clist->columns);
5072 for (i = 0; i < clist->columns; i++)
5073 if (clist->column[i].auto_resize)
5075 GTK_CLIST_CLASS_FW (clist)->cell_size_request
5076 (clist, >K_CTREE_ROW (node)->row, i, &requisition);
5077 old_width[i] = requisition.width;
5081 if (GTK_CTREE_ROW (node)->row.style)
5083 if (GTK_WIDGET_REALIZED (ctree))
5084 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
5085 gtk_style_unref (GTK_CTREE_ROW (node)->row.style);
5088 GTK_CTREE_ROW (node)->row.style = style;
5090 if (GTK_CTREE_ROW (node)->row.style)
5092 gtk_style_ref (GTK_CTREE_ROW (node)->row.style);
5094 if (GTK_WIDGET_REALIZED (ctree))
5095 GTK_CTREE_ROW (node)->row.style =
5096 gtk_style_attach (GTK_CTREE_ROW (node)->row.style,
5097 clist->clist_window);
5100 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5102 for (i = 0; i < clist->columns; i++)
5103 if (clist->column[i].auto_resize)
5104 column_auto_resize (clist, >K_CTREE_ROW (node)->row, i,
5108 tree_draw_node (ctree, node);
5112 gtk_ctree_node_get_row_style (GtkCTree *ctree,
5115 g_return_val_if_fail (ctree != NULL, NULL);
5116 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5117 g_return_val_if_fail (node != NULL, NULL);
5119 return GTK_CTREE_ROW (node)->row.style;
5123 gtk_ctree_node_set_foreground (GtkCTree *ctree,
5127 g_return_if_fail (ctree != NULL);
5128 g_return_if_fail (GTK_IS_CTREE (ctree));
5129 g_return_if_fail (node != NULL);
5133 GTK_CTREE_ROW (node)->row.foreground = *color;
5134 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
5135 if (GTK_WIDGET_REALIZED (ctree))
5136 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5137 >K_CTREE_ROW (node)->row.foreground);
5140 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
5142 tree_draw_node (ctree, node);
5146 gtk_ctree_node_set_background (GtkCTree *ctree,
5150 g_return_if_fail (ctree != NULL);
5151 g_return_if_fail (GTK_IS_CTREE (ctree));
5152 g_return_if_fail (node != NULL);
5156 GTK_CTREE_ROW (node)->row.background = *color;
5157 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
5158 if (GTK_WIDGET_REALIZED (ctree))
5159 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5160 >K_CTREE_ROW (node)->row.background);
5163 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
5165 tree_draw_node (ctree, node);
5169 gtk_ctree_node_set_row_data (GtkCTree *ctree,
5173 gtk_ctree_node_set_row_data_full (ctree, node, data, NULL);
5177 gtk_ctree_node_set_row_data_full (GtkCTree *ctree,
5180 GtkDestroyNotify destroy)
5182 g_return_if_fail (ctree != NULL);
5183 g_return_if_fail (GTK_IS_CTREE (ctree));
5184 g_return_if_fail (node != NULL);
5186 GTK_CTREE_ROW (node)->row.data = data;
5187 GTK_CTREE_ROW (node)->row.destroy = destroy;
5191 gtk_ctree_node_get_row_data (GtkCTree *ctree,
5194 g_return_val_if_fail (ctree != NULL, NULL);
5195 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5197 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
5201 gtk_ctree_node_moveto (GtkCTree *ctree,
5210 g_return_if_fail (ctree != NULL);
5211 g_return_if_fail (GTK_IS_CTREE (ctree));
5213 clist = GTK_CLIST (ctree);
5215 while (node && !gtk_ctree_is_viewable (ctree, node))
5216 node = GTK_CTREE_ROW (node)->parent;
5219 row = g_list_position (clist->row_list, (GList *)node);
5221 gtk_clist_moveto (clist, row, column, row_align, col_align);
5224 GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree,
5229 g_return_val_if_fail (ctree != NULL, 0);
5230 g_return_val_if_fail (node != NULL, 0);
5232 row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node);
5233 return gtk_clist_row_is_visible (GTK_CLIST (ctree), row);
5237 /***********************************************************
5238 * GtkCTree specific functions *
5239 ***********************************************************/
5242 gtk_ctree_set_indent (GtkCTree *ctree,
5247 g_return_if_fail (ctree != NULL);
5248 g_return_if_fail (GTK_IS_CTREE (ctree));
5249 g_return_if_fail (indent >= 0);
5251 if (indent == ctree->tree_indent)
5254 clist = GTK_CLIST (ctree);
5255 ctree->tree_indent = indent;
5257 if (clist->column[ctree->tree_column].auto_resize &&
5258 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5259 gtk_clist_set_column_width
5260 (clist, ctree->tree_column,
5261 gtk_clist_optimal_column_width (clist, ctree->tree_column));
5263 CLIST_REFRESH (ctree);
5267 gtk_ctree_set_spacing (GtkCTree *ctree,
5273 g_return_if_fail (ctree != NULL);
5274 g_return_if_fail (GTK_IS_CTREE (ctree));
5275 g_return_if_fail (spacing >= 0);
5277 if (spacing == ctree->tree_spacing)
5280 clist = GTK_CLIST (ctree);
5282 old_spacing = ctree->tree_spacing;
5283 ctree->tree_spacing = spacing;
5285 if (clist->column[ctree->tree_column].auto_resize &&
5286 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5287 gtk_clist_set_column_width (clist, ctree->tree_column,
5288 clist->column[ctree->tree_column].width +
5289 spacing - old_spacing);
5291 CLIST_REFRESH (ctree);
5295 gtk_ctree_set_show_stub (GtkCTree *ctree,
5298 g_return_if_fail (ctree != NULL);
5299 g_return_if_fail (GTK_IS_CTREE (ctree));
5301 show_stub = show_stub != FALSE;
5303 if (show_stub != ctree->show_stub)
5307 clist = GTK_CLIST (ctree);
5308 ctree->show_stub = show_stub;
5310 if (CLIST_UNFROZEN (clist) && clist->rows &&
5311 gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
5312 GTK_CLIST_CLASS_FW (clist)->draw_row
5313 (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list));
5318 gtk_ctree_set_line_style (GtkCTree *ctree,
5319 GtkCTreeLineStyle line_style)
5322 GtkCTreeLineStyle old_style;
5324 g_return_if_fail (ctree != NULL);
5325 g_return_if_fail (GTK_IS_CTREE (ctree));
5327 if (line_style == ctree->line_style)
5330 clist = GTK_CLIST (ctree);
5332 old_style = ctree->line_style;
5333 ctree->line_style = line_style;
5335 if (clist->column[ctree->tree_column].auto_resize &&
5336 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5338 if (old_style == GTK_CTREE_LINES_TABBED)
5339 gtk_clist_set_column_width
5340 (clist, ctree->tree_column,
5341 clist->column[ctree->tree_column].width - 3);
5342 else if (line_style == GTK_CTREE_LINES_TABBED)
5343 gtk_clist_set_column_width
5344 (clist, ctree->tree_column,
5345 clist->column[ctree->tree_column].width + 3);
5348 if (GTK_WIDGET_REALIZED (ctree))
5352 case GTK_CTREE_LINES_SOLID:
5353 if (GTK_WIDGET_REALIZED (ctree))
5354 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5357 case GTK_CTREE_LINES_DOTTED:
5358 if (GTK_WIDGET_REALIZED (ctree))
5359 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
5360 GDK_LINE_ON_OFF_DASH, None, None);
5361 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
5363 case GTK_CTREE_LINES_TABBED:
5364 if (GTK_WIDGET_REALIZED (ctree))
5365 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5368 case GTK_CTREE_LINES_NONE:
5373 CLIST_REFRESH (ctree);
5378 gtk_ctree_set_expander_style (GtkCTree *ctree,
5379 GtkCTreeExpanderStyle expander_style)
5382 GtkCTreeExpanderStyle old_style;
5384 g_return_if_fail (ctree != NULL);
5385 g_return_if_fail (GTK_IS_CTREE (ctree));
5387 if (expander_style == ctree->expander_style)
5390 clist = GTK_CLIST (ctree);
5392 old_style = ctree->expander_style;
5393 ctree->expander_style = expander_style;
5395 if (clist->column[ctree->tree_column].auto_resize &&
5396 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5400 new_width = clist->column[ctree->tree_column].width;
5403 case GTK_CTREE_EXPANDER_NONE:
5405 case GTK_CTREE_EXPANDER_TRIANGLE:
5406 new_width -= PM_SIZE + 3;
5408 case GTK_CTREE_EXPANDER_SQUARE:
5409 case GTK_CTREE_EXPANDER_CIRCULAR:
5410 new_width -= PM_SIZE + 1;
5414 switch (expander_style)
5416 case GTK_CTREE_EXPANDER_NONE:
5418 case GTK_CTREE_EXPANDER_TRIANGLE:
5419 new_width += PM_SIZE + 3;
5421 case GTK_CTREE_EXPANDER_SQUARE:
5422 case GTK_CTREE_EXPANDER_CIRCULAR:
5423 new_width += PM_SIZE + 1;
5427 gtk_clist_set_column_width (clist, ctree->tree_column, new_width);
5430 if (GTK_WIDGET_DRAWABLE (clist))
5431 CLIST_REFRESH (clist);
5435 /***********************************************************
5436 * Tree sorting functions *
5437 ***********************************************************/
5441 tree_sort (GtkCTree *ctree,
5445 GtkCTreeNode *list_start;
5450 clist = GTK_CLIST (ctree);
5453 list_start = GTK_CTREE_ROW (node)->children;
5455 list_start = GTK_CTREE_NODE (clist->row_list);
5460 work = GTK_CTREE_ROW (cmp)->sibling;
5463 if (clist->sort_type == GTK_SORT_ASCENDING)
5466 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0)
5472 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0)
5475 work = GTK_CTREE_ROW (work)->sibling;
5477 if (cmp == list_start)
5478 list_start = GTK_CTREE_ROW (cmp)->sibling;
5481 gtk_ctree_unlink (ctree, cmp, FALSE);
5482 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5488 gtk_ctree_sort_recursive (GtkCTree *ctree,
5492 GtkCTreeNode *focus_node = NULL;
5494 g_return_if_fail (ctree != NULL);
5495 g_return_if_fail (GTK_IS_CTREE (ctree));
5497 clist = GTK_CLIST (ctree);
5499 gtk_clist_freeze (clist);
5501 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5503 if (clist->anchor != -1)
5504 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5506 g_list_free (clist->undo_selection);
5507 g_list_free (clist->undo_unselection);
5508 clist->undo_selection = NULL;
5509 clist->undo_unselection = NULL;
5512 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5514 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5516 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5519 tree_sort (ctree, NULL, NULL);
5523 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5524 clist->undo_anchor = clist->focus_row;
5527 gtk_clist_thaw (clist);
5531 real_sort_list (GtkCList *clist)
5533 gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL);
5537 gtk_ctree_sort_node (GtkCTree *ctree,
5541 GtkCTreeNode *focus_node = NULL;
5543 g_return_if_fail (ctree != NULL);
5544 g_return_if_fail (GTK_IS_CTREE (ctree));
5546 clist = GTK_CLIST (ctree);
5548 gtk_clist_freeze (clist);
5550 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5552 if (clist->anchor != -1)
5553 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
5555 g_list_free (clist->undo_selection);
5556 g_list_free (clist->undo_unselection);
5557 clist->undo_selection = NULL;
5558 clist->undo_unselection = NULL;
5561 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5562 focus_node = GTK_CTREE_NODE
5563 (g_list_nth (clist->row_list, clist->focus_row));
5565 tree_sort (ctree, node, NULL);
5569 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5570 clist->undo_anchor = clist->focus_row;
5573 gtk_clist_thaw (clist);
5576 /************************************************************************/
5579 fake_unselect_all (GtkCList *clist,
5583 GList *focus_node = NULL;
5585 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5587 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
5588 GTK_CTREE_ROW (focus_node)->row.selectable)
5590 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5592 if (CLIST_UNFROZEN (clist) &&
5593 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5594 GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
5595 GTK_CLIST_ROW (focus_node));
5599 clist->undo_selection = clist->selection;
5600 clist->selection = NULL;
5601 clist->selection_end = NULL;
5603 for (list = clist->undo_selection; list; list = list->next)
5605 if (list->data == focus_node)
5608 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
5609 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
5614 selection_find (GtkCList *clist,
5616 GList *row_list_element)
5618 return g_list_find (clist->selection, row_list_element);
5622 resync_selection (GtkCList *clist, GdkEvent *event)
5632 g_return_if_fail (clist != NULL);
5633 g_return_if_fail (GTK_IS_CTREE (clist));
5635 if (clist->anchor < 0)
5638 ctree = GTK_CTREE (clist);
5640 clist->freeze_count++;
5642 i = MIN (clist->anchor, clist->drag_pos);
5643 e = MAX (clist->anchor, clist->drag_pos);
5645 if (clist->undo_selection)
5647 list = clist->selection;
5648 clist->selection = clist->undo_selection;
5649 clist->selection_end = g_list_last (clist->selection);
5650 clist->undo_selection = list;
5651 list = clist->selection;
5660 if (gtk_ctree_is_viewable (ctree, node))
5662 row = g_list_position (clist->row_list, (GList *)node);
5663 if (row >= i && row <= e)
5666 if (unselect && GTK_CTREE_ROW (node)->row.selectable)
5668 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5669 gtk_ctree_unselect (ctree, node);
5670 clist->undo_selection = g_list_prepend (clist->undo_selection,
5676 if (clist->anchor < clist->drag_pos)
5678 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
5679 i++, node = GTK_CTREE_NODE_NEXT (node))
5680 if (GTK_CTREE_ROW (node)->row.selectable)
5682 if (g_list_find (clist->selection, node))
5684 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5686 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5687 gtk_ctree_unselect (ctree, node);
5688 clist->undo_selection =
5689 g_list_prepend (clist->undo_selection, node);
5692 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5694 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5695 clist->undo_unselection =
5696 g_list_prepend (clist->undo_unselection, node);
5702 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, e)); i <= e;
5703 e--, node = GTK_CTREE_NODE_PREV (node))
5704 if (GTK_CTREE_ROW (node)->row.selectable)
5706 if (g_list_find (clist->selection, node))
5708 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5710 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5711 gtk_ctree_unselect (ctree, node);
5712 clist->undo_selection =
5713 g_list_prepend (clist->undo_selection, node);
5716 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5718 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5719 clist->undo_unselection =
5720 g_list_prepend (clist->undo_unselection, node);
5725 for (list = g_list_reverse (clist->undo_unselection); list;
5727 gtk_ctree_select (ctree, list->data);
5730 clist->drag_pos = -1;
5732 if (!CLIST_UNFROZEN (clist))
5733 clist->freeze_count--;
5737 real_undo_selection (GtkCList *clist)
5742 g_return_if_fail (clist != NULL);
5743 g_return_if_fail (GTK_IS_CTREE (clist));
5745 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
5748 if (!(clist->undo_selection || clist->undo_unselection))
5750 gtk_clist_unselect_all (clist);
5754 ctree = GTK_CTREE (clist);
5756 for (work = clist->undo_selection; work; work = work->next)
5757 if (GTK_CTREE_ROW (work->data)->row.selectable)
5758 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
5760 for (work = clist->undo_unselection; work; work = work->next)
5761 if (GTK_CTREE_ROW (work->data)->row.selectable)
5762 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
5764 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
5766 gtk_widget_draw_focus (GTK_WIDGET (clist));
5767 clist->focus_row = clist->undo_anchor;
5768 gtk_widget_draw_focus (GTK_WIDGET (clist));
5771 clist->focus_row = clist->undo_anchor;
5773 clist->undo_anchor = -1;
5775 g_list_free (clist->undo_selection);
5776 g_list_free (clist->undo_unselection);
5777 clist->undo_selection = NULL;
5778 clist->undo_unselection = NULL;
5780 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5781 clist->clist_window_height)
5782 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5783 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5784 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5789 gtk_ctree_set_drag_compare_func (GtkCTree *ctree,
5790 GtkCTreeCompareDragFunc cmp_func)
5792 g_return_if_fail (ctree != NULL);
5793 g_return_if_fail (GTK_IS_CTREE (ctree));
5795 ctree->drag_compare = cmp_func;
5799 check_drag (GtkCTree *ctree,
5800 GtkCTreeNode *drag_source,
5801 GtkCTreeNode *drag_target,
5802 GtkCListDragPos insert_pos)
5804 g_return_val_if_fail (ctree != NULL, FALSE);
5805 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
5807 if (drag_source && drag_source != drag_target &&
5808 (!GTK_CTREE_ROW (drag_source)->children ||
5809 !gtk_ctree_is_ancestor (ctree, drag_source, drag_target)))
5813 case GTK_CLIST_DRAG_NONE:
5815 case GTK_CLIST_DRAG_AFTER:
5816 if (GTK_CTREE_ROW (drag_target)->sibling != drag_source)
5817 return (!ctree->drag_compare ||
5818 ctree->drag_compare (ctree,
5820 GTK_CTREE_ROW (drag_target)->parent,
5821 GTK_CTREE_ROW(drag_target)->sibling));
5823 case GTK_CLIST_DRAG_BEFORE:
5824 if (GTK_CTREE_ROW (drag_source)->sibling != drag_target)
5825 return (!ctree->drag_compare ||
5826 ctree->drag_compare (ctree,
5828 GTK_CTREE_ROW (drag_target)->parent,
5831 case GTK_CLIST_DRAG_INTO:
5832 if (!GTK_CTREE_ROW (drag_target)->is_leaf &&
5833 GTK_CTREE_ROW (drag_target)->children != drag_source)
5834 return (!ctree->drag_compare ||
5835 ctree->drag_compare (ctree,
5838 GTK_CTREE_ROW (drag_target)->children));
5847 /************************************/
5849 drag_dest_info_destroy (gpointer data)
5851 GtkCListDestInfo *info = data;
5857 gtk_ctree_drag_begin (GtkWidget *widget,
5858 GdkDragContext *context)
5864 g_return_if_fail (widget != NULL);
5865 g_return_if_fail (GTK_IS_CTREE (widget));
5866 g_return_if_fail (context != NULL);
5868 clist = GTK_CLIST (widget);
5869 ctree = GTK_CTREE (widget);
5871 use_icons = GTK_CLIST_USE_DRAG_ICONS (clist);
5872 GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
5873 GTK_WIDGET_CLASS (parent_class)->drag_begin (widget, context);
5879 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
5880 node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
5881 clist->click_cell.row));
5884 if (GTK_CELL_PIXTEXT
5885 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
5887 gtk_drag_set_icon_pixmap
5889 gtk_widget_get_colormap (widget),
5891 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap,
5893 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask,
5898 gtk_drag_set_icon_default (context);
5903 gtk_ctree_drag_motion (GtkWidget *widget,
5904 GdkDragContext *context,
5912 GtkCListDestInfo *dest_info;
5914 gint insert_pos = GTK_CLIST_DRAG_NONE;
5917 g_return_val_if_fail (widget != NULL, FALSE);
5918 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
5920 clist = GTK_CLIST (widget);
5921 ctree = GTK_CTREE (widget);
5923 y -= (GTK_CONTAINER (widget)->border_width +
5924 widget->style->klass->ythickness + clist->column_title_area.height);
5925 row = ROW_FROM_YPIXEL (clist, y);
5927 if (row >= clist->rows)
5929 row = clist->rows - 1;
5930 y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
5935 x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
5936 column = COLUMN_FROM_XPIXEL (clist, x);
5940 y_delta = y - ROW_TOP_YPIXEL (clist, row);
5942 if (GTK_CLIST_DRAW_DRAG_RECT(clist))
5944 insert_pos = GTK_CLIST_DRAG_INTO;
5945 h = clist->row_height / 4;
5947 else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
5949 insert_pos = GTK_CLIST_DRAG_BEFORE;
5950 h = clist->row_height / 2;
5953 if (GTK_CLIST_DRAW_DRAG_LINE(clist))
5956 insert_pos = GTK_CLIST_DRAG_BEFORE;
5957 else if (clist->row_height - y_delta < h)
5958 insert_pos = GTK_CLIST_DRAG_AFTER;
5962 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
5966 dest_info = g_new (GtkCListDestInfo, 1);
5968 dest_info->cell.row = -1;
5969 dest_info->cell.column = -1;
5970 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
5972 g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
5973 drag_dest_info_destroy);
5976 if (GTK_CLIST_REORDERABLE (clist))
5979 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
5981 list = context->targets;
5984 if (atom == GPOINTER_TO_INT (list->data))
5991 GtkCTreeNode *drag_source;
5992 GtkCTreeNode *drag_target;
5994 drag_source = GTK_CTREE_NODE (g_list_nth (clist->row_list,
5995 clist->click_cell.row));
5996 drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
5998 if (gtk_drag_get_source_widget (context) != widget ||
5999 !check_drag (ctree, drag_source, drag_target, insert_pos))
6001 if (dest_info->cell.row < 0)
6003 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
6009 if (row != dest_info->cell.row ||
6010 (row == dest_info->cell.row &&
6011 dest_info->insert_pos != insert_pos))
6013 if (dest_info->cell.row >= 0)
6014 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
6016 g_list_nth (clist->row_list, dest_info->cell.row)->data,
6017 dest_info->cell.row, dest_info->insert_pos);
6019 dest_info->insert_pos = insert_pos;
6020 dest_info->cell.row = row;
6021 dest_info->cell.column = column;
6023 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
6025 g_list_nth (clist->row_list, dest_info->cell.row)->data,
6026 dest_info->cell.row, dest_info->insert_pos);
6028 gdk_drag_status (context, context->suggested_action, time);
6034 dest_info->insert_pos = insert_pos;
6035 dest_info->cell.row = row;
6036 dest_info->cell.column = column;
6041 gtk_ctree_drag_data_received (GtkWidget *widget,
6042 GdkDragContext *context,
6045 GtkSelectionData *selection_data,
6052 g_return_if_fail (widget != NULL);
6053 g_return_if_fail (GTK_IS_CTREE (widget));
6054 g_return_if_fail (context != NULL);
6055 g_return_if_fail (selection_data != NULL);
6057 ctree = GTK_CTREE (widget);
6058 clist = GTK_CLIST (widget);
6060 if (GTK_CLIST_REORDERABLE (clist) &&
6061 gtk_drag_get_source_widget (context) == widget &&
6062 selection_data->target ==
6063 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
6064 selection_data->format == GTK_TYPE_POINTER &&
6065 selection_data->length == sizeof (GtkCListCellInfo))
6067 GtkCListCellInfo *source_info;
6068 GtkCListDestInfo *dest_info;
6070 source_info = (GtkCListCellInfo *)(selection_data->data);
6071 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
6073 if (dest_info && source_info)
6075 GtkCTreeNode *source_node;
6076 GtkCTreeNode *dest_node;
6078 source_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6080 dest_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6081 dest_info->cell.row));
6083 if (!source_info || !dest_info)
6086 switch (dest_info->insert_pos)
6088 case GTK_CLIST_DRAG_NONE:
6090 case GTK_CLIST_DRAG_INTO:
6091 if (check_drag (ctree, source_node, dest_node,
6092 dest_info->insert_pos))
6093 gtk_ctree_move (ctree, source_node, dest_node,
6094 GTK_CTREE_ROW (dest_node)->children);
6095 g_dataset_remove_data (context, "gtk-clist-drag-dest");
6097 case GTK_CLIST_DRAG_BEFORE:
6098 if (check_drag (ctree, source_node, dest_node,
6099 dest_info->insert_pos))
6100 gtk_ctree_move (ctree, source_node,
6101 GTK_CTREE_ROW (dest_node)->parent, dest_node);
6102 g_dataset_remove_data (context, "gtk-clist-drag-dest");
6104 case GTK_CLIST_DRAG_AFTER:
6105 if (check_drag (ctree, source_node, dest_node,
6106 dest_info->insert_pos))
6107 gtk_ctree_move (ctree, source_node,
6108 GTK_CTREE_ROW (dest_node)->parent,
6109 GTK_CTREE_ROW (dest_node)->sibling);
6110 g_dataset_remove_data (context, "gtk-clist-drag-dest");