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 Lesser 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 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser 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.
25 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
26 * file for a list of people on the GTK+ Team. See the ChangeLog
27 * files for a list of changes. These files are distributed with
28 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gtkbindings.h"
36 #include <gdk/gdkkeysyms.h>
39 #define TAB_SIZE (PM_SIZE + 6)
40 #define CELL_SPACING 1
41 #define CLIST_OPTIMUM_SIZE 64
42 #define COLUMN_INSET 3
45 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
46 (((row) + 1) * CELL_SPACING) + \
48 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
49 ((clist)->row_height + CELL_SPACING))
50 #define COLUMN_LEFT_XPIXEL(clist, col) ((clist)->column[(col)].area.x \
52 #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
55 COLUMN_FROM_XPIXEL (GtkCList * clist,
60 for (i = 0; i < clist->columns; i++)
61 if (clist->column[i].visible)
63 cx = clist->column[i].area.x + clist->hoffset;
65 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
66 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
74 #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0)
75 #define CLIST_REFRESH(clist) G_STMT_START { \
76 if (CLIST_UNFROZEN (clist)) \
77 GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
93 static void gtk_ctree_class_init (GtkCTreeClass *klass);
94 static void gtk_ctree_init (GtkCTree *ctree);
95 static GObject* gtk_ctree_constructor (GType type,
96 guint n_construct_properties,
97 GObjectConstructParam *construct_params);
98 static void gtk_ctree_set_arg (GtkObject *object,
101 static void gtk_ctree_get_arg (GtkObject *object,
104 static void gtk_ctree_realize (GtkWidget *widget);
105 static void gtk_ctree_unrealize (GtkWidget *widget);
106 static gint gtk_ctree_button_press (GtkWidget *widget,
107 GdkEventButton *event);
108 static void ctree_attach_styles (GtkCTree *ctree,
111 static void ctree_detach_styles (GtkCTree *ctree,
114 static gint draw_cell_pixmap (GdkWindow *window,
115 GdkRectangle *clip_rectangle,
123 static void get_cell_style (GtkCList *clist,
124 GtkCListRow *clist_row,
130 static gint gtk_ctree_draw_expander (GtkCTree *ctree,
131 GtkCTreeRow *ctree_row,
133 GdkRectangle *clip_rectangle,
135 static gint gtk_ctree_draw_lines (GtkCTree *ctree,
136 GtkCTreeRow *ctree_row,
140 GdkRectangle *clip_rectangle,
141 GdkRectangle *cell_rectangle,
145 static void draw_row (GtkCList *clist,
148 GtkCListRow *clist_row);
149 static void draw_drag_highlight (GtkCList *clist,
150 GtkCListRow *dest_row,
151 gint dest_row_number,
152 GtkCListDragPos drag_pos);
153 static void tree_draw_node (GtkCTree *ctree,
155 static void set_cell_contents (GtkCList *clist,
156 GtkCListRow *clist_row,
163 static void set_node_info (GtkCTree *ctree,
167 GdkPixmap *pixmap_closed,
168 GdkBitmap *mask_closed,
169 GdkPixmap *pixmap_opened,
170 GdkBitmap *mask_opened,
173 static GtkCTreeRow *row_new (GtkCTree *ctree);
174 static void row_delete (GtkCTree *ctree,
175 GtkCTreeRow *ctree_row);
176 static void tree_delete (GtkCTree *ctree,
179 static void tree_delete_row (GtkCTree *ctree,
182 static void real_clear (GtkCList *clist);
183 static void tree_update_level (GtkCTree *ctree,
186 static void tree_select (GtkCTree *ctree,
189 static void tree_unselect (GtkCTree *ctree,
192 static void real_select_all (GtkCList *clist);
193 static void real_unselect_all (GtkCList *clist);
194 static void tree_expand (GtkCTree *ctree,
197 static void tree_collapse (GtkCTree *ctree,
200 static void tree_collapse_to_depth (GtkCTree *ctree,
203 static void tree_toggle_expansion (GtkCTree *ctree,
206 static void change_focus_row_expansion (GtkCTree *ctree,
207 GtkCTreeExpansionType expansion);
208 static void real_select_row (GtkCList *clist,
212 static void real_unselect_row (GtkCList *clist,
216 static void real_tree_select (GtkCTree *ctree,
219 static void real_tree_unselect (GtkCTree *ctree,
222 static void real_tree_expand (GtkCTree *ctree,
224 static void real_tree_collapse (GtkCTree *ctree,
226 static void real_tree_move (GtkCTree *ctree,
228 GtkCTreeNode *new_parent,
229 GtkCTreeNode *new_sibling);
230 static void real_row_move (GtkCList *clist,
233 static void gtk_ctree_link (GtkCTree *ctree,
235 GtkCTreeNode *parent,
236 GtkCTreeNode *sibling,
237 gboolean update_focus_row);
238 static void gtk_ctree_unlink (GtkCTree *ctree,
240 gboolean update_focus_row);
241 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
243 static gboolean ctree_is_hot_spot (GtkCTree *ctree,
248 static void tree_sort (GtkCTree *ctree,
251 static void fake_unselect_all (GtkCList *clist,
253 static GList * selection_find (GtkCList *clist,
255 GList *row_list_element);
256 static void resync_selection (GtkCList *clist,
258 static void real_undo_selection (GtkCList *clist);
259 static void select_row_recursive (GtkCTree *ctree,
262 static gint real_insert_row (GtkCList *clist,
265 static void real_remove_row (GtkCList *clist,
267 static void real_sort_list (GtkCList *clist);
268 static void cell_size_request (GtkCList *clist,
269 GtkCListRow *clist_row,
271 GtkRequisition *requisition);
272 static void column_auto_resize (GtkCList *clist,
273 GtkCListRow *clist_row,
276 static void auto_resize_columns (GtkCList *clist);
279 static gboolean check_drag (GtkCTree *ctree,
280 GtkCTreeNode *drag_source,
281 GtkCTreeNode *drag_target,
282 GtkCListDragPos insert_pos);
283 static void gtk_ctree_drag_begin (GtkWidget *widget,
284 GdkDragContext *context);
285 static gint gtk_ctree_drag_motion (GtkWidget *widget,
286 GdkDragContext *context,
290 static void gtk_ctree_drag_data_received (GtkWidget *widget,
291 GdkDragContext *context,
294 GtkSelectionData *selection_data,
297 static void remove_grab (GtkCList *clist);
298 static void drag_dest_cell (GtkCList *clist,
301 GtkCListDestInfo *dest_info);
311 CHANGE_FOCUS_ROW_EXPANSION,
315 static GtkCListClass *parent_class = NULL;
316 static GtkContainerClass *container_class = NULL;
317 static guint ctree_signals[LAST_SIGNAL] = {0};
321 gtk_ctree_get_type (void)
323 static GtkType ctree_type = 0;
327 static const GtkTypeInfo ctree_info =
331 sizeof (GtkCTreeClass),
332 (GtkClassInitFunc) gtk_ctree_class_init,
333 (GtkObjectInitFunc) gtk_ctree_init,
334 /* reserved_1 */ NULL,
335 /* reserved_2 */ NULL,
336 (GtkClassInitFunc) NULL,
339 ctree_type = gtk_type_unique (GTK_TYPE_CLIST, &ctree_info);
346 gtk_ctree_class_init (GtkCTreeClass *klass)
348 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
349 GtkObjectClass *object_class;
350 GtkWidgetClass *widget_class;
351 GtkCListClass *clist_class;
352 GtkBindingSet *binding_set;
354 gobject_class->constructor = gtk_ctree_constructor;
356 object_class = (GtkObjectClass *) klass;
357 widget_class = (GtkWidgetClass *) klass;
358 container_class = (GtkContainerClass *) klass;
359 clist_class = (GtkCListClass *) klass;
361 parent_class = gtk_type_class (GTK_TYPE_CLIST);
362 container_class = gtk_type_class (GTK_TYPE_CONTAINER);
364 object_class->set_arg = gtk_ctree_set_arg;
365 object_class->get_arg = gtk_ctree_get_arg;
367 widget_class->realize = gtk_ctree_realize;
368 widget_class->unrealize = gtk_ctree_unrealize;
369 widget_class->button_press_event = gtk_ctree_button_press;
371 widget_class->drag_begin = gtk_ctree_drag_begin;
372 widget_class->drag_motion = gtk_ctree_drag_motion;
373 widget_class->drag_data_received = gtk_ctree_drag_data_received;
375 clist_class->select_row = real_select_row;
376 clist_class->unselect_row = real_unselect_row;
377 clist_class->row_move = real_row_move;
378 clist_class->undo_selection = real_undo_selection;
379 clist_class->resync_selection = resync_selection;
380 clist_class->selection_find = selection_find;
381 clist_class->click_column = NULL;
382 clist_class->draw_row = draw_row;
383 clist_class->draw_drag_highlight = draw_drag_highlight;
384 clist_class->clear = real_clear;
385 clist_class->select_all = real_select_all;
386 clist_class->unselect_all = real_unselect_all;
387 clist_class->fake_unselect_all = fake_unselect_all;
388 clist_class->insert_row = real_insert_row;
389 clist_class->remove_row = real_remove_row;
390 clist_class->sort_list = real_sort_list;
391 clist_class->set_cell_contents = set_cell_contents;
392 clist_class->cell_size_request = cell_size_request;
394 klass->tree_select_row = real_tree_select;
395 klass->tree_unselect_row = real_tree_unselect;
396 klass->tree_expand = real_tree_expand;
397 klass->tree_collapse = real_tree_collapse;
398 klass->tree_move = real_tree_move;
399 klass->change_focus_row_expansion = change_focus_row_expansion;
401 gtk_object_add_arg_type ("GtkCTree::n_columns", /* overrides GtkCList::n_columns!! */
403 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
405 gtk_object_add_arg_type ("GtkCTree::tree_column",
407 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
409 gtk_object_add_arg_type ("GtkCTree::indent",
413 gtk_object_add_arg_type ("GtkCTree::spacing",
417 gtk_object_add_arg_type ("GtkCTree::show_stub",
421 gtk_object_add_arg_type ("GtkCTree::line_style",
422 GTK_TYPE_CTREE_LINE_STYLE,
425 gtk_object_add_arg_type ("GtkCTree::expander_style",
426 GTK_TYPE_CTREE_EXPANDER_STYLE,
430 ctree_signals[TREE_SELECT_ROW] =
431 gtk_signal_new ("tree_select_row",
433 GTK_CLASS_TYPE (object_class),
434 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_select_row),
435 gtk_marshal_VOID__POINTER_INT,
436 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
437 ctree_signals[TREE_UNSELECT_ROW] =
438 gtk_signal_new ("tree_unselect_row",
440 GTK_CLASS_TYPE (object_class),
441 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_unselect_row),
442 gtk_marshal_VOID__POINTER_INT,
443 GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT);
444 ctree_signals[TREE_EXPAND] =
445 gtk_signal_new ("tree_expand",
447 GTK_CLASS_TYPE (object_class),
448 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_expand),
449 gtk_marshal_VOID__POINTER,
450 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
451 ctree_signals[TREE_COLLAPSE] =
452 gtk_signal_new ("tree_collapse",
454 GTK_CLASS_TYPE (object_class),
455 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_collapse),
456 gtk_marshal_VOID__POINTER,
457 GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
458 ctree_signals[TREE_MOVE] =
459 gtk_signal_new ("tree_move",
461 GTK_CLASS_TYPE (object_class),
462 GTK_SIGNAL_OFFSET (GtkCTreeClass, tree_move),
463 gtk_marshal_VOID__POINTER_POINTER_POINTER,
464 GTK_TYPE_NONE, 3, GTK_TYPE_POINTER,
465 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
466 ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
467 gtk_signal_new ("change_focus_row_expansion",
468 GTK_RUN_LAST | GTK_RUN_ACTION,
469 GTK_CLASS_TYPE (object_class),
470 GTK_SIGNAL_OFFSET (GtkCTreeClass,
471 change_focus_row_expansion),
472 gtk_marshal_VOID__ENUM,
473 GTK_TYPE_NONE, 1, GTK_TYPE_CTREE_EXPANSION_TYPE);
475 binding_set = gtk_binding_set_by_class (klass);
476 gtk_binding_entry_add_signal (binding_set,
478 "change_focus_row_expansion", 1,
479 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
480 gtk_binding_entry_add_signal (binding_set,
482 "change_focus_row_expansion", 1,
483 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND);
484 gtk_binding_entry_add_signal (binding_set,
485 GDK_KP_Add, GDK_CONTROL_MASK,
486 "change_focus_row_expansion", 1,
488 GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
489 gtk_binding_entry_add_signal (binding_set,
491 "change_focus_row_expansion", 1,
492 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
493 gtk_binding_entry_add_signal (binding_set,
495 "change_focus_row_expansion", 1,
496 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE);
497 gtk_binding_entry_add_signal (binding_set,
498 GDK_KP_Subtract, GDK_CONTROL_MASK,
499 "change_focus_row_expansion", 1,
501 GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
502 gtk_binding_entry_add_signal (binding_set,
504 "change_focus_row_expansion", 1,
505 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
506 gtk_binding_entry_add_signal (binding_set,
508 "change_focus_row_expansion", 1,
509 GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE);
510 gtk_binding_entry_add_signal (binding_set,
511 GDK_KP_Multiply, GDK_CONTROL_MASK,
512 "change_focus_row_expansion", 1,
514 GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
518 gtk_ctree_set_arg (GtkObject *object,
525 ctree = GTK_CTREE (object);
526 clist = GTK_CLIST (ctree);
530 case ARG_N_COLUMNS: /* construct-only arg, only set at construction time */
531 g_return_if_fail (clist->row_mem_chunk == NULL);
532 clist->columns = MAX (1, GTK_VALUE_UINT (*arg));
533 clist->row_mem_chunk = g_mem_chunk_new ("ctree row mem chunk",
534 sizeof (GtkCTreeRow),
536 * CLIST_OPTIMUM_SIZE,
538 clist->cell_mem_chunk = g_mem_chunk_new ("ctree cell mem chunk",
539 sizeof (GtkCell) * clist->columns,
540 sizeof (GtkCell) * clist->columns
541 * CLIST_OPTIMUM_SIZE,
543 ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns);
545 case ARG_TREE_COLUMN: /* construct-only arg, only set at construction time */
546 ctree->tree_column = GTK_VALUE_UINT (*arg);
547 if (clist->row_mem_chunk)
548 ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns);
551 gtk_ctree_set_indent (ctree, GTK_VALUE_UINT (*arg));
554 gtk_ctree_set_spacing (ctree, GTK_VALUE_UINT (*arg));
557 gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg));
560 gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg));
562 case ARG_EXPANDER_STYLE:
563 gtk_ctree_set_expander_style (ctree, GTK_VALUE_ENUM (*arg));
571 gtk_ctree_get_arg (GtkObject *object,
577 ctree = GTK_CTREE (object);
582 GTK_VALUE_UINT (*arg) = GTK_CLIST (ctree)->columns;
584 case ARG_TREE_COLUMN:
585 GTK_VALUE_UINT (*arg) = ctree->tree_column;
588 GTK_VALUE_UINT (*arg) = ctree->tree_indent;
591 GTK_VALUE_UINT (*arg) = ctree->tree_spacing;
594 GTK_VALUE_BOOL (*arg) = ctree->show_stub;
597 GTK_VALUE_ENUM (*arg) = ctree->line_style;
599 case ARG_EXPANDER_STYLE:
600 GTK_VALUE_ENUM (*arg) = ctree->expander_style;
603 arg->type = GTK_TYPE_INVALID;
609 gtk_ctree_init (GtkCTree *ctree)
613 GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_RECT);
614 GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_LINE);
616 clist = GTK_CLIST (ctree);
618 ctree->tree_indent = 20;
619 ctree->tree_spacing = 5;
620 ctree->tree_column = 0;
621 ctree->line_style = GTK_CTREE_LINES_SOLID;
622 ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE;
623 ctree->drag_compare = NULL;
624 ctree->show_stub = TRUE;
626 clist->button_actions[0] |= GTK_BUTTON_EXPANDS;
630 ctree_attach_styles (GtkCTree *ctree,
637 clist = GTK_CLIST (ctree);
639 if (GTK_CTREE_ROW (node)->row.style)
640 GTK_CTREE_ROW (node)->row.style =
641 gtk_style_attach (GTK_CTREE_ROW (node)->row.style, clist->clist_window);
643 if (GTK_CTREE_ROW (node)->row.fg_set || GTK_CTREE_ROW (node)->row.bg_set)
645 GdkColormap *colormap;
647 colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
648 if (GTK_CTREE_ROW (node)->row.fg_set)
649 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.foreground));
650 if (GTK_CTREE_ROW (node)->row.bg_set)
651 gdk_color_alloc (colormap, &(GTK_CTREE_ROW (node)->row.background));
654 for (i = 0; i < clist->columns; i++)
655 if (GTK_CTREE_ROW (node)->row.cell[i].style)
656 GTK_CTREE_ROW (node)->row.cell[i].style =
657 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[i].style,
658 clist->clist_window);
662 ctree_detach_styles (GtkCTree *ctree,
669 clist = GTK_CLIST (ctree);
671 if (GTK_CTREE_ROW (node)->row.style)
672 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
673 for (i = 0; i < clist->columns; i++)
674 if (GTK_CTREE_ROW (node)->row.cell[i].style)
675 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[i].style);
679 gtk_ctree_realize (GtkWidget *widget)
688 g_return_if_fail (widget != NULL);
689 g_return_if_fail (GTK_IS_CTREE (widget));
691 GTK_WIDGET_CLASS (parent_class)->realize (widget);
693 ctree = GTK_CTREE (widget);
694 clist = GTK_CLIST (widget);
696 node = GTK_CTREE_NODE (clist->row_list);
697 for (i = 0; i < clist->rows; i++)
699 if (GTK_CTREE_ROW (node)->children && !GTK_CTREE_ROW (node)->expanded)
700 for (child = GTK_CTREE_ROW (node)->children; child;
701 child = GTK_CTREE_ROW (child)->sibling)
702 gtk_ctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
703 node = GTK_CTREE_NODE_NEXT (node);
706 values.foreground = widget->style->fg[GTK_STATE_NORMAL];
707 values.background = widget->style->base[GTK_STATE_NORMAL];
708 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
709 values.line_style = GDK_LINE_SOLID;
710 ctree->lines_gc = gdk_gc_new_with_values (GTK_CLIST(widget)->clist_window,
717 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
719 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
720 GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
721 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
726 gtk_ctree_unrealize (GtkWidget *widget)
731 g_return_if_fail (widget != NULL);
732 g_return_if_fail (GTK_IS_CTREE (widget));
734 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
736 ctree = GTK_CTREE (widget);
737 clist = GTK_CLIST (widget);
739 if (GTK_WIDGET_REALIZED (widget))
745 node = GTK_CTREE_NODE (clist->row_list);
746 for (i = 0; i < clist->rows; i++)
748 if (GTK_CTREE_ROW (node)->children &&
749 !GTK_CTREE_ROW (node)->expanded)
750 for (child = GTK_CTREE_ROW (node)->children; child;
751 child = GTK_CTREE_ROW (child)->sibling)
752 gtk_ctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
753 node = GTK_CTREE_NODE_NEXT (node);
757 gdk_gc_destroy (ctree->lines_gc);
761 gtk_ctree_button_press (GtkWidget *widget,
762 GdkEventButton *event)
768 g_return_val_if_fail (widget != NULL, FALSE);
769 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
770 g_return_val_if_fail (event != NULL, FALSE);
772 ctree = GTK_CTREE (widget);
773 clist = GTK_CLIST (widget);
775 button_actions = clist->button_actions[event->button - 1];
777 if (button_actions == GTK_BUTTON_IGNORED)
780 if (event->window == clist->clist_window)
791 if (!gtk_clist_get_selection_info (clist, x, y, &row, &column))
794 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
796 if (button_actions & GTK_BUTTON_EXPANDS &&
797 (GTK_CTREE_ROW (work)->children && !GTK_CTREE_ROW (work)->is_leaf &&
798 (event->type == GDK_2BUTTON_PRESS ||
799 ctree_is_hot_spot (ctree, work, row, x, y))))
801 if (GTK_CTREE_ROW (work)->expanded)
802 gtk_ctree_collapse (ctree, work);
804 gtk_ctree_expand (ctree, work);
809 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
813 draw_drag_highlight (GtkCList *clist,
814 GtkCListRow *dest_row,
815 gint dest_row_number,
816 GtkCListDragPos drag_pos)
824 g_return_if_fail (clist != NULL);
825 g_return_if_fail (GTK_IS_CTREE (clist));
827 ctree = GTK_CTREE (clist);
829 level = ((GtkCTreeRow *)(dest_row))->level;
831 y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
835 case GTK_CLIST_DRAG_NONE:
837 case GTK_CLIST_DRAG_AFTER:
838 y += clist->row_height + 1;
839 case GTK_CLIST_DRAG_BEFORE:
841 if (clist->column[ctree->tree_column].visible)
842 switch (clist->column[ctree->tree_column].justification)
844 case GTK_JUSTIFY_CENTER:
845 case GTK_JUSTIFY_FILL:
846 case GTK_JUSTIFY_LEFT:
847 if (ctree->tree_column > 0)
848 gdk_draw_line (clist->clist_window, clist->xor_gc,
849 COLUMN_LEFT_XPIXEL(clist, 0), y,
850 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+
851 clist->column[ctree->tree_column - 1].area.width,
854 gdk_draw_line (clist->clist_window, clist->xor_gc,
855 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
856 ctree->tree_indent * level -
857 (ctree->tree_indent - PM_SIZE) / 2, y,
858 GTK_WIDGET (ctree)->allocation.width, y);
860 case GTK_JUSTIFY_RIGHT:
861 if (ctree->tree_column < clist->columns - 1)
862 gdk_draw_line (clist->clist_window, clist->xor_gc,
863 COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1),
865 COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
866 clist->column[clist->columns - 1].area.width, y);
868 gdk_draw_line (clist->clist_window, clist->xor_gc,
869 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
870 + clist->column[ctree->tree_column].area.width -
871 ctree->tree_indent * level +
872 (ctree->tree_indent - PM_SIZE) / 2, y);
876 gdk_draw_line (clist->clist_window, clist->xor_gc,
877 0, y, clist->clist_window_width, y);
879 case GTK_CLIST_DRAG_INTO:
880 y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height;
882 if (clist->column[ctree->tree_column].visible)
883 switch (clist->column[ctree->tree_column].justification)
885 case GTK_JUSTIFY_CENTER:
886 case GTK_JUSTIFY_FILL:
887 case GTK_JUSTIFY_LEFT:
888 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) +
889 ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
891 points[3].x = points[0].x;
892 points[3].y = y - clist->row_height - 1;
893 points[1].x = clist->clist_window_width - 1;
894 points[1].y = points[0].y;
895 points[2].x = points[1].x;
896 points[2].y = points[3].y;
898 for (i = 0; i < 3; i++)
899 gdk_draw_line (clist->clist_window, clist->xor_gc,
900 points[i].x, points[i].y,
901 points[i+1].x, points[i+1].y);
903 if (ctree->tree_column > 0)
905 points[0].x = COLUMN_LEFT_XPIXEL(clist,
906 ctree->tree_column - 1) +
907 clist->column[ctree->tree_column - 1].area.width ;
909 points[3].x = points[0].x;
910 points[3].y = y - clist->row_height - 1;
912 points[1].y = points[0].y;
914 points[2].y = points[3].y;
916 for (i = 0; i < 3; i++)
917 gdk_draw_line (clist->clist_window, clist->xor_gc,
918 points[i].x, points[i].y, points[i+1].x,
922 case GTK_JUSTIFY_RIGHT:
923 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) -
924 ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
925 clist->column[ctree->tree_column].area.width;
927 points[3].x = points[0].x;
928 points[3].y = y - clist->row_height - 1;
930 points[1].y = points[0].y;
932 points[2].y = points[3].y;
934 for (i = 0; i < 3; i++)
935 gdk_draw_line (clist->clist_window, clist->xor_gc,
936 points[i].x, points[i].y,
937 points[i+1].x, points[i+1].y);
939 if (ctree->tree_column < clist->columns - 1)
941 points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1);
943 points[3].x = points[0].x;
944 points[3].y = y - clist->row_height - 1;
945 points[1].x = clist->clist_window_width - 1;
946 points[1].y = points[0].y;
947 points[2].x = points[1].x;
948 points[2].y = points[3].y;
950 for (i = 0; i < 3; i++)
951 gdk_draw_line (clist->clist_window, clist->xor_gc,
952 points[i].x, points[i].y,
953 points[i+1].x, points[i+1].y);
958 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
959 0, y - clist->row_height,
960 clist->clist_window_width - 1, clist->row_height);
966 draw_cell_pixmap (GdkWindow *window,
967 GdkRectangle *clip_rectangle,
981 gdk_gc_set_clip_mask (fg_gc, mask);
982 gdk_gc_set_clip_origin (fg_gc, x, y);
984 if (x < clip_rectangle->x)
986 xsrc = clip_rectangle->x - x;
988 x = clip_rectangle->x;
990 if (x + width > clip_rectangle->x + clip_rectangle->width)
991 width = clip_rectangle->x + clip_rectangle->width - x;
993 if (y < clip_rectangle->y)
995 ysrc = clip_rectangle->y - y;
997 y = clip_rectangle->y;
999 if (y + height > clip_rectangle->y + clip_rectangle->height)
1000 height = clip_rectangle->y + clip_rectangle->height - y;
1002 if (width > 0 && height > 0)
1003 gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
1007 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1008 gdk_gc_set_clip_origin (fg_gc, 0, 0);
1011 return x + MAX (width, 0);
1015 get_cell_style (GtkCList *clist,
1016 GtkCListRow *clist_row,
1025 if ((state == GTK_STATE_NORMAL) &&
1026 (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
1027 fg_state = GTK_STATE_INSENSITIVE;
1031 if (clist_row->cell[column].style)
1034 *style = clist_row->cell[column].style;
1036 *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
1038 if (state == GTK_STATE_SELECTED)
1039 *bg_gc = clist_row->cell[column].style->bg_gc[state];
1041 *bg_gc = clist_row->cell[column].style->base_gc[state];
1044 else if (clist_row->style)
1047 *style = clist_row->style;
1049 *fg_gc = clist_row->style->fg_gc[fg_state];
1051 if (state == GTK_STATE_SELECTED)
1052 *bg_gc = clist_row->style->bg_gc[state];
1054 *bg_gc = clist_row->style->base_gc[state];
1060 *style = GTK_WIDGET (clist)->style;
1062 *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
1064 if (state == GTK_STATE_SELECTED)
1065 *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
1067 *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
1070 if (state != GTK_STATE_SELECTED)
1072 if (fg_gc && clist_row->fg_set)
1073 *fg_gc = clist->fg_gc;
1074 if (bg_gc && clist_row->bg_set)
1075 *bg_gc = clist->bg_gc;
1081 gtk_ctree_draw_expander (GtkCTree *ctree,
1082 GtkCTreeRow *ctree_row,
1084 GdkRectangle *clip_rectangle,
1089 gint justification_factor;
1092 if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
1095 clist = GTK_CLIST (ctree);
1096 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
1097 justification_factor = -1;
1099 justification_factor = 1;
1100 y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
1101 (clip_rectangle->height + 1) % 2);
1103 if (!ctree_row->children)
1105 switch (ctree->expander_style)
1107 case GTK_CTREE_EXPANDER_NONE:
1109 case GTK_CTREE_EXPANDER_TRIANGLE:
1110 return x + justification_factor * (PM_SIZE + 3);
1111 case GTK_CTREE_EXPANDER_SQUARE:
1112 case GTK_CTREE_EXPANDER_CIRCULAR:
1113 return x + justification_factor * (PM_SIZE + 1);
1117 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle);
1118 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle);
1120 switch (ctree->expander_style)
1122 case GTK_CTREE_EXPANDER_NONE:
1124 case GTK_CTREE_EXPANDER_TRIANGLE:
1125 if (ctree_row->expanded)
1128 points[0].y = y + (PM_SIZE + 2) / 6;
1129 points[1].x = points[0].x + justification_factor * (PM_SIZE + 2);
1130 points[1].y = points[0].y;
1131 points[2].x = (points[0].x +
1132 justification_factor * (PM_SIZE + 2) / 2);
1133 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
1137 points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2);
1138 points[0].y = y - 1;
1139 points[1].x = points[0].x;
1140 points[1].y = points[0].y + (PM_SIZE + 2);
1141 points[2].x = (points[0].x +
1142 justification_factor * (2 * (PM_SIZE + 2) / 3 - 1));
1143 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
1146 gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1148 gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1151 x += justification_factor * (PM_SIZE + 3);
1153 case GTK_CTREE_EXPANDER_SQUARE:
1154 case GTK_CTREE_EXPANDER_CIRCULAR:
1155 if (justification_factor == -1)
1156 x += justification_factor * (PM_SIZE + 1);
1158 if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
1160 gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
1161 TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1162 gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1163 FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
1167 gdk_draw_rectangle (clist->clist_window,
1168 style->base_gc[GTK_STATE_NORMAL], TRUE,
1169 x, y, PM_SIZE, PM_SIZE);
1170 gdk_draw_rectangle (clist->clist_window,
1171 style->fg_gc[GTK_STATE_NORMAL], FALSE,
1172 x, y, PM_SIZE, PM_SIZE);
1175 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1176 x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
1178 if (!ctree_row->expanded)
1179 gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
1180 x + PM_SIZE / 2, y + 2,
1181 x + PM_SIZE / 2, y + PM_SIZE - 2);
1183 if (justification_factor == 1)
1184 x += justification_factor * (PM_SIZE + 1);
1188 gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
1189 gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
1196 gtk_ctree_draw_lines (GtkCTree *ctree,
1197 GtkCTreeRow *ctree_row,
1201 GdkRectangle *clip_rectangle,
1202 GdkRectangle *cell_rectangle,
1203 GdkRectangle *crect,
1209 GtkCTreeNode *parent;
1210 GdkRectangle tree_rectangle;
1211 GdkRectangle tc_rectangle;
1222 gint justification_factor;
1224 clist = GTK_CLIST (ctree);
1225 ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
1226 justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
1230 offset = (clip_rectangle->x + clip_rectangle->width - 1 -
1231 ctree->tree_indent * (ctree_row->level - 1));
1232 justification_factor = -1;
1236 offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1);
1237 justification_factor = 1;
1240 switch (ctree->line_style)
1242 case GTK_CTREE_LINES_NONE:
1244 case GTK_CTREE_LINES_TABBED:
1245 xcenter = offset + justification_factor * TAB_SIZE;
1247 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1248 clist->column[ctree->tree_column].area.width +
1250 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1251 COLUMN_INSET - CELL_SPACING);
1255 tree_rectangle.y = crect->y;
1256 tree_rectangle.height = crect->height;
1260 tree_rectangle.x = xcenter;
1261 tree_rectangle.width = column_right - xcenter;
1265 tree_rectangle.x = column_left;
1266 tree_rectangle.width = xcenter - column_left;
1269 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1271 offset += justification_factor * 3;
1276 gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
1278 next_level = ctree_row->level;
1280 if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
1282 node = gtk_ctree_find_node_ptr (ctree, ctree_row);
1283 if (GTK_CTREE_NODE_NEXT (node))
1284 next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level;
1289 if (ctree->tree_indent > 0)
1291 node = ctree_row->parent;
1294 xcenter -= (justification_factor * ctree->tree_indent);
1296 if ((justify_right && xcenter < column_left) ||
1297 (!justify_right && xcenter > column_right))
1299 node = GTK_CTREE_ROW (node)->parent;
1303 tree_rectangle.y = cell_rectangle->y;
1304 tree_rectangle.height = cell_rectangle->height;
1307 tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1,
1309 tree_rectangle.width = MIN (xcenter - column_left,
1310 ctree->tree_indent);
1314 tree_rectangle.x = xcenter;
1315 tree_rectangle.width = MIN (column_right - xcenter,
1316 ctree->tree_indent);
1319 if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
1322 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1323 state, column, NULL, NULL, &bg_gc);
1325 if (bg_gc == clist->bg_gc)
1326 gdk_gc_set_foreground
1327 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1330 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1333 tree_rectangle.width,
1334 tree_rectangle.height);
1336 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1340 tc_rectangle.height);
1342 if (next_level > GTK_CTREE_ROW (node)->level)
1343 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1345 xcenter, crect->y + crect->height);
1350 offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
1351 width = offset_x / 2 + offset_x % 2;
1353 parent = GTK_CTREE_ROW (node)->parent;
1355 tree_rectangle.y = ycenter;
1356 tree_rectangle.height = (cell_rectangle->y - ycenter +
1357 cell_rectangle->height);
1361 tree_rectangle.x = MAX(xcenter + 1 - width, column_left);
1362 tree_rectangle.width = MIN (xcenter + 1 - column_left,
1367 tree_rectangle.x = xcenter;
1368 tree_rectangle.width = MIN (column_right - xcenter,
1373 gdk_rectangle_intersect (area, &tree_rectangle,
1378 get_cell_style (clist, >K_CTREE_ROW (parent)->row,
1379 state, column, NULL, NULL, &bg_gc);
1380 if (bg_gc == clist->bg_gc)
1381 gdk_gc_set_foreground
1383 >K_CTREE_ROW (parent)->row.background);
1385 else if (state == GTK_STATE_SELECTED)
1386 bg_gc = style->base_gc[state];
1388 bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
1391 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1394 tree_rectangle.width,
1395 tree_rectangle.height);
1397 gdk_draw_rectangle (clist->clist_window,
1402 tc_rectangle.height);
1405 get_cell_style (clist, >K_CTREE_ROW (node)->row,
1406 state, column, NULL, NULL, &bg_gc);
1407 if (bg_gc == clist->bg_gc)
1408 gdk_gc_set_foreground
1409 (clist->bg_gc, >K_CTREE_ROW (node)->row.background);
1411 gdk_gc_set_clip_rectangle (bg_gc, crect);
1412 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1413 xcenter - (justify_right * offset_x),
1415 offset_x, clist->row_height,
1416 (180 + (justify_right * 90)) * 64, 90 * 64);
1417 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1419 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1420 xcenter, cell_rectangle->y, xcenter, ycenter);
1423 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1424 xcenter - offset_x, cell_rectangle->y,
1425 offset_x, clist->row_height,
1428 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1429 xcenter, cell_rectangle->y,
1430 offset_x, clist->row_height,
1433 node = GTK_CTREE_ROW (node)->parent;
1437 if (state != GTK_STATE_SELECTED)
1439 tree_rectangle.y = clip_rectangle->y;
1440 tree_rectangle.height = clip_rectangle->height;
1441 tree_rectangle.width = COLUMN_INSET + CELL_SPACING +
1442 MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET,
1446 tree_rectangle.x = MAX (xcenter + 1, column_left);
1448 tree_rectangle.x = column_left;
1451 gdk_draw_rectangle (clist->clist_window,
1453 (ctree)->style->base_gc[GTK_STATE_NORMAL],
1457 tree_rectangle.width,
1458 tree_rectangle.height);
1459 else if (gdk_rectangle_intersect (area, &tree_rectangle,
1461 gdk_draw_rectangle (clist->clist_window,
1463 (ctree)->style->base_gc[GTK_STATE_NORMAL],
1468 tc_rectangle.height);
1471 xcenter = offset + (justification_factor * ctree->tree_indent / 2);
1473 get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL,
1475 if (bg_gc == clist->bg_gc)
1476 gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background);
1478 gdk_gc_set_clip_rectangle (bg_gc, crect);
1479 if (ctree_row->is_leaf)
1483 points[0].x = offset + justification_factor * TAB_SIZE;
1484 points[0].y = cell_rectangle->y;
1486 points[1].x = points[0].x - justification_factor * 4;
1487 points[1].y = points[0].y;
1489 points[2].x = points[1].x - justification_factor * 2;
1490 points[2].y = points[1].y + 3;
1492 points[3].x = points[2].x;
1493 points[3].y = points[2].y + clist->row_height - 5;
1495 points[4].x = points[3].x + justification_factor * 2;
1496 points[4].y = points[3].y + 3;
1498 points[5].x = points[4].x + justification_factor * 4;
1499 points[5].y = points[4].y;
1501 gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6);
1502 gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6);
1506 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
1507 offset - (justify_right * 2 * TAB_SIZE),
1509 2 * TAB_SIZE, clist->row_height,
1510 (90 + (180 * justify_right)) * 64, 180 * 64);
1511 gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
1512 offset - (justify_right * 2 * TAB_SIZE),
1514 2 * TAB_SIZE, clist->row_height,
1515 (90 + (180 * justify_right)) * 64, 180 * 64);
1517 gdk_gc_set_clip_rectangle (bg_gc, NULL);
1518 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1520 offset += justification_factor * 3;
1523 xcenter = offset + justification_factor * PM_SIZE / 2;
1527 tree_rectangle.y = crect->y;
1528 tree_rectangle.height = crect->height;
1532 tree_rectangle.x = xcenter - PM_SIZE / 2 - 2;
1533 tree_rectangle.width = (clip_rectangle->x +
1534 clip_rectangle->width -tree_rectangle.x);
1538 tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2;
1539 tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 -
1543 if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
1549 if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
1551 offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
1552 offset_y = abs((cell_rectangle->y + clist->voffset) % 2);
1555 clip_rectangle->y--;
1556 clip_rectangle->height++;
1557 gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle);
1558 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1560 (ctree->show_stub || clist->row_list->data != ctree_row) ?
1561 cell_rectangle->y + offset_y : ycenter,
1563 (ctree_row->sibling) ? crect->y +crect->height : ycenter);
1565 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1566 xcenter + (justification_factor * offset_x), ycenter,
1567 xcenter + (justification_factor * (PM_SIZE / 2 + 2)),
1570 node = ctree_row->parent;
1573 xcenter -= (justification_factor * ctree->tree_indent);
1575 if (GTK_CTREE_ROW (node)->sibling)
1576 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1577 xcenter, cell_rectangle->y + offset_y,
1578 xcenter, crect->y + crect->height);
1579 node = GTK_CTREE_ROW (node)->parent;
1581 gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
1582 clip_rectangle->y++;
1583 clip_rectangle->height--;
1590 draw_row (GtkCList *clist,
1593 GtkCListRow *clist_row)
1598 GdkRectangle *crect;
1599 GdkRectangle row_rectangle;
1600 GdkRectangle cell_rectangle;
1601 GdkRectangle clip_rectangle;
1602 GdkRectangle intersect_rectangle;
1604 gint column_left = 0;
1605 gint column_right = 0;
1610 g_return_if_fail (clist != NULL);
1612 /* bail now if we arn't drawable yet */
1613 if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
1616 widget = GTK_WIDGET (clist);
1617 ctree = GTK_CTREE (clist);
1619 /* if the function is passed the pointer to the row instead of null,
1620 * it avoids this expensive lookup */
1622 clist_row = (g_list_nth (clist->row_list, row))->data;
1624 /* rectangle of the entire row */
1625 row_rectangle.x = 0;
1626 row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
1627 row_rectangle.width = clist->clist_window_width;
1628 row_rectangle.height = clist->row_height;
1630 /* rectangle of the cell spacing above the row */
1631 cell_rectangle.x = 0;
1632 cell_rectangle.y = row_rectangle.y - CELL_SPACING;
1633 cell_rectangle.width = row_rectangle.width;
1634 cell_rectangle.height = CELL_SPACING;
1636 /* rectangle used to clip drawing operations, its y and height
1637 * positions only need to be set once, so we set them once here.
1638 * the x and width are set withing the drawing loop below once per
1640 clip_rectangle.y = row_rectangle.y;
1641 clip_rectangle.height = row_rectangle.height;
1643 if (clist_row->state == GTK_STATE_NORMAL)
1645 if (clist_row->fg_set)
1646 gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
1647 if (clist_row->bg_set)
1648 gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
1651 state = clist_row->state;
1653 gdk_gc_set_foreground (ctree->lines_gc,
1654 &widget->style->fg[clist_row->state]);
1656 /* draw the cell borders */
1659 rect = &intersect_rectangle;
1660 crect = &intersect_rectangle;
1662 if (gdk_rectangle_intersect (area, &cell_rectangle, crect))
1663 gdk_draw_rectangle (clist->clist_window,
1664 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1665 crect->x, crect->y, crect->width, crect->height);
1669 rect = &clip_rectangle;
1670 crect = &cell_rectangle;
1672 gdk_draw_rectangle (clist->clist_window,
1673 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1674 crect->x, crect->y, crect->width, crect->height);
1677 /* horizontal black lines */
1678 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1681 column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
1682 clist->column[ctree->tree_column].area.width +
1684 column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
1685 COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING);
1687 switch (clist->column[ctree->tree_column].justification)
1689 case GTK_JUSTIFY_CENTER:
1690 case GTK_JUSTIFY_FILL:
1691 case GTK_JUSTIFY_LEFT:
1692 offset = (column_left + ctree->tree_indent *
1693 (((GtkCTreeRow *)clist_row)->level - 1));
1695 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1696 MIN (offset + TAB_SIZE, column_right),
1698 clist->clist_window_width, cell_rectangle.y);
1700 case GTK_JUSTIFY_RIGHT:
1701 offset = (column_right - 1 - ctree->tree_indent *
1702 (((GtkCTreeRow *)clist_row)->level - 1));
1704 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1705 -1, cell_rectangle.y,
1706 MAX (offset - TAB_SIZE, column_left),
1712 /* the last row has to clear its bottom cell spacing too */
1713 if (clist_row == clist->row_list_end->data)
1715 cell_rectangle.y += clist->row_height + CELL_SPACING;
1717 if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect))
1719 gdk_draw_rectangle (clist->clist_window,
1720 widget->style->base_gc[GTK_STATE_ACTIVE], TRUE,
1721 crect->x, crect->y, crect->width, crect->height);
1723 /* horizontal black lines */
1724 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
1726 switch (clist->column[ctree->tree_column].justification)
1728 case GTK_JUSTIFY_CENTER:
1729 case GTK_JUSTIFY_FILL:
1730 case GTK_JUSTIFY_LEFT:
1731 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1732 MIN (column_left + TAB_SIZE + COLUMN_INSET +
1733 (((GtkCTreeRow *)clist_row)->level > 1) *
1734 MIN (ctree->tree_indent / 2, TAB_SIZE),
1737 clist->clist_window_width, cell_rectangle.y);
1739 case GTK_JUSTIFY_RIGHT:
1740 gdk_draw_line (clist->clist_window, ctree->lines_gc,
1741 -1, cell_rectangle.y,
1742 MAX (column_right - TAB_SIZE - 1 -
1744 (((GtkCTreeRow *)clist_row)->level > 1) *
1745 MIN (ctree->tree_indent / 2, TAB_SIZE),
1746 column_left - 1), cell_rectangle.y);
1753 for (last_column = clist->columns - 1;
1754 last_column >= 0 && !clist->column[last_column].visible; last_column--)
1757 /* iterate and draw all the columns (row cells) and draw their contents */
1758 for (i = 0; i < clist->columns; i++)
1763 PangoLayout *layout = NULL;
1764 PangoRectangle logical_rect;
1772 if (!clist->column[i].visible)
1775 get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
1777 /* calculate clipping region */
1778 clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
1779 clip_rectangle.width = clist->column[i].area.width;
1781 cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING;
1782 cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET +
1783 (1 + (i == last_column)) * CELL_SPACING);
1784 cell_rectangle.y = clip_rectangle.y;
1785 cell_rectangle.height = clip_rectangle.height;
1790 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
1791 &intersect_rectangle))
1793 if (i != ctree->tree_column)
1798 gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
1799 crect->x, crect->y, crect->width, crect->height);
1802 layout = _gtk_clist_create_cell_layout (clist, clist_row, i);
1805 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1806 width = logical_rect.width;
1811 switch (clist_row->cell[i].type)
1813 case GTK_CELL_PIXMAP:
1815 (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
1817 width += pixmap_width;
1819 case GTK_CELL_PIXTEXT:
1820 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1823 (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1824 &pixmap_width, &height);
1825 width += pixmap_width;
1828 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text &&
1829 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1830 width += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1832 if (i == ctree->tree_column)
1833 width += (ctree->tree_indent *
1834 ((GtkCTreeRow *)clist_row)->level);
1840 switch (clist->column[i].justification)
1842 case GTK_JUSTIFY_LEFT:
1843 offset = clip_rectangle.x + clist_row->cell[i].horizontal;
1845 case GTK_JUSTIFY_RIGHT:
1846 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
1847 clip_rectangle.width - width);
1849 case GTK_JUSTIFY_CENTER:
1850 case GTK_JUSTIFY_FILL:
1851 offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
1852 (clip_rectangle.width / 2) - (width / 2));
1856 if (i != ctree->tree_column)
1858 offset += clist_row->cell[i].horizontal;
1859 switch (clist_row->cell[i].type)
1861 case GTK_CELL_PIXMAP:
1863 (clist->clist_window, &clip_rectangle, fg_gc,
1864 GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
1865 GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
1867 clip_rectangle.y + clist_row->cell[i].vertical +
1868 (clip_rectangle.height - height) / 2,
1869 pixmap_width, height);
1871 case GTK_CELL_PIXTEXT:
1872 offset = draw_cell_pixmap
1873 (clist->clist_window, &clip_rectangle, fg_gc,
1874 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1875 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
1877 clip_rectangle.y + clist_row->cell[i].vertical +
1878 (clip_rectangle.height - height) / 2,
1879 pixmap_width, height);
1880 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1886 gint row_center_offset = 1.5 + (clist->row_height - logical_rect.height - 1) / 2;
1888 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
1889 gdk_draw_layout (clist->clist_window, fg_gc,
1891 row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
1893 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1894 g_object_unref (G_OBJECT (layout));
1904 if (bg_gc == clist->bg_gc)
1905 gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
1907 /* draw ctree->tree_column */
1908 cell_rectangle.y -= CELL_SPACING;
1909 cell_rectangle.height += CELL_SPACING;
1911 if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
1912 &intersect_rectangle))
1915 g_object_unref (G_OBJECT (layout));
1920 offset = gtk_ctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
1921 state, &clip_rectangle, &cell_rectangle,
1922 crect, area, style);
1925 offset = gtk_ctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
1926 style, &clip_rectangle, offset);
1928 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1929 offset -= ctree->tree_spacing;
1931 offset += ctree->tree_spacing;
1933 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1934 offset -= (pixmap_width + clist_row->cell[i].horizontal);
1936 offset += clist_row->cell[i].horizontal;
1938 old_offset = offset;
1939 offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
1940 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
1941 GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
1943 clip_rectangle.y + clist_row->cell[i].vertical
1944 + (clip_rectangle.height - height) / 2,
1945 pixmap_width, height);
1949 gint row_center_offset = 1.5 + (clist->row_height - logical_rect.height - 1) / 2;
1951 if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
1953 offset = (old_offset - string_width);
1954 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1955 offset -= GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1959 if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
1960 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
1963 gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
1964 gdk_draw_layout (clist->clist_window, fg_gc,
1966 row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
1969 g_object_unref (G_OBJECT (layout));
1971 gdk_gc_set_clip_rectangle (fg_gc, NULL);
1974 /* draw focus rectangle */
1975 if (clist->focus_row == row &&
1976 GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS (widget))
1979 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1980 row_rectangle.x, row_rectangle.y,
1981 row_rectangle.width - 1, row_rectangle.height - 1);
1982 else if (gdk_rectangle_intersect (area, &row_rectangle,
1983 &intersect_rectangle))
1985 gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
1986 gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
1987 row_rectangle.x, row_rectangle.y,
1988 row_rectangle.width - 1,
1989 row_rectangle.height - 1);
1990 gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
1996 tree_draw_node (GtkCTree *ctree,
2001 clist = GTK_CLIST (ctree);
2003 if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
2008 work = GTK_CTREE_NODE (clist->row_list);
2009 while (work && work != node)
2011 work = GTK_CTREE_NODE_NEXT (work);
2014 if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
2015 GTK_CLIST_GET_CLASS (clist)->draw_row
2016 (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
2020 static GtkCTreeNode *
2021 gtk_ctree_last_visible (GtkCTree *ctree,
2029 work = GTK_CTREE_ROW (node)->children;
2031 if (!work || !GTK_CTREE_ROW (node)->expanded)
2034 while (GTK_CTREE_ROW (work)->sibling)
2035 work = GTK_CTREE_ROW (work)->sibling;
2037 return gtk_ctree_last_visible (ctree, work);
2041 gtk_ctree_link (GtkCTree *ctree,
2043 GtkCTreeNode *parent,
2044 GtkCTreeNode *sibling,
2045 gboolean update_focus_row)
2051 gboolean visible = FALSE;
2055 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
2056 g_return_if_fail (node != NULL);
2057 g_return_if_fail (node != sibling);
2058 g_return_if_fail (node != parent);
2060 clist = GTK_CLIST (ctree);
2062 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2064 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
2066 g_list_free (clist->undo_selection);
2067 g_list_free (clist->undo_unselection);
2068 clist->undo_selection = NULL;
2069 clist->undo_unselection = NULL;
2072 for (rows = 1, list_end = (GList *)node; list_end->next;
2073 list_end = list_end->next)
2076 GTK_CTREE_ROW (node)->parent = parent;
2077 GTK_CTREE_ROW (node)->sibling = sibling;
2079 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
2080 GTK_CTREE_ROW (parent)->expanded)))
2083 clist->rows += rows;
2087 work = (GList *)(GTK_CTREE_ROW (parent)->children);
2089 work = clist->row_list;
2093 if (work != (GList *)sibling)
2095 while (GTK_CTREE_ROW (work)->sibling != sibling)
2096 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2097 GTK_CTREE_ROW (work)->sibling = node;
2100 if (sibling == GTK_CTREE_NODE (clist->row_list))
2101 clist->row_list = (GList *) node;
2102 if (GTK_CTREE_NODE_PREV (sibling) &&
2103 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling)
2105 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
2106 list->next = (GList *)node;
2109 list = (GList *)node;
2110 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
2111 list_end->next = (GList *)sibling;
2112 list = (GList *)sibling;
2113 list->prev = list_end;
2114 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
2115 GTK_CTREE_ROW (parent)->children = node;
2122 while (GTK_CTREE_ROW (work)->sibling)
2123 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
2124 GTK_CTREE_ROW (work)->sibling = node;
2126 /* find last visible child of sibling */
2127 work = (GList *) gtk_ctree_last_visible (ctree,
2128 GTK_CTREE_NODE (work));
2130 list_end->next = work->next;
2132 list = work->next->prev = list_end;
2133 work->next = (GList *)node;
2134 list = (GList *)node;
2141 GTK_CTREE_ROW (parent)->children = node;
2142 list = (GList *)node;
2143 list->prev = (GList *)parent;
2144 if (GTK_CTREE_ROW (parent)->expanded)
2146 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
2147 if (GTK_CTREE_NODE_NEXT(parent))
2149 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
2150 list->prev = list_end;
2152 list = (GList *)parent;
2153 list->next = (GList *)node;
2156 list_end->next = NULL;
2160 clist->row_list = (GList *)node;
2161 list = (GList *)node;
2163 list_end->next = NULL;
2168 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
2170 if (clist->row_list_end == NULL ||
2171 clist->row_list_end->next == (GList *)node)
2172 clist->row_list_end = list_end;
2174 if (visible && update_focus_row)
2178 pos = g_list_position (clist->row_list, (GList *)node);
2180 if (pos <= clist->focus_row)
2182 clist->focus_row += rows;
2183 clist->undo_anchor = clist->focus_row;
2189 gtk_ctree_unlink (GtkCTree *ctree,
2191 gboolean update_focus_row)
2198 GtkCTreeNode *parent;
2201 g_return_if_fail (ctree != NULL);
2202 g_return_if_fail (GTK_IS_CTREE (ctree));
2203 g_return_if_fail (node != NULL);
2205 clist = GTK_CLIST (ctree);
2207 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED)
2209 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
2211 g_list_free (clist->undo_selection);
2212 g_list_free (clist->undo_unselection);
2213 clist->undo_selection = NULL;
2214 clist->undo_unselection = NULL;
2217 visible = gtk_ctree_is_viewable (ctree, node);
2219 /* clist->row_list_end unlinked ? */
2221 (GTK_CTREE_NODE_NEXT (node) == NULL ||
2222 (GTK_CTREE_ROW (node)->children &&
2223 gtk_ctree_is_ancestor (ctree, node,
2224 GTK_CTREE_NODE (clist->row_list_end)))))
2225 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
2229 level = GTK_CTREE_ROW (node)->level;
2230 work = GTK_CTREE_NODE_NEXT (node);
2231 while (work && GTK_CTREE_ROW (work)->level > level)
2233 work = GTK_CTREE_NODE_NEXT (work);
2239 clist->rows -= (rows + 1);
2241 if (update_focus_row)
2245 pos = g_list_position (clist->row_list, (GList *)node);
2246 if (pos + rows < clist->focus_row)
2247 clist->focus_row -= (rows + 1);
2248 else if (pos <= clist->focus_row)
2250 if (!GTK_CTREE_ROW (node)->sibling)
2251 clist->focus_row = MAX (pos - 1, 0);
2253 clist->focus_row = pos;
2255 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
2257 clist->undo_anchor = clist->focus_row;
2263 list = (GList *)GTK_CTREE_NODE_PREV (work);
2265 list = (GList *)work;
2266 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
2269 if (GTK_CTREE_NODE_PREV (node) &&
2270 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node)
2272 list = (GList *)GTK_CTREE_NODE_PREV (node);
2273 list->next = (GList *)work;
2277 parent = GTK_CTREE_ROW (node)->parent;
2280 if (GTK_CTREE_ROW (parent)->children == node)
2282 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
2283 if (!GTK_CTREE_ROW (parent)->children)
2284 gtk_ctree_collapse (ctree, parent);
2288 GtkCTreeNode *sibling;
2290 sibling = GTK_CTREE_ROW (parent)->children;
2291 while (GTK_CTREE_ROW (sibling)->sibling != node)
2292 sibling = GTK_CTREE_ROW (sibling)->sibling;
2293 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2298 if (clist->row_list == (GList *)node)
2299 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
2302 GtkCTreeNode *sibling;
2304 sibling = GTK_CTREE_NODE (clist->row_list);
2305 while (GTK_CTREE_ROW (sibling)->sibling != node)
2306 sibling = GTK_CTREE_ROW (sibling)->sibling;
2307 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
2313 real_row_move (GtkCList *clist,
2320 g_return_if_fail (clist != NULL);
2321 g_return_if_fail (GTK_IS_CTREE (clist));
2323 if (GTK_CLIST_AUTO_SORT (clist))
2326 if (source_row < 0 || source_row >= clist->rows ||
2327 dest_row < 0 || dest_row >= clist->rows ||
2328 source_row == dest_row)
2331 ctree = GTK_CTREE (clist);
2332 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, source_row));
2334 if (source_row < dest_row)
2339 work = GTK_CTREE_ROW (node)->children;
2341 while (work && GTK_CTREE_ROW (work)->level > GTK_CTREE_ROW (node)->level)
2343 work = GTK_CTREE_NODE_NEXT (work);
2347 if (dest_row > clist->rows)
2348 dest_row = clist->rows;
2351 if (dest_row < clist->rows)
2353 GtkCTreeNode *sibling;
2355 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, dest_row));
2356 gtk_ctree_move (ctree, node, GTK_CTREE_ROW (sibling)->parent, sibling);
2359 gtk_ctree_move (ctree, node, NULL, NULL);
2363 real_tree_move (GtkCTree *ctree,
2365 GtkCTreeNode *new_parent,
2366 GtkCTreeNode *new_sibling)
2370 gboolean visible = FALSE;
2372 g_return_if_fail (ctree != NULL);
2373 g_return_if_fail (node != NULL);
2374 g_return_if_fail (!new_sibling ||
2375 GTK_CTREE_ROW (new_sibling)->parent == new_parent);
2377 if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
2380 /* new_parent != child of child */
2381 for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
2385 clist = GTK_CLIST (ctree);
2387 visible = gtk_ctree_is_viewable (ctree, node);
2389 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
2391 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
2393 g_list_free (clist->undo_selection);
2394 g_list_free (clist->undo_unselection);
2395 clist->undo_selection = NULL;
2396 clist->undo_unselection = NULL;
2399 if (GTK_CLIST_AUTO_SORT (clist))
2401 if (new_parent == GTK_CTREE_ROW (node)->parent)
2405 new_sibling = GTK_CTREE_ROW (new_parent)->children;
2407 new_sibling = GTK_CTREE_NODE (clist->row_list);
2409 while (new_sibling && clist->compare
2410 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
2411 new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
2414 if (new_parent == GTK_CTREE_ROW (node)->parent &&
2415 new_sibling == GTK_CTREE_ROW (node)->sibling)
2418 gtk_clist_freeze (clist);
2421 if (gtk_ctree_is_viewable (ctree, node) ||
2422 gtk_ctree_is_viewable (ctree, new_sibling))
2423 work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
2425 gtk_ctree_unlink (ctree, node, FALSE);
2426 gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE);
2430 while (work && !gtk_ctree_is_viewable (ctree, work))
2431 work = GTK_CTREE_ROW (work)->parent;
2432 clist->focus_row = g_list_position (clist->row_list, (GList *)work);
2433 clist->undo_anchor = clist->focus_row;
2436 if (clist->column[ctree->tree_column].auto_resize &&
2437 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
2438 (visible || gtk_ctree_is_viewable (ctree, node)))
2439 gtk_clist_set_column_width
2440 (clist, ctree->tree_column,
2441 gtk_clist_optimal_column_width (clist, ctree->tree_column));
2443 gtk_clist_thaw (clist);
2447 change_focus_row_expansion (GtkCTree *ctree,
2448 GtkCTreeExpansionType action)
2453 g_return_if_fail (ctree != NULL);
2454 g_return_if_fail (GTK_IS_CTREE (ctree));
2456 clist = GTK_CLIST (ctree);
2458 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (ctree))
2462 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
2463 GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
2468 case GTK_CTREE_EXPANSION_EXPAND:
2469 gtk_ctree_expand (ctree, node);
2471 case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
2472 gtk_ctree_expand_recursive (ctree, node);
2474 case GTK_CTREE_EXPANSION_COLLAPSE:
2475 gtk_ctree_collapse (ctree, node);
2477 case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
2478 gtk_ctree_collapse_recursive (ctree, node);
2480 case GTK_CTREE_EXPANSION_TOGGLE:
2481 gtk_ctree_toggle_expansion (ctree, node);
2483 case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
2484 gtk_ctree_toggle_expansion_recursive (ctree, node);
2490 real_tree_expand (GtkCTree *ctree,
2495 GtkRequisition requisition;
2499 g_return_if_fail (ctree != NULL);
2500 g_return_if_fail (GTK_IS_CTREE (ctree));
2502 if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
2505 clist = GTK_CLIST (ctree);
2507 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
2509 GTK_CTREE_ROW (node)->expanded = TRUE;
2510 level = GTK_CTREE_ROW (node)->level;
2512 visible = gtk_ctree_is_viewable (ctree, node);
2513 /* get cell width if tree_column is auto resized */
2514 if (visible && clist->column[ctree->tree_column].auto_resize &&
2515 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2516 GTK_CLIST_GET_CLASS (clist)->cell_size_request
2517 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2519 /* unref/unset closed pixmap */
2520 if (GTK_CELL_PIXTEXT
2521 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2525 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2528 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2530 if (GTK_CELL_PIXTEXT
2531 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2535 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2537 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2541 /* set/ref opened pixmap */
2542 if (GTK_CTREE_ROW (node)->pixmap_opened)
2545 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2546 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
2548 if (GTK_CTREE_ROW (node)->mask_opened)
2550 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2551 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
2555 work = GTK_CTREE_ROW (node)->children;
2558 GList *list = (GList *)work;
2559 gint *cell_width = NULL;
2564 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2566 cell_width = g_new0 (gint, clist->columns);
2567 if (clist->column[ctree->tree_column].auto_resize)
2568 cell_width[ctree->tree_column] = requisition.width;
2572 /* search maximum cell widths of auto_resize columns */
2573 for (i = 0; i < clist->columns; i++)
2574 if (clist->column[i].auto_resize)
2576 GTK_CLIST_GET_CLASS (clist)->cell_size_request
2577 (clist, >K_CTREE_ROW (work)->row, i, &requisition);
2578 cell_width[i] = MAX (requisition.width, cell_width[i]);
2581 list = (GList *)work;
2582 work = GTK_CTREE_NODE_NEXT (work);
2589 list = (GList *)work;
2590 work = GTK_CTREE_NODE_NEXT (work);
2594 list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
2596 if (GTK_CTREE_NODE_NEXT (node))
2600 tmp_list = (GList *)GTK_CTREE_NODE_NEXT (node);
2601 tmp_list->prev = list;
2604 clist->row_list_end = list;
2606 list = (GList *)node;
2607 list->next = (GList *)(GTK_CTREE_ROW (node)->children);
2611 /* resize auto_resize columns if needed */
2612 for (i = 0; i < clist->columns; i++)
2613 if (clist->column[i].auto_resize &&
2614 cell_width[i] > clist->column[i].width)
2615 gtk_clist_set_column_width (clist, i, cell_width[i]);
2616 g_free (cell_width);
2618 /* update focus_row position */
2619 row = g_list_position (clist->row_list, (GList *)node);
2620 if (row < clist->focus_row)
2621 clist->focus_row += tmp;
2624 CLIST_REFRESH (clist);
2627 else if (visible && clist->column[ctree->tree_column].auto_resize)
2628 /* resize tree_column if needed */
2629 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2634 real_tree_collapse (GtkCTree *ctree,
2639 GtkRequisition requisition;
2643 g_return_if_fail (ctree != NULL);
2644 g_return_if_fail (GTK_IS_CTREE (ctree));
2646 if (!node || !GTK_CTREE_ROW (node)->expanded ||
2647 GTK_CTREE_ROW (node)->is_leaf)
2650 clist = GTK_CLIST (ctree);
2652 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
2654 GTK_CTREE_ROW (node)->expanded = FALSE;
2655 level = GTK_CTREE_ROW (node)->level;
2657 visible = gtk_ctree_is_viewable (ctree, node);
2658 /* get cell width if tree_column is auto resized */
2659 if (visible && clist->column[ctree->tree_column].auto_resize &&
2660 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2661 GTK_CLIST_GET_CLASS (clist)->cell_size_request
2662 (clist, >K_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
2664 /* unref/unset opened pixmap */
2665 if (GTK_CELL_PIXTEXT
2666 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
2670 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
2673 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
2675 if (GTK_CELL_PIXTEXT
2676 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
2680 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
2682 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
2686 /* set/ref closed pixmap */
2687 if (GTK_CTREE_ROW (node)->pixmap_closed)
2690 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap =
2691 gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_closed);
2693 if (GTK_CTREE_ROW (node)->mask_closed)
2695 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask =
2696 gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_closed);
2699 work = GTK_CTREE_ROW (node)->children;
2706 while (work && GTK_CTREE_ROW (work)->level > level)
2708 work = GTK_CTREE_NODE_NEXT (work);
2714 list = (GList *)node;
2715 list->next = (GList *)work;
2716 list = (GList *)GTK_CTREE_NODE_PREV (work);
2718 list = (GList *)work;
2719 list->prev = (GList *)node;
2723 list = (GList *)node;
2725 clist->row_list_end = (GList *)node;
2730 /* resize auto_resize columns if needed */
2731 auto_resize_columns (clist);
2733 row = g_list_position (clist->row_list, (GList *)node);
2734 if (row < clist->focus_row)
2735 clist->focus_row -= tmp;
2737 CLIST_REFRESH (clist);
2740 else if (visible && clist->column[ctree->tree_column].auto_resize &&
2741 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2742 /* resize tree_column if needed */
2743 column_auto_resize (clist, >K_CTREE_ROW (node)->row, ctree->tree_column,
2749 column_auto_resize (GtkCList *clist,
2750 GtkCListRow *clist_row,
2754 /* resize column if needed for auto_resize */
2755 GtkRequisition requisition;
2757 if (!clist->column[column].auto_resize ||
2758 GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2762 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
2763 column, &requisition);
2765 requisition.width = 0;
2767 if (requisition.width > clist->column[column].width)
2768 gtk_clist_set_column_width (clist, column, requisition.width);
2769 else if (requisition.width < old_width &&
2770 old_width == clist->column[column].width)
2775 /* run a "gtk_clist_optimal_column_width" but break, if
2776 * the column doesn't shrink */
2777 if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
2778 new_width = (clist->column[column].button->requisition.width -
2779 (CELL_SPACING + (2 * COLUMN_INSET)));
2783 for (list = clist->row_list; list; list = list->next)
2785 GTK_CLIST_GET_CLASS (clist)->cell_size_request
2786 (clist, GTK_CLIST_ROW (list), column, &requisition);
2787 new_width = MAX (new_width, requisition.width);
2788 if (new_width == clist->column[column].width)
2791 if (new_width < clist->column[column].width)
2792 gtk_clist_set_column_width (clist, column, new_width);
2797 auto_resize_columns (GtkCList *clist)
2801 if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2804 for (i = 0; i < clist->columns; i++)
2805 column_auto_resize (clist, NULL, i, clist->column[i].width);
2809 cell_size_request (GtkCList *clist,
2810 GtkCListRow *clist_row,
2812 GtkRequisition *requisition)
2817 PangoLayout *layout;
2818 PangoRectangle logical_rect;
2820 g_return_if_fail (clist != NULL);
2821 g_return_if_fail (GTK_IS_CTREE (clist));
2822 g_return_if_fail (requisition != NULL);
2824 ctree = GTK_CTREE (clist);
2826 layout = _gtk_clist_create_cell_layout (clist, clist_row, column);
2829 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2831 requisition->width = logical_rect.width;
2832 requisition->height = logical_rect.height;
2834 g_object_unref (G_OBJECT (layout));
2838 requisition->width = 0;
2839 requisition->height = 0;
2842 switch (clist_row->cell[column].type)
2844 case GTK_CELL_PIXTEXT:
2845 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
2847 gdk_window_get_size (GTK_CELL_PIXTEXT
2848 (clist_row->cell[column])->pixmap,
2850 width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
2855 requisition->width += width;
2856 requisition->height = MAX (requisition->height, height);
2858 if (column == ctree->tree_column)
2860 requisition->width += (ctree->tree_spacing + ctree->tree_indent *
2861 (((GtkCTreeRow *) clist_row)->level - 1));
2862 switch (ctree->expander_style)
2864 case GTK_CTREE_EXPANDER_NONE:
2866 case GTK_CTREE_EXPANDER_TRIANGLE:
2867 requisition->width += PM_SIZE + 3;
2869 case GTK_CTREE_EXPANDER_SQUARE:
2870 case GTK_CTREE_EXPANDER_CIRCULAR:
2871 requisition->width += PM_SIZE + 1;
2874 if (ctree->line_style == GTK_CTREE_LINES_TABBED)
2875 requisition->width += 3;
2878 case GTK_CELL_PIXMAP:
2879 gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
2881 requisition->width += width;
2882 requisition->height = MAX (requisition->height, height);
2885 requisition->width = 0;
2886 requisition->height = 0;
2890 requisition->width += clist_row->cell[column].horizontal;
2891 requisition->height += clist_row->cell[column].vertical;
2895 set_cell_contents (GtkCList *clist,
2896 GtkCListRow *clist_row,
2904 gboolean visible = FALSE;
2906 GtkRequisition requisition;
2908 g_return_if_fail (clist != NULL);
2909 g_return_if_fail (GTK_IS_CTREE (clist));
2910 g_return_if_fail (clist_row != NULL);
2912 ctree = GTK_CTREE (clist);
2914 if (clist->column[column].auto_resize &&
2915 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
2917 GtkCTreeNode *parent;
2919 parent = ((GtkCTreeRow *)clist_row)->parent;
2920 if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded &&
2921 gtk_ctree_is_viewable (ctree, parent)))
2924 GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
2925 column, &requisition);
2929 switch (clist_row->cell[column].type)
2931 case GTK_CELL_EMPTY:
2935 g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
2937 case GTK_CELL_PIXMAP:
2938 gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
2939 if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
2940 gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
2942 case GTK_CELL_PIXTEXT:
2943 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
2944 g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
2945 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap)
2948 (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
2949 if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
2951 (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
2954 case GTK_CELL_WIDGET:
2962 clist_row->cell[column].type = GTK_CELL_EMPTY;
2963 if (column == ctree->tree_column && type != GTK_CELL_EMPTY)
2964 type = GTK_CELL_PIXTEXT;
2971 clist_row->cell[column].type = GTK_CELL_TEXT;
2972 GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
2975 case GTK_CELL_PIXMAP:
2978 clist_row->cell[column].type = GTK_CELL_PIXMAP;
2979 GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
2980 /* We set the mask even if it is NULL */
2981 GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
2984 case GTK_CELL_PIXTEXT:
2985 if (column == ctree->tree_column)
2987 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
2988 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
2990 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
2992 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = NULL;
2995 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
2996 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3000 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
3001 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
3004 else if (text && pixmap)
3006 clist_row->cell[column].type = GTK_CELL_PIXTEXT;
3007 GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
3008 GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
3009 GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
3010 GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
3017 if (visible && clist->column[column].auto_resize &&
3018 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
3019 column_auto_resize (clist, clist_row, column, requisition.width);
3023 set_node_info (GtkCTree *ctree,
3027 GdkPixmap *pixmap_closed,
3028 GdkBitmap *mask_closed,
3029 GdkPixmap *pixmap_opened,
3030 GdkBitmap *mask_opened,
3034 if (GTK_CTREE_ROW (node)->pixmap_opened)
3036 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
3037 if (GTK_CTREE_ROW (node)->mask_opened)
3038 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
3040 if (GTK_CTREE_ROW (node)->pixmap_closed)
3042 gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
3043 if (GTK_CTREE_ROW (node)->mask_closed)
3044 gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
3047 GTK_CTREE_ROW (node)->pixmap_opened = NULL;
3048 GTK_CTREE_ROW (node)->mask_opened = NULL;
3049 GTK_CTREE_ROW (node)->pixmap_closed = NULL;
3050 GTK_CTREE_ROW (node)->mask_closed = NULL;
3054 GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
3056 GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
3060 GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
3062 GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
3065 GTK_CTREE_ROW (node)->is_leaf = is_leaf;
3066 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
3068 if (GTK_CTREE_ROW (node)->expanded)
3069 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3070 text, spacing, pixmap_opened, mask_opened);
3072 gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
3073 text, spacing, pixmap_closed, mask_closed);
3077 tree_delete (GtkCTree *ctree,
3081 tree_unselect (ctree, node, NULL);
3082 row_delete (ctree, GTK_CTREE_ROW (node));
3083 g_list_free_1 ((GList *)node);
3087 tree_delete_row (GtkCTree *ctree,
3091 row_delete (ctree, GTK_CTREE_ROW (node));
3092 g_list_free_1 ((GList *)node);
3096 tree_update_level (GtkCTree *ctree,
3103 if (GTK_CTREE_ROW (node)->parent)
3104 GTK_CTREE_ROW (node)->level =
3105 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
3107 GTK_CTREE_ROW (node)->level = 1;
3111 tree_select (GtkCTree *ctree,
3115 if (node && GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
3116 GTK_CTREE_ROW (node)->row.selectable)
3117 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
3122 tree_unselect (GtkCTree *ctree,
3126 if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
3127 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
3132 tree_expand (GtkCTree *ctree,
3136 if (node && !GTK_CTREE_ROW (node)->expanded)
3137 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3141 tree_collapse (GtkCTree *ctree,
3145 if (node && GTK_CTREE_ROW (node)->expanded)
3146 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3150 tree_collapse_to_depth (GtkCTree *ctree,
3154 if (node && GTK_CTREE_ROW (node)->level == depth)
3155 gtk_ctree_collapse_recursive (ctree, node);
3159 tree_toggle_expansion (GtkCTree *ctree,
3166 if (GTK_CTREE_ROW (node)->expanded)
3167 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
3169 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
3172 static GtkCTreeRow *
3173 row_new (GtkCTree *ctree)
3176 GtkCTreeRow *ctree_row;
3179 clist = GTK_CLIST (ctree);
3180 ctree_row = g_chunk_new (GtkCTreeRow, clist->row_mem_chunk);
3181 ctree_row->row.cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
3183 for (i = 0; i < clist->columns; i++)
3185 ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
3186 ctree_row->row.cell[i].vertical = 0;
3187 ctree_row->row.cell[i].horizontal = 0;
3188 ctree_row->row.cell[i].style = NULL;
3191 GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
3193 ctree_row->row.fg_set = FALSE;
3194 ctree_row->row.bg_set = FALSE;
3195 ctree_row->row.style = NULL;
3196 ctree_row->row.selectable = TRUE;
3197 ctree_row->row.state = GTK_STATE_NORMAL;
3198 ctree_row->row.data = NULL;
3199 ctree_row->row.destroy = NULL;
3201 ctree_row->level = 0;
3202 ctree_row->expanded = FALSE;
3203 ctree_row->parent = NULL;
3204 ctree_row->sibling = NULL;
3205 ctree_row->children = NULL;
3206 ctree_row->pixmap_closed = NULL;
3207 ctree_row->mask_closed = NULL;
3208 ctree_row->pixmap_opened = NULL;
3209 ctree_row->mask_opened = NULL;
3215 row_delete (GtkCTree *ctree,
3216 GtkCTreeRow *ctree_row)
3221 clist = GTK_CLIST (ctree);
3223 for (i = 0; i < clist->columns; i++)
3225 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
3226 (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
3227 if (ctree_row->row.cell[i].style)
3229 if (GTK_WIDGET_REALIZED (ctree))
3230 gtk_style_detach (ctree_row->row.cell[i].style);
3231 gtk_style_unref (ctree_row->row.cell[i].style);
3235 if (ctree_row->row.style)
3237 if (GTK_WIDGET_REALIZED (ctree))
3238 gtk_style_detach (ctree_row->row.style);
3239 gtk_style_unref (ctree_row->row.style);
3242 if (ctree_row->pixmap_closed)
3244 gdk_pixmap_unref (ctree_row->pixmap_closed);
3245 if (ctree_row->mask_closed)
3246 gdk_bitmap_unref (ctree_row->mask_closed);
3249 if (ctree_row->pixmap_opened)
3251 gdk_pixmap_unref (ctree_row->pixmap_opened);
3252 if (ctree_row->mask_opened)
3253 gdk_bitmap_unref (ctree_row->mask_opened);
3256 if (ctree_row->row.destroy)
3258 GtkDestroyNotify dnotify = ctree_row->row.destroy;
3259 gpointer ddata = ctree_row->row.data;
3261 ctree_row->row.destroy = NULL;
3262 ctree_row->row.data = NULL;
3267 g_mem_chunk_free (clist->cell_mem_chunk, ctree_row->row.cell);
3268 g_mem_chunk_free (clist->row_mem_chunk, ctree_row);
3272 real_select_row (GtkCList *clist,
3279 g_return_if_fail (clist != NULL);
3280 g_return_if_fail (GTK_IS_CTREE (clist));
3282 if ((node = g_list_nth (clist->row_list, row)) &&
3283 GTK_CTREE_ROW (node)->row.selectable)
3284 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],
3289 real_unselect_row (GtkCList *clist,
3296 g_return_if_fail (clist != NULL);
3297 g_return_if_fail (GTK_IS_CTREE (clist));
3299 if ((node = g_list_nth (clist->row_list, row)))
3300 gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],
3305 real_tree_select (GtkCTree *ctree,
3311 GtkCTreeNode *sel_row;
3312 gboolean node_selected;
3314 g_return_if_fail (ctree != NULL);
3315 g_return_if_fail (GTK_IS_CTREE (ctree));
3317 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3318 !GTK_CTREE_ROW (node)->row.selectable)
3321 clist = GTK_CLIST (ctree);
3323 switch (clist->selection_mode)
3325 case GTK_SELECTION_SINGLE:
3326 case GTK_SELECTION_BROWSE:
3328 node_selected = FALSE;
3329 list = clist->selection;
3333 sel_row = list->data;
3336 if (node == sel_row)
3337 node_selected = TRUE;
3339 gtk_signal_emit (GTK_OBJECT (ctree),
3340 ctree_signals[TREE_UNSELECT_ROW], sel_row, column);
3350 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
3352 if (!clist->selection)
3354 clist->selection = g_list_append (clist->selection, node);
3355 clist->selection_end = clist->selection;
3358 clist->selection_end = g_list_append (clist->selection_end, node)->next;
3360 tree_draw_node (ctree, node);
3364 real_tree_unselect (GtkCTree *ctree,
3370 g_return_if_fail (ctree != NULL);
3371 g_return_if_fail (GTK_IS_CTREE (ctree));
3373 if (!node || GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
3376 clist = GTK_CLIST (ctree);
3378 if (clist->selection_end && clist->selection_end->data == node)
3379 clist->selection_end = clist->selection_end->prev;
3381 clist->selection = g_list_remove (clist->selection, node);
3383 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
3385 tree_draw_node (ctree, node);
3389 select_row_recursive (GtkCTree *ctree,
3393 if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
3394 !GTK_CTREE_ROW (node)->row.selectable)
3397 GTK_CLIST (ctree)->undo_unselection =
3398 g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node);
3399 gtk_ctree_select (ctree, node);
3403 real_select_all (GtkCList *clist)
3408 g_return_if_fail (clist != NULL);
3409 g_return_if_fail (GTK_IS_CTREE (clist));
3411 ctree = GTK_CTREE (clist);
3413 switch (clist->selection_mode)
3415 case GTK_SELECTION_SINGLE:
3416 case GTK_SELECTION_BROWSE:
3419 case GTK_SELECTION_EXTENDED:
3421 gtk_clist_freeze (clist);
3423 g_list_free (clist->undo_selection);
3424 g_list_free (clist->undo_unselection);
3425 clist->undo_selection = NULL;
3426 clist->undo_unselection = NULL;
3428 clist->anchor_state = GTK_STATE_SELECTED;
3430 clist->drag_pos = -1;
3431 clist->undo_anchor = clist->focus_row;
3433 for (node = GTK_CTREE_NODE (clist->row_list); node;
3434 node = GTK_CTREE_NODE_NEXT (node))
3435 gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL);
3437 gtk_clist_thaw (clist);
3440 case GTK_SELECTION_MULTIPLE:
3441 gtk_ctree_select_recursive (ctree, NULL);
3451 real_unselect_all (GtkCList *clist)
3457 g_return_if_fail (clist != NULL);
3458 g_return_if_fail (GTK_IS_CTREE (clist));
3460 ctree = GTK_CTREE (clist);
3462 switch (clist->selection_mode)
3464 case GTK_SELECTION_BROWSE:
3465 if (clist->focus_row >= 0)
3469 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
3474 case GTK_SELECTION_EXTENDED:
3475 g_list_free (clist->undo_selection);
3476 g_list_free (clist->undo_unselection);
3477 clist->undo_selection = NULL;
3478 clist->undo_unselection = NULL;
3481 clist->drag_pos = -1;
3482 clist->undo_anchor = clist->focus_row;
3489 list = clist->selection;
3495 gtk_ctree_unselect (ctree, node);
3500 ctree_is_hot_spot (GtkCTree *ctree,
3506 GtkCTreeRow *tree_row;
3508 GtkCellPixText *cell;
3512 g_return_val_if_fail (ctree != NULL, FALSE);
3513 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
3514 g_return_val_if_fail (node != NULL, FALSE);
3516 clist = GTK_CLIST (ctree);
3518 if (!clist->column[ctree->tree_column].visible ||
3519 ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
3522 tree_row = GTK_CTREE_ROW (node);
3524 cell = GTK_CELL_PIXTEXT(tree_row->row.cell[ctree->tree_column]);
3526 yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
3527 (clist->row_height - 1) % 2);
3529 if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
3530 xl = (clist->column[ctree->tree_column].area.x +
3531 clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
3532 (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
3533 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3535 xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
3536 (tree_row->level - 1) * ctree->tree_indent +
3537 (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
3539 return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
3542 /***********************************************************
3543 ***********************************************************
3544 *** Public interface ***
3545 ***********************************************************
3546 ***********************************************************/
3549 /***********************************************************
3550 * Creation, insertion, deletion *
3551 ***********************************************************/
3554 gtk_ctree_constructor (GType type,
3555 guint n_construct_properties,
3556 GObjectConstructParam *construct_properties)
3558 GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
3559 n_construct_properties,
3560 construct_properties);
3566 gtk_ctree_new_with_titles (gint columns,
3572 g_return_val_if_fail (columns > 0, NULL);
3573 g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
3575 widget = gtk_widget_new (GTK_TYPE_CTREE,
3576 "n_columns", columns,
3577 "tree_column", tree_column,
3581 GtkCList *clist = GTK_CLIST (widget);
3584 for (i = 0; i < columns; i++)
3585 gtk_clist_set_column_title (clist, i, titles[i]);
3586 gtk_clist_column_titles_show (clist);
3593 gtk_ctree_new (gint columns,
3596 return gtk_ctree_new_with_titles (columns, tree_column, NULL);
3600 real_insert_row (GtkCList *clist,
3604 GtkCTreeNode *parent = NULL;
3605 GtkCTreeNode *sibling;
3608 g_return_val_if_fail (clist != NULL, -1);
3609 g_return_val_if_fail (GTK_IS_CTREE (clist), -1);
3611 sibling = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3613 parent = GTK_CTREE_ROW (sibling)->parent;
3615 node = gtk_ctree_insert_node (GTK_CTREE (clist), parent, sibling, text, 5,
3616 NULL, NULL, NULL, NULL, TRUE, FALSE);
3618 if (GTK_CLIST_AUTO_SORT (clist) || !sibling)
3619 return g_list_position (clist->row_list, (GList *) node);
3625 gtk_ctree_insert_node (GtkCTree *ctree,
3626 GtkCTreeNode *parent,
3627 GtkCTreeNode *sibling,
3630 GdkPixmap *pixmap_closed,
3631 GdkBitmap *mask_closed,
3632 GdkPixmap *pixmap_opened,
3633 GdkBitmap *mask_opened,
3638 GtkCTreeRow *new_row;
3643 g_return_val_if_fail (ctree != NULL, NULL);
3644 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3646 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3648 if (parent && GTK_CTREE_ROW (parent)->is_leaf)
3651 clist = GTK_CLIST (ctree);
3653 /* create the row */
3654 new_row = row_new (ctree);
3655 list = g_list_alloc ();
3656 list->data = new_row;
3657 node = GTK_CTREE_NODE (list);
3660 for (i = 0; i < clist->columns; i++)
3661 if (text[i] && i != ctree->tree_column)
3662 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
3663 (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
3665 set_node_info (ctree, node, text ?
3666 text[ctree->tree_column] : NULL, spacing, pixmap_closed,
3667 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
3669 /* sorted insertion */
3670 if (GTK_CLIST_AUTO_SORT (clist))
3673 sibling = GTK_CTREE_ROW (parent)->children;
3675 sibling = GTK_CTREE_NODE (clist->row_list);
3677 while (sibling && clist->compare
3678 (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
3679 sibling = GTK_CTREE_ROW (sibling)->sibling;
3682 gtk_ctree_link (ctree, node, parent, sibling, TRUE);
3684 if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
3685 gtk_ctree_is_viewable (ctree, node))
3687 for (i = 0; i < clist->columns; i++)
3688 if (clist->column[i].auto_resize)
3689 column_auto_resize (clist, &(new_row->row), i, 0);
3692 if (clist->rows == 1)
3694 clist->focus_row = 0;
3695 if (clist->selection_mode == GTK_SELECTION_BROWSE)
3696 gtk_ctree_select (ctree, node);
3700 CLIST_REFRESH (clist);
3706 gtk_ctree_insert_gnode (GtkCTree *ctree,
3707 GtkCTreeNode *parent,
3708 GtkCTreeNode *sibling,
3710 GtkCTreeGNodeFunc func,
3714 GtkCTreeNode *cnode = NULL;
3715 GtkCTreeNode *child = NULL;
3716 GtkCTreeNode *new_child;
3721 g_return_val_if_fail (ctree != NULL, NULL);
3722 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3723 g_return_val_if_fail (gnode != NULL, NULL);
3724 g_return_val_if_fail (func != NULL, NULL);
3726 g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
3728 clist = GTK_CLIST (ctree);
3731 depth = GTK_CTREE_ROW (parent)->level + 1;
3733 list = g_list_alloc ();
3734 list->data = row_new (ctree);
3735 cnode = GTK_CTREE_NODE (list);
3737 gtk_clist_freeze (clist);
3739 set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
3741 if (!func (ctree, depth, gnode, cnode, data))
3743 tree_delete_row (ctree, cnode, NULL);
3747 if (GTK_CLIST_AUTO_SORT (clist))
3750 sibling = GTK_CTREE_ROW (parent)->children;
3752 sibling = GTK_CTREE_NODE (clist->row_list);
3754 while (sibling && clist->compare
3755 (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
3756 sibling = GTK_CTREE_ROW (sibling)->sibling;
3759 gtk_ctree_link (ctree, cnode, parent, sibling, TRUE);
3761 for (work = g_node_last_child (gnode); work; work = work->prev)
3763 new_child = gtk_ctree_insert_gnode (ctree, cnode, child,
3769 gtk_clist_thaw (clist);
3775 gtk_ctree_export_to_gnode (GtkCTree *ctree,
3779 GtkCTreeGNodeFunc func,
3786 g_return_val_if_fail (ctree != NULL, NULL);
3787 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
3788 g_return_val_if_fail (node != NULL, NULL);
3789 g_return_val_if_fail (func != NULL, NULL);
3792 g_return_val_if_fail (parent != NULL, NULL);
3793 g_return_val_if_fail (sibling->parent == parent, NULL);
3796 gnode = g_node_new (NULL);
3797 depth = g_node_depth (parent) + 1;
3799 if (!func (ctree, depth, gnode, node, data))
3801 g_node_destroy (gnode);
3806 g_node_insert_before (parent, sibling, gnode);
3808 if (!GTK_CTREE_ROW (node)->is_leaf)
3810 GNode *new_sibling = NULL;
3812 for (work = GTK_CTREE_ROW (node)->children; work;
3813 work = GTK_CTREE_ROW (work)->sibling)
3814 new_sibling = gtk_ctree_export_to_gnode (ctree, gnode, new_sibling,
3817 g_node_reverse_children (gnode);
3824 real_remove_row (GtkCList *clist,
3829 g_return_if_fail (clist != NULL);
3830 g_return_if_fail (GTK_IS_CTREE (clist));
3832 node = GTK_CTREE_NODE (g_list_nth (clist->row_list, row));
3835 gtk_ctree_remove_node (GTK_CTREE (clist), node);
3839 gtk_ctree_remove_node (GtkCTree *ctree,
3844 g_return_if_fail (ctree != NULL);
3845 g_return_if_fail (GTK_IS_CTREE (ctree));
3847 clist = GTK_CLIST (ctree);
3849 gtk_clist_freeze (clist);
3855 visible = gtk_ctree_is_viewable (ctree, node);
3856 gtk_ctree_unlink (ctree, node, TRUE);
3857 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
3859 if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
3860 clist->focus_row >= 0)
3861 gtk_clist_select_row (clist, clist->focus_row, -1);
3863 auto_resize_columns (clist);
3866 gtk_clist_clear (clist);
3868 gtk_clist_thaw (clist);
3872 real_clear (GtkCList *clist)
3878 g_return_if_fail (clist != NULL);
3879 g_return_if_fail (GTK_IS_CTREE (clist));
3881 ctree = GTK_CTREE (clist);
3883 /* remove all rows */
3884 work = GTK_CTREE_NODE (clist->row_list);
3885 clist->row_list = NULL;
3886 clist->row_list_end = NULL;
3888 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
3892 work = GTK_CTREE_ROW (work)->sibling;
3893 gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row),
3896 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
3898 parent_class->clear (clist);
3902 /***********************************************************
3903 * Generic recursive functions, querying / finding tree *
3905 ***********************************************************/
3909 gtk_ctree_post_recursive (GtkCTree *ctree,
3917 g_return_if_fail (ctree != NULL);
3918 g_return_if_fail (GTK_IS_CTREE (ctree));
3919 g_return_if_fail (func != NULL);
3922 work = GTK_CTREE_ROW (node)->children;
3924 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3928 tmp = GTK_CTREE_ROW (work)->sibling;
3929 gtk_ctree_post_recursive (ctree, work, func, data);
3934 func (ctree, node, data);
3938 gtk_ctree_post_recursive_to_depth (GtkCTree *ctree,
3947 g_return_if_fail (ctree != NULL);
3948 g_return_if_fail (GTK_IS_CTREE (ctree));
3949 g_return_if_fail (func != NULL);
3953 gtk_ctree_post_recursive (ctree, node, func, data);
3958 work = GTK_CTREE_ROW (node)->children;
3960 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3962 if (work && GTK_CTREE_ROW (work)->level <= depth)
3966 tmp = GTK_CTREE_ROW (work)->sibling;
3967 gtk_ctree_post_recursive_to_depth (ctree, work, depth, func, data);
3972 if (node && GTK_CTREE_ROW (node)->level <= depth)
3973 func (ctree, node, data);
3977 gtk_ctree_pre_recursive (GtkCTree *ctree,
3985 g_return_if_fail (ctree != NULL);
3986 g_return_if_fail (GTK_IS_CTREE (ctree));
3987 g_return_if_fail (func != NULL);
3991 work = GTK_CTREE_ROW (node)->children;
3992 func (ctree, node, data);
3995 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
3999 tmp = GTK_CTREE_ROW (work)->sibling;
4000 gtk_ctree_pre_recursive (ctree, work, func, data);
4006 gtk_ctree_pre_recursive_to_depth (GtkCTree *ctree,
4015 g_return_if_fail (ctree != NULL);
4016 g_return_if_fail (GTK_IS_CTREE (ctree));
4017 g_return_if_fail (func != NULL);
4021 gtk_ctree_pre_recursive (ctree, node, func, data);
4027 work = GTK_CTREE_ROW (node)->children;
4028 if (GTK_CTREE_ROW (node)->level <= depth)
4029 func (ctree, node, data);
4032 work = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4034 if (work && GTK_CTREE_ROW (work)->level <= depth)
4038 tmp = GTK_CTREE_ROW (work)->sibling;
4039 gtk_ctree_pre_recursive_to_depth (ctree, work, depth, func, data);
4046 gtk_ctree_is_viewable (GtkCTree *ctree,
4051 g_return_val_if_fail (ctree != NULL, FALSE);
4052 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4053 g_return_val_if_fail (node != NULL, FALSE);
4055 work = GTK_CTREE_ROW (node);
4057 while (work->parent && GTK_CTREE_ROW (work->parent)->expanded)
4058 work = GTK_CTREE_ROW (work->parent);
4067 gtk_ctree_last (GtkCTree *ctree,
4070 g_return_val_if_fail (ctree != NULL, NULL);
4071 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4076 while (GTK_CTREE_ROW (node)->sibling)
4077 node = GTK_CTREE_ROW (node)->sibling;
4079 if (GTK_CTREE_ROW (node)->children)
4080 return gtk_ctree_last (ctree, GTK_CTREE_ROW (node)->children);
4086 gtk_ctree_find_node_ptr (GtkCTree *ctree,
4087 GtkCTreeRow *ctree_row)
4091 g_return_val_if_fail (ctree != NULL, FALSE);
4092 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4093 g_return_val_if_fail (ctree_row != NULL, FALSE);
4095 if (ctree_row->parent)
4096 node = GTK_CTREE_ROW(ctree_row->parent)->children;
4098 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4100 while (GTK_CTREE_ROW (node) != ctree_row)
4101 node = GTK_CTREE_ROW (node)->sibling;
4107 gtk_ctree_node_nth (GtkCTree *ctree,
4110 g_return_val_if_fail (ctree != NULL, NULL);
4111 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4113 if ((row < 0) || (row >= GTK_CLIST(ctree)->rows))
4116 return GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row));
4120 gtk_ctree_find (GtkCTree *ctree,
4122 GtkCTreeNode *child)
4128 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4134 if (GTK_CTREE_ROW (node)->children)
4136 if (gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child))
4139 node = GTK_CTREE_ROW (node)->sibling;
4145 gtk_ctree_is_ancestor (GtkCTree *ctree,
4147 GtkCTreeNode *child)
4149 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4150 g_return_val_if_fail (node != NULL, FALSE);
4152 if (GTK_CTREE_ROW (node)->children)
4153 return gtk_ctree_find (ctree, GTK_CTREE_ROW (node)->children, child);
4159 gtk_ctree_find_by_row_data (GtkCTree *ctree,
4166 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4170 if (GTK_CTREE_ROW (node)->row.data == data)
4172 if (GTK_CTREE_ROW (node)->children &&
4173 (work = gtk_ctree_find_by_row_data
4174 (ctree, GTK_CTREE_ROW (node)->children, data)))
4176 node = GTK_CTREE_ROW (node)->sibling;
4182 gtk_ctree_find_all_by_row_data (GtkCTree *ctree,
4188 g_return_val_if_fail (ctree != NULL, NULL);
4189 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4191 /* if node == NULL then look in the whole tree */
4193 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4197 if (GTK_CTREE_ROW (node)->row.data == data)
4198 list = g_list_append (list, node);
4200 if (GTK_CTREE_ROW (node)->children)
4204 sub_list = gtk_ctree_find_all_by_row_data (ctree,
4208 list = g_list_concat (list, sub_list);
4210 node = GTK_CTREE_ROW (node)->sibling;
4216 gtk_ctree_find_by_row_data_custom (GtkCTree *ctree,
4223 g_return_val_if_fail (func != NULL, NULL);
4226 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4230 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4232 if (GTK_CTREE_ROW (node)->children &&
4233 (work = gtk_ctree_find_by_row_data_custom
4234 (ctree, GTK_CTREE_ROW (node)->children, data, func)))
4236 node = GTK_CTREE_ROW (node)->sibling;
4242 gtk_ctree_find_all_by_row_data_custom (GtkCTree *ctree,
4249 g_return_val_if_fail (ctree != NULL, NULL);
4250 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
4251 g_return_val_if_fail (func != NULL, NULL);
4253 /* if node == NULL then look in the whole tree */
4255 node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
4259 if (!func (GTK_CTREE_ROW (node)->row.data, data))
4260 list = g_list_append (list, node);
4262 if (GTK_CTREE_ROW (node)->children)
4266 sub_list = gtk_ctree_find_all_by_row_data_custom (ctree,
4271 list = g_list_concat (list, sub_list);
4273 node = GTK_CTREE_ROW (node)->sibling;
4279 gtk_ctree_is_hot_spot (GtkCTree *ctree,
4287 g_return_val_if_fail (ctree != NULL, FALSE);
4288 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
4290 if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
4291 if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
4292 return ctree_is_hot_spot (ctree, node, row, x, y);
4298 /***********************************************************
4299 * Tree signals : move, expand, collapse, (un)select *
4300 ***********************************************************/
4304 gtk_ctree_move (GtkCTree *ctree,
4306 GtkCTreeNode *new_parent,
4307 GtkCTreeNode *new_sibling)
4309 g_return_if_fail (ctree != NULL);
4310 g_return_if_fail (GTK_IS_CTREE (ctree));
4311 g_return_if_fail (node != NULL);
4313 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], node,
4314 new_parent, new_sibling);
4318 gtk_ctree_expand (GtkCTree *ctree,
4321 g_return_if_fail (ctree != NULL);
4322 g_return_if_fail (GTK_IS_CTREE (ctree));
4323 g_return_if_fail (node != NULL);
4325 if (GTK_CTREE_ROW (node)->is_leaf)
4328 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node);
4332 gtk_ctree_expand_recursive (GtkCTree *ctree,
4336 gboolean thaw = FALSE;
4338 g_return_if_fail (ctree != NULL);
4339 g_return_if_fail (GTK_IS_CTREE (ctree));
4341 clist = GTK_CLIST (ctree);
4343 if (node && GTK_CTREE_ROW (node)->is_leaf)
4346 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4348 gtk_clist_freeze (clist);
4352 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_expand), NULL);
4355 gtk_clist_thaw (clist);
4359 gtk_ctree_expand_to_depth (GtkCTree *ctree,
4364 gboolean thaw = FALSE;
4366 g_return_if_fail (ctree != NULL);
4367 g_return_if_fail (GTK_IS_CTREE (ctree));
4369 clist = GTK_CLIST (ctree);
4371 if (node && GTK_CTREE_ROW (node)->is_leaf)
4374 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4376 gtk_clist_freeze (clist);
4380 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4381 GTK_CTREE_FUNC (tree_expand), NULL);
4384 gtk_clist_thaw (clist);
4388 gtk_ctree_collapse (GtkCTree *ctree,
4391 g_return_if_fail (ctree != NULL);
4392 g_return_if_fail (GTK_IS_CTREE (ctree));
4393 g_return_if_fail (node != NULL);
4395 if (GTK_CTREE_ROW (node)->is_leaf)
4398 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node);
4402 gtk_ctree_collapse_recursive (GtkCTree *ctree,
4406 gboolean thaw = FALSE;
4409 g_return_if_fail (ctree != NULL);
4410 g_return_if_fail (GTK_IS_CTREE (ctree));
4412 if (node && GTK_CTREE_ROW (node)->is_leaf)
4415 clist = GTK_CLIST (ctree);
4417 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4419 gtk_clist_freeze (clist);
4423 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4424 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
4425 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4426 for (i = 0; i < clist->columns; i++)
4427 if (clist->column[i].auto_resize)
4428 gtk_clist_set_column_width (clist, i,
4429 gtk_clist_optimal_column_width (clist, i));
4432 gtk_clist_thaw (clist);
4436 gtk_ctree_collapse_to_depth (GtkCTree *ctree,
4441 gboolean thaw = FALSE;
4444 g_return_if_fail (ctree != NULL);
4445 g_return_if_fail (GTK_IS_CTREE (ctree));
4447 if (node && GTK_CTREE_ROW (node)->is_leaf)
4450 clist = GTK_CLIST (ctree);
4452 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4454 gtk_clist_freeze (clist);
4458 GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4459 gtk_ctree_post_recursive_to_depth (ctree, node, depth,
4460 GTK_CTREE_FUNC (tree_collapse_to_depth),
4461 GINT_TO_POINTER (depth));
4462 GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
4463 for (i = 0; i < clist->columns; i++)
4464 if (clist->column[i].auto_resize)
4465 gtk_clist_set_column_width (clist, i,
4466 gtk_clist_optimal_column_width (clist, i));
4469 gtk_clist_thaw (clist);
4473 gtk_ctree_toggle_expansion (GtkCTree *ctree,
4476 g_return_if_fail (ctree != NULL);
4477 g_return_if_fail (GTK_IS_CTREE (ctree));
4478 g_return_if_fail (node != NULL);
4480 if (GTK_CTREE_ROW (node)->is_leaf)
4483 tree_toggle_expansion (ctree, node, NULL);
4487 gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree,
4491 gboolean thaw = FALSE;
4493 g_return_if_fail (ctree != NULL);
4494 g_return_if_fail (GTK_IS_CTREE (ctree));
4496 if (node && GTK_CTREE_ROW (node)->is_leaf)
4499 clist = GTK_CLIST (ctree);
4501 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4503 gtk_clist_freeze (clist);
4507 gtk_ctree_post_recursive (ctree, node,
4508 GTK_CTREE_FUNC (tree_toggle_expansion), NULL);
4511 gtk_clist_thaw (clist);
4515 gtk_ctree_select (GtkCTree *ctree,
4518 g_return_if_fail (ctree != NULL);
4519 g_return_if_fail (GTK_IS_CTREE (ctree));
4520 g_return_if_fail (node != NULL);
4522 if (GTK_CTREE_ROW (node)->row.selectable)
4523 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW],
4528 gtk_ctree_unselect (GtkCTree *ctree,
4531 g_return_if_fail (ctree != NULL);
4532 g_return_if_fail (GTK_IS_CTREE (ctree));
4533 g_return_if_fail (node != NULL);
4535 gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW],
4540 gtk_ctree_select_recursive (GtkCTree *ctree,
4543 gtk_ctree_real_select_recursive (ctree, node, TRUE);
4547 gtk_ctree_unselect_recursive (GtkCTree *ctree,
4550 gtk_ctree_real_select_recursive (ctree, node, FALSE);
4554 gtk_ctree_real_select_recursive (GtkCTree *ctree,
4559 gboolean thaw = FALSE;
4561 g_return_if_fail (ctree != NULL);
4562 g_return_if_fail (GTK_IS_CTREE (ctree));
4564 clist = GTK_CLIST (ctree);
4567 (clist->selection_mode == GTK_SELECTION_BROWSE ||
4568 clist->selection_mode == GTK_SELECTION_SINGLE)) ||
4569 (!state && clist->selection_mode == GTK_SELECTION_BROWSE))
4572 if (CLIST_UNFROZEN (clist) && (!node || gtk_ctree_is_viewable (ctree, node)))
4574 gtk_clist_freeze (clist);
4578 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
4580 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
4582 g_list_free (clist->undo_selection);
4583 g_list_free (clist->undo_unselection);
4584 clist->undo_selection = NULL;
4585 clist->undo_unselection = NULL;
4589 gtk_ctree_post_recursive (ctree, node,
4590 GTK_CTREE_FUNC (tree_select), NULL);
4592 gtk_ctree_post_recursive (ctree, node,
4593 GTK_CTREE_FUNC (tree_unselect), NULL);
4596 gtk_clist_thaw (clist);
4600 /***********************************************************
4601 * Analogons of GtkCList functions *
4602 ***********************************************************/
4606 gtk_ctree_node_set_text (GtkCTree *ctree,
4613 g_return_if_fail (ctree != NULL);
4614 g_return_if_fail (GTK_IS_CTREE (ctree));
4615 g_return_if_fail (node != NULL);
4617 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4620 clist = GTK_CLIST (ctree);
4622 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
4623 (clist, &(GTK_CTREE_ROW(node)->row), column, GTK_CELL_TEXT,
4624 text, 0, NULL, NULL);
4626 tree_draw_node (ctree, node);
4630 gtk_ctree_node_set_pixmap (GtkCTree *ctree,
4638 g_return_if_fail (ctree != NULL);
4639 g_return_if_fail (GTK_IS_CTREE (ctree));
4640 g_return_if_fail (node != NULL);
4641 g_return_if_fail (pixmap != NULL);
4643 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4646 gdk_pixmap_ref (pixmap);
4648 gdk_pixmap_ref (mask);
4650 clist = GTK_CLIST (ctree);
4652 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
4653 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXMAP,
4654 NULL, 0, pixmap, mask);
4656 tree_draw_node (ctree, node);
4660 gtk_ctree_node_set_pixtext (GtkCTree *ctree,
4670 g_return_if_fail (ctree != NULL);
4671 g_return_if_fail (GTK_IS_CTREE (ctree));
4672 g_return_if_fail (node != NULL);
4673 if (column != ctree->tree_column)
4674 g_return_if_fail (pixmap != NULL);
4675 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4678 clist = GTK_CLIST (ctree);
4682 gdk_pixmap_ref (pixmap);
4684 gdk_pixmap_ref (mask);
4687 GTK_CLIST_GET_CLASS (clist)->set_cell_contents
4688 (clist, &(GTK_CTREE_ROW (node)->row), column, GTK_CELL_PIXTEXT,
4689 text, spacing, pixmap, mask);
4691 tree_draw_node (ctree, node);
4695 gtk_ctree_set_node_info (GtkCTree *ctree,
4699 GdkPixmap *pixmap_closed,
4700 GdkBitmap *mask_closed,
4701 GdkPixmap *pixmap_opened,
4702 GdkBitmap *mask_opened,
4707 gboolean old_expanded;
4709 g_return_if_fail (ctree != NULL);
4710 g_return_if_fail (GTK_IS_CTREE (ctree));
4711 g_return_if_fail (node != NULL);
4713 old_leaf = GTK_CTREE_ROW (node)->is_leaf;
4714 old_expanded = GTK_CTREE_ROW (node)->expanded;
4716 if (is_leaf && GTK_CTREE_ROW (node)->children)
4721 work = GTK_CTREE_ROW (node)->children;
4725 work = GTK_CTREE_ROW(work)->sibling;
4726 gtk_ctree_remove_node (ctree, ptr);
4730 set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
4731 pixmap_opened, mask_opened, is_leaf, expanded);
4733 if (!is_leaf && !old_leaf)
4735 GTK_CTREE_ROW (node)->expanded = old_expanded;
4736 if (expanded && !old_expanded)
4737 gtk_ctree_expand (ctree, node);
4738 else if (!expanded && old_expanded)
4739 gtk_ctree_collapse (ctree, node);
4742 GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
4744 tree_draw_node (ctree, node);
4748 gtk_ctree_node_set_shift (GtkCTree *ctree,
4755 GtkRequisition requisition;
4756 gboolean visible = FALSE;
4758 g_return_if_fail (ctree != NULL);
4759 g_return_if_fail (GTK_IS_CTREE (ctree));
4760 g_return_if_fail (node != NULL);
4762 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4765 clist = GTK_CLIST (ctree);
4767 if (clist->column[column].auto_resize &&
4768 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
4770 visible = gtk_ctree_is_viewable (ctree, node);
4772 GTK_CLIST_GET_CLASS (clist)->cell_size_request
4773 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
4776 GTK_CTREE_ROW (node)->row.cell[column].vertical = vertical;
4777 GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
4780 column_auto_resize (clist, >K_CTREE_ROW (node)->row,
4781 column, requisition.width);
4783 tree_draw_node (ctree, node);
4787 remove_grab (GtkCList *clist)
4789 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
4791 gtk_grab_remove (GTK_WIDGET (clist));
4792 gdk_pointer_ungrab (GDK_CURRENT_TIME);
4797 gtk_timeout_remove (clist->htimer);
4803 gtk_timeout_remove (clist->vtimer);
4809 gtk_ctree_node_set_selectable (GtkCTree *ctree,
4811 gboolean selectable)
4813 g_return_if_fail (ctree != NULL);
4814 g_return_if_fail (GTK_IS_CTREE (ctree));
4815 g_return_if_fail (node != NULL);
4817 if (selectable == GTK_CTREE_ROW (node)->row.selectable)
4820 GTK_CTREE_ROW (node)->row.selectable = selectable;
4822 if (!selectable && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
4826 clist = GTK_CLIST (ctree);
4828 if (clist->anchor >= 0 &&
4829 clist->selection_mode == GTK_SELECTION_EXTENDED)
4831 clist->drag_button = 0;
4832 remove_grab (clist);
4834 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
4836 gtk_ctree_unselect (ctree, node);
4841 gtk_ctree_node_get_selectable (GtkCTree *ctree,
4844 g_return_val_if_fail (node != NULL, FALSE);
4846 return GTK_CTREE_ROW (node)->row.selectable;
4850 gtk_ctree_node_get_cell_type (GtkCTree *ctree,
4854 g_return_val_if_fail (ctree != NULL, -1);
4855 g_return_val_if_fail (GTK_IS_CTREE (ctree), -1);
4856 g_return_val_if_fail (node != NULL, -1);
4858 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4861 return GTK_CTREE_ROW (node)->row.cell[column].type;
4865 gtk_ctree_node_get_text (GtkCTree *ctree,
4870 g_return_val_if_fail (ctree != NULL, 0);
4871 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4872 g_return_val_if_fail (node != NULL, 0);
4874 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4877 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_TEXT)
4881 *text = GTK_CELL_TEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4887 gtk_ctree_node_get_pixmap (GtkCTree *ctree,
4893 g_return_val_if_fail (ctree != NULL, 0);
4894 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4895 g_return_val_if_fail (node != NULL, 0);
4897 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4900 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXMAP)
4904 *pixmap = GTK_CELL_PIXMAP (GTK_CTREE_ROW(node)->row.cell[column])->pixmap;
4906 *mask = GTK_CELL_PIXMAP (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4912 gtk_ctree_node_get_pixtext (GtkCTree *ctree,
4920 g_return_val_if_fail (ctree != NULL, 0);
4921 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4922 g_return_val_if_fail (node != NULL, 0);
4924 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
4927 if (GTK_CTREE_ROW (node)->row.cell[column].type != GTK_CELL_PIXTEXT)
4931 *text = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->text;
4933 *spacing = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4934 (node)->row.cell[column])->spacing;
4936 *pixmap = GTK_CELL_PIXTEXT (GTK_CTREE_ROW
4937 (node)->row.cell[column])->pixmap;
4939 *mask = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (node)->row.cell[column])->mask;
4945 gtk_ctree_get_node_info (GtkCTree *ctree,
4949 GdkPixmap **pixmap_closed,
4950 GdkBitmap **mask_closed,
4951 GdkPixmap **pixmap_opened,
4952 GdkBitmap **mask_opened,
4956 g_return_val_if_fail (ctree != NULL, 0);
4957 g_return_val_if_fail (GTK_IS_CTREE (ctree), 0);
4958 g_return_val_if_fail (node != NULL, 0);
4961 *text = GTK_CELL_PIXTEXT
4962 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->text;
4964 *spacing = GTK_CELL_PIXTEXT
4965 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
4967 *pixmap_closed = GTK_CTREE_ROW (node)->pixmap_closed;
4969 *mask_closed = GTK_CTREE_ROW (node)->mask_closed;
4971 *pixmap_opened = GTK_CTREE_ROW (node)->pixmap_opened;
4973 *mask_opened = GTK_CTREE_ROW (node)->mask_opened;
4975 *is_leaf = GTK_CTREE_ROW (node)->is_leaf;
4977 *expanded = GTK_CTREE_ROW (node)->expanded;
4983 gtk_ctree_node_set_cell_style (GtkCTree *ctree,
4989 GtkRequisition requisition;
4990 gboolean visible = FALSE;
4992 g_return_if_fail (ctree != NULL);
4993 g_return_if_fail (GTK_IS_CTREE (ctree));
4994 g_return_if_fail (node != NULL);
4996 clist = GTK_CLIST (ctree);
4998 if (column < 0 || column >= clist->columns)
5001 if (GTK_CTREE_ROW (node)->row.cell[column].style == style)
5004 if (clist->column[column].auto_resize &&
5005 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5007 visible = gtk_ctree_is_viewable (ctree, node);
5009 GTK_CLIST_GET_CLASS (clist)->cell_size_request
5010 (clist, >K_CTREE_ROW (node)->row, column, &requisition);
5013 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5015 if (GTK_WIDGET_REALIZED (ctree))
5016 gtk_style_detach (GTK_CTREE_ROW (node)->row.cell[column].style);
5017 gtk_style_unref (GTK_CTREE_ROW (node)->row.cell[column].style);
5020 GTK_CTREE_ROW (node)->row.cell[column].style = style;
5022 if (GTK_CTREE_ROW (node)->row.cell[column].style)
5024 gtk_style_ref (GTK_CTREE_ROW (node)->row.cell[column].style);
5026 if (GTK_WIDGET_REALIZED (ctree))
5027 GTK_CTREE_ROW (node)->row.cell[column].style =
5028 gtk_style_attach (GTK_CTREE_ROW (node)->row.cell[column].style,
5029 clist->clist_window);
5033 column_auto_resize (clist, >K_CTREE_ROW (node)->row, column,
5036 tree_draw_node (ctree, node);
5040 gtk_ctree_node_get_cell_style (GtkCTree *ctree,
5044 g_return_val_if_fail (ctree != NULL, NULL);
5045 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5046 g_return_val_if_fail (node != NULL, NULL);
5048 if (column < 0 || column >= GTK_CLIST (ctree)->columns)
5051 return GTK_CTREE_ROW (node)->row.cell[column].style;
5055 gtk_ctree_node_set_row_style (GtkCTree *ctree,
5060 GtkRequisition requisition;
5062 gint *old_width = NULL;
5065 g_return_if_fail (ctree != NULL);
5066 g_return_if_fail (GTK_IS_CTREE (ctree));
5067 g_return_if_fail (node != NULL);
5069 clist = GTK_CLIST (ctree);
5071 if (GTK_CTREE_ROW (node)->row.style == style)
5074 visible = gtk_ctree_is_viewable (ctree, node);
5075 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5077 old_width = g_new (gint, clist->columns);
5078 for (i = 0; i < clist->columns; i++)
5079 if (clist->column[i].auto_resize)
5081 GTK_CLIST_GET_CLASS (clist)->cell_size_request
5082 (clist, >K_CTREE_ROW (node)->row, i, &requisition);
5083 old_width[i] = requisition.width;
5087 if (GTK_CTREE_ROW (node)->row.style)
5089 if (GTK_WIDGET_REALIZED (ctree))
5090 gtk_style_detach (GTK_CTREE_ROW (node)->row.style);
5091 gtk_style_unref (GTK_CTREE_ROW (node)->row.style);
5094 GTK_CTREE_ROW (node)->row.style = style;
5096 if (GTK_CTREE_ROW (node)->row.style)
5098 gtk_style_ref (GTK_CTREE_ROW (node)->row.style);
5100 if (GTK_WIDGET_REALIZED (ctree))
5101 GTK_CTREE_ROW (node)->row.style =
5102 gtk_style_attach (GTK_CTREE_ROW (node)->row.style,
5103 clist->clist_window);
5106 if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5108 for (i = 0; i < clist->columns; i++)
5109 if (clist->column[i].auto_resize)
5110 column_auto_resize (clist, >K_CTREE_ROW (node)->row, i,
5114 tree_draw_node (ctree, node);
5118 gtk_ctree_node_get_row_style (GtkCTree *ctree,
5121 g_return_val_if_fail (ctree != NULL, NULL);
5122 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5123 g_return_val_if_fail (node != NULL, NULL);
5125 return GTK_CTREE_ROW (node)->row.style;
5129 gtk_ctree_node_set_foreground (GtkCTree *ctree,
5133 g_return_if_fail (ctree != NULL);
5134 g_return_if_fail (GTK_IS_CTREE (ctree));
5135 g_return_if_fail (node != NULL);
5139 GTK_CTREE_ROW (node)->row.foreground = *color;
5140 GTK_CTREE_ROW (node)->row.fg_set = TRUE;
5141 if (GTK_WIDGET_REALIZED (ctree))
5142 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5143 >K_CTREE_ROW (node)->row.foreground);
5146 GTK_CTREE_ROW (node)->row.fg_set = FALSE;
5148 tree_draw_node (ctree, node);
5152 gtk_ctree_node_set_background (GtkCTree *ctree,
5156 g_return_if_fail (ctree != NULL);
5157 g_return_if_fail (GTK_IS_CTREE (ctree));
5158 g_return_if_fail (node != NULL);
5162 GTK_CTREE_ROW (node)->row.background = *color;
5163 GTK_CTREE_ROW (node)->row.bg_set = TRUE;
5164 if (GTK_WIDGET_REALIZED (ctree))
5165 gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
5166 >K_CTREE_ROW (node)->row.background);
5169 GTK_CTREE_ROW (node)->row.bg_set = FALSE;
5171 tree_draw_node (ctree, node);
5175 gtk_ctree_node_set_row_data (GtkCTree *ctree,
5179 gtk_ctree_node_set_row_data_full (ctree, node, data, NULL);
5183 gtk_ctree_node_set_row_data_full (GtkCTree *ctree,
5186 GtkDestroyNotify destroy)
5188 GtkDestroyNotify dnotify;
5191 g_return_if_fail (ctree != NULL);
5192 g_return_if_fail (GTK_IS_CTREE (ctree));
5193 g_return_if_fail (node != NULL);
5195 dnotify = GTK_CTREE_ROW (node)->row.destroy;
5196 ddata = GTK_CTREE_ROW (node)->row.data;
5198 GTK_CTREE_ROW (node)->row.data = data;
5199 GTK_CTREE_ROW (node)->row.destroy = destroy;
5206 gtk_ctree_node_get_row_data (GtkCTree *ctree,
5209 g_return_val_if_fail (ctree != NULL, NULL);
5210 g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
5212 return node ? GTK_CTREE_ROW (node)->row.data : NULL;
5216 gtk_ctree_node_moveto (GtkCTree *ctree,
5225 g_return_if_fail (ctree != NULL);
5226 g_return_if_fail (GTK_IS_CTREE (ctree));
5228 clist = GTK_CLIST (ctree);
5230 while (node && !gtk_ctree_is_viewable (ctree, node))
5231 node = GTK_CTREE_ROW (node)->parent;
5234 row = g_list_position (clist->row_list, (GList *)node);
5236 gtk_clist_moveto (clist, row, column, row_align, col_align);
5239 GtkVisibility gtk_ctree_node_is_visible (GtkCTree *ctree,
5244 g_return_val_if_fail (ctree != NULL, 0);
5245 g_return_val_if_fail (node != NULL, 0);
5247 row = g_list_position (GTK_CLIST (ctree)->row_list, (GList*) node);
5248 return gtk_clist_row_is_visible (GTK_CLIST (ctree), row);
5252 /***********************************************************
5253 * GtkCTree specific functions *
5254 ***********************************************************/
5257 gtk_ctree_set_indent (GtkCTree *ctree,
5262 g_return_if_fail (ctree != NULL);
5263 g_return_if_fail (GTK_IS_CTREE (ctree));
5264 g_return_if_fail (indent >= 0);
5266 if (indent == ctree->tree_indent)
5269 clist = GTK_CLIST (ctree);
5270 ctree->tree_indent = indent;
5272 if (clist->column[ctree->tree_column].auto_resize &&
5273 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5274 gtk_clist_set_column_width
5275 (clist, ctree->tree_column,
5276 gtk_clist_optimal_column_width (clist, ctree->tree_column));
5278 CLIST_REFRESH (ctree);
5282 gtk_ctree_set_spacing (GtkCTree *ctree,
5288 g_return_if_fail (ctree != NULL);
5289 g_return_if_fail (GTK_IS_CTREE (ctree));
5290 g_return_if_fail (spacing >= 0);
5292 if (spacing == ctree->tree_spacing)
5295 clist = GTK_CLIST (ctree);
5297 old_spacing = ctree->tree_spacing;
5298 ctree->tree_spacing = spacing;
5300 if (clist->column[ctree->tree_column].auto_resize &&
5301 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5302 gtk_clist_set_column_width (clist, ctree->tree_column,
5303 clist->column[ctree->tree_column].width +
5304 spacing - old_spacing);
5306 CLIST_REFRESH (ctree);
5310 gtk_ctree_set_show_stub (GtkCTree *ctree,
5313 g_return_if_fail (ctree != NULL);
5314 g_return_if_fail (GTK_IS_CTREE (ctree));
5316 show_stub = show_stub != FALSE;
5318 if (show_stub != ctree->show_stub)
5322 clist = GTK_CLIST (ctree);
5323 ctree->show_stub = show_stub;
5325 if (CLIST_UNFROZEN (clist) && clist->rows &&
5326 gtk_clist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
5327 GTK_CLIST_GET_CLASS (clist)->draw_row
5328 (clist, NULL, 0, GTK_CLIST_ROW (clist->row_list));
5333 gtk_ctree_set_line_style (GtkCTree *ctree,
5334 GtkCTreeLineStyle line_style)
5337 GtkCTreeLineStyle old_style;
5339 g_return_if_fail (ctree != NULL);
5340 g_return_if_fail (GTK_IS_CTREE (ctree));
5342 if (line_style == ctree->line_style)
5345 clist = GTK_CLIST (ctree);
5347 old_style = ctree->line_style;
5348 ctree->line_style = line_style;
5350 if (clist->column[ctree->tree_column].auto_resize &&
5351 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5353 if (old_style == GTK_CTREE_LINES_TABBED)
5354 gtk_clist_set_column_width
5355 (clist, ctree->tree_column,
5356 clist->column[ctree->tree_column].width - 3);
5357 else if (line_style == GTK_CTREE_LINES_TABBED)
5358 gtk_clist_set_column_width
5359 (clist, ctree->tree_column,
5360 clist->column[ctree->tree_column].width + 3);
5363 if (GTK_WIDGET_REALIZED (ctree))
5367 case GTK_CTREE_LINES_SOLID:
5368 if (GTK_WIDGET_REALIZED (ctree))
5369 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5370 GDK_CAP_BUTT, GDK_JOIN_MITER);
5372 case GTK_CTREE_LINES_DOTTED:
5373 if (GTK_WIDGET_REALIZED (ctree))
5374 gdk_gc_set_line_attributes (ctree->lines_gc, 1,
5375 GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
5376 gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
5378 case GTK_CTREE_LINES_TABBED:
5379 if (GTK_WIDGET_REALIZED (ctree))
5380 gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID,
5381 GDK_CAP_BUTT, GDK_JOIN_MITER);
5383 case GTK_CTREE_LINES_NONE:
5388 CLIST_REFRESH (ctree);
5393 gtk_ctree_set_expander_style (GtkCTree *ctree,
5394 GtkCTreeExpanderStyle expander_style)
5397 GtkCTreeExpanderStyle old_style;
5399 g_return_if_fail (ctree != NULL);
5400 g_return_if_fail (GTK_IS_CTREE (ctree));
5402 if (expander_style == ctree->expander_style)
5405 clist = GTK_CLIST (ctree);
5407 old_style = ctree->expander_style;
5408 ctree->expander_style = expander_style;
5410 if (clist->column[ctree->tree_column].auto_resize &&
5411 !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
5415 new_width = clist->column[ctree->tree_column].width;
5418 case GTK_CTREE_EXPANDER_NONE:
5420 case GTK_CTREE_EXPANDER_TRIANGLE:
5421 new_width -= PM_SIZE + 3;
5423 case GTK_CTREE_EXPANDER_SQUARE:
5424 case GTK_CTREE_EXPANDER_CIRCULAR:
5425 new_width -= PM_SIZE + 1;
5429 switch (expander_style)
5431 case GTK_CTREE_EXPANDER_NONE:
5433 case GTK_CTREE_EXPANDER_TRIANGLE:
5434 new_width += PM_SIZE + 3;
5436 case GTK_CTREE_EXPANDER_SQUARE:
5437 case GTK_CTREE_EXPANDER_CIRCULAR:
5438 new_width += PM_SIZE + 1;
5442 gtk_clist_set_column_width (clist, ctree->tree_column, new_width);
5445 if (GTK_WIDGET_DRAWABLE (clist))
5446 CLIST_REFRESH (clist);
5450 /***********************************************************
5451 * Tree sorting functions *
5452 ***********************************************************/
5456 tree_sort (GtkCTree *ctree,
5460 GtkCTreeNode *list_start;
5465 clist = GTK_CLIST (ctree);
5468 list_start = GTK_CTREE_ROW (node)->children;
5470 list_start = GTK_CTREE_NODE (clist->row_list);
5475 work = GTK_CTREE_ROW (cmp)->sibling;
5478 if (clist->sort_type == GTK_SORT_ASCENDING)
5481 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) < 0)
5487 (clist, GTK_CTREE_ROW (work), GTK_CTREE_ROW (cmp)) > 0)
5490 work = GTK_CTREE_ROW (work)->sibling;
5492 if (cmp == list_start)
5493 list_start = GTK_CTREE_ROW (cmp)->sibling;
5496 gtk_ctree_unlink (ctree, cmp, FALSE);
5497 gtk_ctree_link (ctree, cmp, node, list_start, FALSE);
5503 gtk_ctree_sort_recursive (GtkCTree *ctree,
5507 GtkCTreeNode *focus_node = NULL;
5509 g_return_if_fail (ctree != NULL);
5510 g_return_if_fail (GTK_IS_CTREE (ctree));
5512 clist = GTK_CLIST (ctree);
5514 gtk_clist_freeze (clist);
5516 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5518 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
5520 g_list_free (clist->undo_selection);
5521 g_list_free (clist->undo_unselection);
5522 clist->undo_selection = NULL;
5523 clist->undo_unselection = NULL;
5526 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5528 GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
5530 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
5533 tree_sort (ctree, NULL, NULL);
5537 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5538 clist->undo_anchor = clist->focus_row;
5541 gtk_clist_thaw (clist);
5545 real_sort_list (GtkCList *clist)
5547 gtk_ctree_sort_recursive (GTK_CTREE (clist), NULL);
5551 gtk_ctree_sort_node (GtkCTree *ctree,
5555 GtkCTreeNode *focus_node = NULL;
5557 g_return_if_fail (ctree != NULL);
5558 g_return_if_fail (GTK_IS_CTREE (ctree));
5560 clist = GTK_CLIST (ctree);
5562 gtk_clist_freeze (clist);
5564 if (clist->selection_mode == GTK_SELECTION_EXTENDED)
5566 GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
5568 g_list_free (clist->undo_selection);
5569 g_list_free (clist->undo_unselection);
5570 clist->undo_selection = NULL;
5571 clist->undo_unselection = NULL;
5574 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
5575 focus_node = GTK_CTREE_NODE
5576 (g_list_nth (clist->row_list, clist->focus_row));
5578 tree_sort (ctree, node, NULL);
5582 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
5583 clist->undo_anchor = clist->focus_row;
5586 gtk_clist_thaw (clist);
5589 /************************************************************************/
5592 fake_unselect_all (GtkCList *clist,
5596 GList *focus_node = NULL;
5598 if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
5600 if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
5601 GTK_CTREE_ROW (focus_node)->row.selectable)
5603 GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
5605 if (CLIST_UNFROZEN (clist) &&
5606 gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
5607 GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
5608 GTK_CLIST_ROW (focus_node));
5612 clist->undo_selection = clist->selection;
5613 clist->selection = NULL;
5614 clist->selection_end = NULL;
5616 for (list = clist->undo_selection; list; list = list->next)
5618 if (list->data == focus_node)
5621 GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
5622 tree_draw_node (GTK_CTREE (clist), GTK_CTREE_NODE (list->data));
5627 selection_find (GtkCList *clist,
5629 GList *row_list_element)
5631 return g_list_find (clist->selection, row_list_element);
5635 resync_selection (GtkCList *clist, GdkEvent *event)
5645 g_return_if_fail (clist != NULL);
5646 g_return_if_fail (GTK_IS_CTREE (clist));
5648 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
5651 if (clist->anchor < 0 || clist->drag_pos < 0)
5654 ctree = GTK_CTREE (clist);
5656 clist->freeze_count++;
5658 i = MIN (clist->anchor, clist->drag_pos);
5659 e = MAX (clist->anchor, clist->drag_pos);
5661 if (clist->undo_selection)
5663 list = clist->selection;
5664 clist->selection = clist->undo_selection;
5665 clist->selection_end = g_list_last (clist->selection);
5666 clist->undo_selection = list;
5667 list = clist->selection;
5676 if (gtk_ctree_is_viewable (ctree, node))
5678 row = g_list_position (clist->row_list, (GList *)node);
5679 if (row >= i && row <= e)
5682 if (unselect && GTK_CTREE_ROW (node)->row.selectable)
5684 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5685 gtk_ctree_unselect (ctree, node);
5686 clist->undo_selection = g_list_prepend (clist->undo_selection,
5692 if (clist->anchor < clist->drag_pos)
5694 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
5695 i++, node = GTK_CTREE_NODE_NEXT (node))
5696 if (GTK_CTREE_ROW (node)->row.selectable)
5698 if (g_list_find (clist->selection, node))
5700 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5702 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5703 gtk_ctree_unselect (ctree, node);
5704 clist->undo_selection =
5705 g_list_prepend (clist->undo_selection, node);
5708 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5710 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5711 clist->undo_unselection =
5712 g_list_prepend (clist->undo_unselection, node);
5718 for (node = GTK_CTREE_NODE (g_list_nth (clist->row_list, e)); i <= e;
5719 e--, node = GTK_CTREE_NODE_PREV (node))
5720 if (GTK_CTREE_ROW (node)->row.selectable)
5722 if (g_list_find (clist->selection, node))
5724 if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
5726 GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
5727 gtk_ctree_unselect (ctree, node);
5728 clist->undo_selection =
5729 g_list_prepend (clist->undo_selection, node);
5732 else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
5734 GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
5735 clist->undo_unselection =
5736 g_list_prepend (clist->undo_unselection, node);
5741 clist->undo_unselection = g_list_reverse (clist->undo_unselection);
5742 for (list = clist->undo_unselection; list; list = list->next)
5743 gtk_ctree_select (ctree, list->data);
5746 clist->drag_pos = -1;
5748 if (!CLIST_UNFROZEN (clist))
5749 clist->freeze_count--;
5753 real_undo_selection (GtkCList *clist)
5758 g_return_if_fail (clist != NULL);
5759 g_return_if_fail (GTK_IS_CTREE (clist));
5761 if (clist->selection_mode != GTK_SELECTION_EXTENDED)
5764 if (!(clist->undo_selection || clist->undo_unselection))
5766 gtk_clist_unselect_all (clist);
5770 ctree = GTK_CTREE (clist);
5772 for (work = clist->undo_selection; work; work = work->next)
5773 if (GTK_CTREE_ROW (work->data)->row.selectable)
5774 gtk_ctree_select (ctree, GTK_CTREE_NODE (work->data));
5776 for (work = clist->undo_unselection; work; work = work->next)
5777 if (GTK_CTREE_ROW (work->data)->row.selectable)
5778 gtk_ctree_unselect (ctree, GTK_CTREE_NODE (work->data));
5780 if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
5782 gtk_widget_draw_focus (GTK_WIDGET (clist));
5783 clist->focus_row = clist->undo_anchor;
5784 gtk_widget_draw_focus (GTK_WIDGET (clist));
5787 clist->focus_row = clist->undo_anchor;
5789 clist->undo_anchor = -1;
5791 g_list_free (clist->undo_selection);
5792 g_list_free (clist->undo_unselection);
5793 clist->undo_selection = NULL;
5794 clist->undo_unselection = NULL;
5796 if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
5797 clist->clist_window_height)
5798 gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
5799 else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
5800 gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
5805 gtk_ctree_set_drag_compare_func (GtkCTree *ctree,
5806 GtkCTreeCompareDragFunc cmp_func)
5808 g_return_if_fail (ctree != NULL);
5809 g_return_if_fail (GTK_IS_CTREE (ctree));
5811 ctree->drag_compare = cmp_func;
5815 check_drag (GtkCTree *ctree,
5816 GtkCTreeNode *drag_source,
5817 GtkCTreeNode *drag_target,
5818 GtkCListDragPos insert_pos)
5820 g_return_val_if_fail (ctree != NULL, FALSE);
5821 g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE);
5823 if (drag_source && drag_source != drag_target &&
5824 (!GTK_CTREE_ROW (drag_source)->children ||
5825 !gtk_ctree_is_ancestor (ctree, drag_source, drag_target)))
5829 case GTK_CLIST_DRAG_NONE:
5831 case GTK_CLIST_DRAG_AFTER:
5832 if (GTK_CTREE_ROW (drag_target)->sibling != drag_source)
5833 return (!ctree->drag_compare ||
5834 ctree->drag_compare (ctree,
5836 GTK_CTREE_ROW (drag_target)->parent,
5837 GTK_CTREE_ROW(drag_target)->sibling));
5839 case GTK_CLIST_DRAG_BEFORE:
5840 if (GTK_CTREE_ROW (drag_source)->sibling != drag_target)
5841 return (!ctree->drag_compare ||
5842 ctree->drag_compare (ctree,
5844 GTK_CTREE_ROW (drag_target)->parent,
5847 case GTK_CLIST_DRAG_INTO:
5848 if (!GTK_CTREE_ROW (drag_target)->is_leaf &&
5849 GTK_CTREE_ROW (drag_target)->children != drag_source)
5850 return (!ctree->drag_compare ||
5851 ctree->drag_compare (ctree,
5854 GTK_CTREE_ROW (drag_target)->children));
5863 /************************************/
5865 drag_dest_info_destroy (gpointer data)
5867 GtkCListDestInfo *info = data;
5873 drag_dest_cell (GtkCList *clist,
5876 GtkCListDestInfo *dest_info)
5880 widget = GTK_WIDGET (clist);
5882 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
5884 y -= (GTK_CONTAINER (widget)->border_width +
5885 widget->style->ythickness + clist->column_title_area.height);
5886 dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
5888 if (dest_info->cell.row >= clist->rows)
5890 dest_info->cell.row = clist->rows - 1;
5891 y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
5893 if (dest_info->cell.row < -1)
5894 dest_info->cell.row = -1;
5896 x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
5898 dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
5900 if (dest_info->cell.row >= 0)
5905 y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
5907 if (GTK_CLIST_DRAW_DRAG_RECT(clist) &&
5908 !GTK_CTREE_ROW (g_list_nth (clist->row_list,
5909 dest_info->cell.row))->is_leaf)
5911 dest_info->insert_pos = GTK_CLIST_DRAG_INTO;
5912 h = clist->row_height / 4;
5914 else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
5916 dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
5917 h = clist->row_height / 2;
5920 if (GTK_CLIST_DRAW_DRAG_LINE(clist))
5923 dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
5924 else if (clist->row_height - y_delta < h)
5925 dest_info->insert_pos = GTK_CLIST_DRAG_AFTER;
5931 gtk_ctree_drag_begin (GtkWidget *widget,
5932 GdkDragContext *context)
5938 g_return_if_fail (widget != NULL);
5939 g_return_if_fail (GTK_IS_CTREE (widget));
5940 g_return_if_fail (context != NULL);
5942 clist = GTK_CLIST (widget);
5943 ctree = GTK_CTREE (widget);
5945 use_icons = GTK_CLIST_USE_DRAG_ICONS (clist);
5946 GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
5947 GTK_WIDGET_CLASS (parent_class)->drag_begin (widget, context);
5953 GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
5954 node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
5955 clist->click_cell.row));
5958 if (GTK_CELL_PIXTEXT
5959 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
5961 gtk_drag_set_icon_pixmap
5963 gtk_widget_get_colormap (widget),
5965 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap,
5967 (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask,
5972 gtk_drag_set_icon_default (context);
5977 gtk_ctree_drag_motion (GtkWidget *widget,
5978 GdkDragContext *context,
5985 GtkCListDestInfo new_info;
5986 GtkCListDestInfo *dest_info;
5988 g_return_val_if_fail (widget != NULL, FALSE);
5989 g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE);
5991 clist = GTK_CLIST (widget);
5992 ctree = GTK_CTREE (widget);
5994 dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
5998 dest_info = g_new (GtkCListDestInfo, 1);
6000 dest_info->cell.row = -1;
6001 dest_info->cell.column = -1;
6002 dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
6004 g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
6005 drag_dest_info_destroy);
6008 drag_dest_cell (clist, x, y, &new_info);
6010 if (GTK_CLIST_REORDERABLE (clist))
6013 GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
6015 list = context->targets;
6018 if (atom == GPOINTER_TO_INT (list->data))
6025 GtkCTreeNode *drag_source;
6026 GtkCTreeNode *drag_target;
6028 drag_source = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6029 clist->click_cell.row));
6030 drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6031 new_info.cell.row));
6033 if (gtk_drag_get_source_widget (context) != widget ||
6034 !check_drag (ctree, drag_source, drag_target,
6035 new_info.insert_pos))
6037 if (dest_info->cell.row < 0)
6039 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
6045 if (new_info.cell.row != dest_info->cell.row ||
6046 (new_info.cell.row == dest_info->cell.row &&
6047 dest_info->insert_pos != new_info.insert_pos))
6049 if (dest_info->cell.row >= 0)
6050 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
6052 g_list_nth (clist->row_list, dest_info->cell.row)->data,
6053 dest_info->cell.row, dest_info->insert_pos);
6055 dest_info->insert_pos = new_info.insert_pos;
6056 dest_info->cell.row = new_info.cell.row;
6057 dest_info->cell.column = new_info.cell.column;
6059 GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
6061 g_list_nth (clist->row_list, dest_info->cell.row)->data,
6062 dest_info->cell.row, dest_info->insert_pos);
6064 gdk_drag_status (context, context->suggested_action, time);
6070 dest_info->insert_pos = new_info.insert_pos;
6071 dest_info->cell.row = new_info.cell.row;
6072 dest_info->cell.column = new_info.cell.column;
6077 gtk_ctree_drag_data_received (GtkWidget *widget,
6078 GdkDragContext *context,
6081 GtkSelectionData *selection_data,
6088 g_return_if_fail (widget != NULL);
6089 g_return_if_fail (GTK_IS_CTREE (widget));
6090 g_return_if_fail (context != NULL);
6091 g_return_if_fail (selection_data != NULL);
6093 ctree = GTK_CTREE (widget);
6094 clist = GTK_CLIST (widget);
6096 if (GTK_CLIST_REORDERABLE (clist) &&
6097 gtk_drag_get_source_widget (context) == widget &&
6098 selection_data->target ==
6099 gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
6100 selection_data->format == GTK_TYPE_POINTER &&
6101 selection_data->length == sizeof (GtkCListCellInfo))
6103 GtkCListCellInfo *source_info;
6105 source_info = (GtkCListCellInfo *)(selection_data->data);
6108 GtkCListDestInfo dest_info;
6109 GtkCTreeNode *source_node;
6110 GtkCTreeNode *dest_node;
6112 drag_dest_cell (clist, x, y, &dest_info);
6114 source_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6116 dest_node = GTK_CTREE_NODE (g_list_nth (clist->row_list,
6117 dest_info.cell.row));
6119 if (!source_node || !dest_node)
6122 switch (dest_info.insert_pos)
6124 case GTK_CLIST_DRAG_NONE:
6126 case GTK_CLIST_DRAG_INTO:
6127 if (check_drag (ctree, source_node, dest_node,
6128 dest_info.insert_pos))
6129 gtk_ctree_move (ctree, source_node, dest_node,
6130 GTK_CTREE_ROW (dest_node)->children);
6131 g_dataset_remove_data (context, "gtk-clist-drag-dest");
6133 case GTK_CLIST_DRAG_BEFORE:
6134 if (check_drag (ctree, source_node, dest_node,
6135 dest_info.insert_pos))
6136 gtk_ctree_move (ctree, source_node,
6137 GTK_CTREE_ROW (dest_node)->parent, dest_node);
6138 g_dataset_remove_data (context, "gtk-clist-drag-dest");
6140 case GTK_CLIST_DRAG_AFTER:
6141 if (check_drag (ctree, source_node, dest_node,
6142 dest_info.insert_pos))
6143 gtk_ctree_move (ctree, source_node,
6144 GTK_CTREE_ROW (dest_node)->parent,
6145 GTK_CTREE_ROW (dest_node)->sibling);
6146 g_dataset_remove_data (context, "gtk-clist-drag-dest");