2 * This program is based on gtkflist.c
19 static void gtk_sctree_class_init (GtkSCTreeClass *class);
20 static void gtk_sctree_init (GtkSCTree *sctree);
22 static gint gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event);
23 static gint gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event);
24 static gint gtk_sctree_motion (GtkWidget *widget, GdkEventMotion *event);
25 static void gtk_sctree_drag_begin (GtkWidget *widget, GdkDragContext *context);
26 static void gtk_sctree_drag_end (GtkWidget *widget, GdkDragContext *context);
27 static void gtk_sctree_drag_data_get (GtkWidget *widget, GdkDragContext *context,
28 GtkSelectionData *data, guint info, guint time);
29 static void gtk_sctree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time);
30 static gboolean gtk_sctree_drag_motion (GtkWidget *widget, GdkDragContext *context,
31 gint x, gint y, guint time);
32 static gboolean gtk_sctree_drag_drop (GtkWidget *widget, GdkDragContext *context,
33 gint x, gint y, guint time);
34 static void gtk_sctree_drag_data_received (GtkWidget *widget, GdkDragContext *context,
35 gint x, gint y, GtkSelectionData *data,
36 guint info, guint time);
38 static void gtk_sctree_clear (GtkCList *clist);
39 static void gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node);
41 static void tree_sort (GtkCTree *ctree, GtkCTreeNode *node, gpointer data);
42 void gtk_sctree_sort_node (GtkCTree *ctree, GtkCTreeNode *node);
43 static void real_sort_list (GtkCList *clist);
44 void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
46 static void gtk_ctree_link (GtkCTree *ctree,
49 GtkCTreeNode *sibling,
50 gboolean update_focus_row);
52 static void gtk_ctree_unlink (GtkCTree *ctree,
54 gboolean update_focus_row);
56 static void tree_update_level (GtkCTree *ctree,
60 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
63 static GtkCTreeClass *parent_class;
65 static guint sctree_signals[LAST_SIGNAL];
68 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
71 * gtk_sctree_get_type:
74 * Creates the GtkSCTree class and its type information
76 * Return value: The type ID for GtkSCTreeClass
79 gtk_sctree_get_type (void)
81 static GtkType sctree_type = 0;
84 GtkTypeInfo sctree_info = {
87 sizeof (GtkSCTreeClass),
88 (GtkClassInitFunc) gtk_sctree_class_init,
89 (GtkObjectInitFunc) gtk_sctree_init,
90 NULL, /* reserved_1 */
91 NULL, /* reserved_2 */
92 (GtkClassInitFunc) NULL
95 sctree_type = gtk_type_unique (gtk_ctree_get_type (), &sctree_info);
101 /* Standard class initialization function */
103 gtk_sctree_class_init (GtkSCTreeClass *klass)
105 GtkObjectClass *object_class;
106 GtkWidgetClass *widget_class;
107 GtkCListClass *clist_class;
108 GtkCTreeClass *ctree_class;
110 object_class = (GtkObjectClass *) klass;
111 widget_class = (GtkWidgetClass *) klass;
112 clist_class = (GtkCListClass *) klass;
113 ctree_class = (GtkCTreeClass *) klass;
115 parent_class = gtk_type_class (gtk_ctree_get_type ());
117 sctree_signals[ROW_POPUP_MENU] =
118 gtk_signal_new ("row_popup_menu",
121 GTK_SIGNAL_OFFSET (GtkSCTreeClass, row_popup_menu),
122 gtk_marshal_NONE__POINTER,
125 sctree_signals[EMPTY_POPUP_MENU] =
126 gtk_signal_new ("empty_popup_menu",
129 GTK_SIGNAL_OFFSET (GtkSCTreeClass, empty_popup_menu),
130 gtk_marshal_NONE__POINTER,
133 sctree_signals[OPEN_ROW] =
134 gtk_signal_new ("open_row",
137 GTK_SIGNAL_OFFSET (GtkSCTreeClass, open_row),
138 gtk_marshal_NONE__NONE,
140 sctree_signals[START_DRAG] =
141 gtk_signal_new ("start_drag",
144 GTK_SIGNAL_OFFSET (GtkSCTreeClass, start_drag),
145 gtk_marshal_NONE__INT_POINTER,
150 gtk_object_class_add_signals (object_class, sctree_signals, LAST_SIGNAL);
152 clist_class->clear = gtk_sctree_clear;
153 ctree_class->tree_collapse = gtk_sctree_collapse;
155 widget_class->button_press_event = gtk_sctree_button_press;
156 widget_class->button_release_event = gtk_sctree_button_release;
157 widget_class->motion_notify_event = gtk_sctree_motion;
158 widget_class->drag_begin = gtk_sctree_drag_begin;
159 widget_class->drag_end = gtk_sctree_drag_end;
160 widget_class->drag_data_get = gtk_sctree_drag_data_get;
161 widget_class->drag_leave = gtk_sctree_drag_leave;
162 widget_class->drag_motion = gtk_sctree_drag_motion;
163 widget_class->drag_drop = gtk_sctree_drag_drop;
164 widget_class->drag_data_received = gtk_sctree_drag_data_received;
167 /* Standard object initialization function */
169 gtk_sctree_init (GtkSCTree *sctree)
171 sctree->anchor_row = NULL;
173 /* GtkCTree does not specify pointer motion by default */
174 gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
175 gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
178 /* Get information the specified row is selected. */
181 row_is_selected(GtkSCTree *sctree, gint row)
183 GtkCListRow *clist_row;
184 clist_row = g_list_nth (GTK_CLIST(sctree)->row_list, row)->data;
185 return clist_row ? clist_row->state == GTK_STATE_SELECTED : FALSE;
188 /* Selects the rows between the anchor to the specified row, inclusive. */
190 select_range (GtkSCTree *sctree, gint row)
196 if (sctree->anchor_row == NULL) {
198 sctree->anchor_row = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
200 prev_row = g_list_position(GTK_CLIST(sctree)->row_list,
201 (GList *)sctree->anchor_row);
203 if (row < prev_row) {
210 for (i = min; i <= max; i++)
211 gtk_clist_select_row (GTK_CLIST (sctree), i, -1);
214 /* Handles row selection according to the specified modifier state */
216 select_row (GtkSCTree *sctree, gint row, gint col, guint state)
218 gboolean range, additive;
219 g_return_if_fail (sctree != NULL);
220 g_return_if_fail (GTK_IS_SCTREE (sctree));
222 range = ((state & GDK_SHIFT_MASK) != 0) &&
223 (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
224 (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
225 additive = ((state & GDK_CONTROL_MASK) != 0) &&
226 (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
227 (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
229 gtk_clist_freeze (GTK_CLIST (sctree));
230 GTK_CLIST(sctree)->focus_row = row;
231 GTK_CLIST_CLASS(GTK_OBJECT(sctree)->klass)->refresh(GTK_CLIST(sctree));
233 gtk_clist_unselect_all (GTK_CLIST (sctree));
238 node = gtk_ctree_node_nth (GTK_CTREE(sctree), row);
240 /*No need to manage overlapped list*/
242 if (row_is_selected(sctree, row))
243 gtk_clist_unselect_row (GTK_CLIST (sctree), row, col);
245 gtk_signal_emit_by_name
246 (GTK_OBJECT (sctree),
247 "tree_select_row", node, col);
249 gtk_signal_emit_by_name
250 (GTK_OBJECT (sctree),
251 "tree_select_row", node, col);
253 sctree->anchor_row = node;
255 select_range (sctree, row);
256 gtk_clist_thaw (GTK_CLIST (sctree));
259 /* Our handler for button_press events. We override all of GtkCList's broken
263 gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
272 g_return_val_if_fail (widget != NULL, FALSE);
273 g_return_val_if_fail (GTK_IS_SCTREE (widget), FALSE);
274 g_return_val_if_fail (event != NULL, FALSE);
276 sctree = GTK_SCTREE (widget);
277 clist = GTK_CLIST (widget);
280 if (event->window != clist->clist_window)
281 return (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
283 on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
285 if (on_row && !GTK_WIDGET_HAS_FOCUS(widget))
286 gtk_widget_grab_focus (widget);
288 if (gtk_ctree_is_hot_spot (GTK_CTREE(sctree), event->x, event->y)) {
289 gtk_ctree_toggle_expansion
291 gtk_ctree_node_nth(GTK_CTREE(sctree), row));
295 switch (event->type) {
296 case GDK_BUTTON_PRESS:
297 if (event->button == 1 || event->button == 2) {
298 if (event->button == 2)
299 event->state &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
301 /* Save the mouse info for DnD */
302 sctree->dnd_press_button = event->button;
303 sctree->dnd_press_x = event->x;
304 sctree->dnd_press_y = event->y;
306 /* Handle selection */
307 if ((row_is_selected (sctree, row)
308 && !(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
309 || ((event->state & GDK_CONTROL_MASK)
310 && !(event->state & GDK_SHIFT_MASK))) {
311 sctree->dnd_select_pending = TRUE;
312 sctree->dnd_select_pending_state = event->state;
313 sctree->dnd_select_pending_row = row;
315 select_row (sctree, row, col, event->state);
317 gtk_clist_unselect_all (clist);
320 } else if (event->button == 3) {
321 /* Emit *_popup_menu signal*/
323 if (!row_is_selected(sctree,row))
324 select_row (sctree, row, col, 0);
325 gtk_signal_emit (GTK_OBJECT (sctree),
326 sctree_signals[ROW_POPUP_MENU],
329 gtk_clist_unselect_all(clist);
330 gtk_signal_emit (GTK_OBJECT (sctree),
331 sctree_signals[EMPTY_POPUP_MENU],
339 case GDK_2BUTTON_PRESS:
340 if (event->button != 1)
343 sctree->dnd_select_pending = FALSE;
344 sctree->dnd_select_pending_state = 0;
347 gtk_signal_emit (GTK_OBJECT (sctree),
348 sctree_signals[OPEN_ROW]);
360 /* Our handler for button_release events. We override all of GtkCList's broken
364 gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event)
372 g_return_val_if_fail (widget != NULL, FALSE);
373 g_return_val_if_fail (GTK_IS_SCTREE (widget), FALSE);
374 g_return_val_if_fail (event != NULL, FALSE);
376 sctree = GTK_SCTREE (widget);
377 clist = GTK_CLIST (widget);
380 if (event->window != clist->clist_window)
381 return (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event);
383 on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
385 if (!(event->button == 1 || event->button == 2))
388 sctree->dnd_press_button = 0;
389 sctree->dnd_press_x = 0;
390 sctree->dnd_press_y = 0;
393 if (sctree->dnd_select_pending) {
394 select_row (sctree, row, col, sctree->dnd_select_pending_state);
395 sctree->dnd_select_pending = FALSE;
396 sctree->dnd_select_pending_state = 0;
405 /* Our handler for motion_notify events. We override all of GtkCList's broken
409 gtk_sctree_motion (GtkWidget *widget, GdkEventMotion *event)
414 g_return_val_if_fail (widget != NULL, FALSE);
415 g_return_val_if_fail (GTK_IS_SCTREE (widget), FALSE);
416 g_return_val_if_fail (event != NULL, FALSE);
418 sctree = GTK_SCTREE (widget);
419 clist = GTK_CLIST (widget);
421 if (event->window != clist->clist_window)
422 return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
424 if (!((sctree->dnd_press_button == 1 && (event->state & GDK_BUTTON1_MASK))
425 || (sctree->dnd_press_button == 2 && (event->state & GDK_BUTTON2_MASK))))
428 /* This is the same threshold value that is used in gtkdnd.c */
430 if (MAX (ABS (sctree->dnd_press_x - event->x),
431 ABS (sctree->dnd_press_y - event->y)) <= 3)
434 /* Handle any pending selections */
436 if (sctree->dnd_select_pending) {
437 if (!row_is_selected(sctree,sctree->dnd_select_pending_row))
439 sctree->dnd_select_pending_row,
441 sctree->dnd_select_pending_state);
443 sctree->dnd_select_pending = FALSE;
444 sctree->dnd_select_pending_state = 0;
447 gtk_signal_emit (GTK_OBJECT (sctree),
448 sctree_signals[START_DRAG],
449 sctree->dnd_press_button,
454 /* We override the drag_begin signal to do nothing */
456 gtk_sctree_drag_begin (GtkWidget *widget, GdkDragContext *context)
461 /* We override the drag_end signal to do nothing */
463 gtk_sctree_drag_end (GtkWidget *widget, GdkDragContext *context)
468 /* We override the drag_data_get signal to do nothing */
470 gtk_sctree_drag_data_get (GtkWidget *widget, GdkDragContext *context,
471 GtkSelectionData *data, guint info, guint time)
476 /* We override the drag_leave signal to do nothing */
478 gtk_sctree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time)
483 /* We override the drag_motion signal to do nothing */
485 gtk_sctree_drag_motion (GtkWidget *widget, GdkDragContext *context,
486 gint x, gint y, guint time)
491 /* We override the drag_drop signal to do nothing */
493 gtk_sctree_drag_drop (GtkWidget *widget, GdkDragContext *context,
494 gint x, gint y, guint time)
499 /* We override the drag_data_received signal to do nothing */
501 gtk_sctree_drag_data_received (GtkWidget *widget, GdkDragContext *context,
502 gint x, gint y, GtkSelectionData *data,
503 guint info, guint time)
508 /* Our handler for the clear signal of the clist. We have to reset the anchor
512 gtk_sctree_clear (GtkCList *clist)
516 g_return_if_fail (clist != NULL);
517 g_return_if_fail (GTK_IS_SCTREE (clist));
519 sctree = GTK_SCTREE (clist);
520 sctree->anchor_row = NULL;
522 if (((GtkCListClass *)parent_class)->clear)
523 (* ((GtkCListClass *)parent_class)->clear) (clist);
526 /* Our handler for the change_focus_row_expansion signal of the ctree.
527 We have to set the anchor to parent visible node.
530 gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node)
532 g_return_if_fail (ctree != NULL);
533 g_return_if_fail (GTK_IS_SCTREE (ctree));
535 (* parent_class->tree_collapse) (ctree, node);
536 GTK_SCTREE(ctree)->anchor_row =
537 gtk_ctree_node_nth(ctree, GTK_CLIST(ctree)->focus_row);
540 GtkWidget *gtk_sctree_new_with_titles (gint columns,
546 sctree = gtk_type_new (gtk_sctree_get_type ());
547 gtk_ctree_construct (GTK_CTREE (sctree), columns, tree_column, titles);
548 gtk_clist_set_selection_mode(GTK_CLIST(sctree), GTK_SELECTION_EXTENDED);
550 return GTK_WIDGET (sctree);
553 void gtk_sctree_select (GtkSCTree *sctree,
557 g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
561 void gtk_sctree_unselect_all (GtkSCTree *sctree)
563 gtk_clist_unselect_all(GTK_CLIST(sctree));
564 sctree->anchor_row = NULL;
567 /***********************************************************
568 * Tree sorting functions *
569 ***********************************************************/
571 static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
579 /* find the maximum element of numbers[root],
580 numbers[2*root] and numbers[2*root+1] */
582 if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, root)),
583 GTK_CTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
586 if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, k)),
587 GTK_CTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
589 /* if numbers[root] wasn't the maximum element then
592 temp = g_ptr_array_index( numbers,root);
593 g_ptr_array_index( numbers, root) = g_ptr_array_index( numbers, j);
594 g_ptr_array_index( numbers, j) = temp;
595 sink( clist, numbers, j, bottom);
600 static void heap_sort(GtkCList *clist, GPtrArray *numbers, gint array_size)
606 for (i = (array_size / 2); i >= 1; i--)
607 sink( clist, numbers, i, array_size);
608 /* output the Heap */
609 for (i = array_size; i >= 2; i--) {
610 temp = g_ptr_array_index( numbers, 1);
611 g_ptr_array_index( numbers, 1) = g_ptr_array_index( numbers, i);
612 g_ptr_array_index( numbers, i) = temp;
613 sink( clist, numbers, 1, i-1);
618 tree_sort (GtkCTree *ctree,
622 GtkCTreeNode *list_start, *work, *next;
623 GPtrArray *row_array, *viewable_array;
628 clist = GTK_CLIST (ctree);
631 work = GTK_CTREE_ROW (node)->children;
633 work = GTK_CTREE_NODE (clist->row_list);
635 row_array = g_ptr_array_new();
636 viewable_array = g_ptr_array_new();
639 g_ptr_array_add( row_array, NULL);
641 /* add all rows to row_array */
642 g_ptr_array_add( row_array, work);
643 if (GTK_CTREE_ROW (work)->parent && gtk_ctree_is_viewable( ctree, work))
644 g_ptr_array_add( viewable_array, GTK_CTREE_ROW (work)->parent);
645 next = GTK_CTREE_ROW (work)->sibling;
646 gtk_ctree_unlink( ctree, work, FALSE);
650 heap_sort( clist, row_array, (row_array->len)-1);
653 list_start = GTK_CTREE_ROW (node)->children;
655 list_start = GTK_CTREE_NODE (clist->row_list);
657 if (clist->sort_type == GTK_SORT_ASCENDING) {
658 for (i=(row_array->len)-1; i>=1; i--) {
659 work = g_ptr_array_index( row_array, i);
660 gtk_ctree_link( ctree, work, node, list_start, FALSE);
662 /* insert work at the beginning of the list */
665 for (i=1; i<row_array->len; i++) {
666 work = g_ptr_array_index( row_array, i);
667 gtk_ctree_link( ctree, work, node, list_start, FALSE);
669 /* insert work at the beginning of the list */
673 for (i=0; i<viewable_array->len; i++) {
674 gtk_ctree_expand( ctree, g_ptr_array_index( viewable_array, i));
679 g_ptr_array_free( row_array, FALSE);
680 g_ptr_array_free( viewable_array, FALSE);
684 gtk_sctree_sort_recursive (GtkCTree *ctree,
688 GtkCTreeNode *focus_node = NULL;
690 g_return_if_fail (ctree != NULL);
691 g_return_if_fail (GTK_IS_CTREE (ctree));
693 clist = GTK_CLIST (ctree);
695 gtk_clist_freeze (clist);
697 if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
698 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
700 g_list_free (clist->undo_selection);
701 g_list_free (clist->undo_unselection);
702 clist->undo_selection = NULL;
703 clist->undo_unselection = NULL;
706 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
707 focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
709 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
712 tree_sort (ctree, NULL, NULL);
715 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
716 clist->undo_anchor = clist->focus_row;
719 gtk_clist_thaw (clist);
723 real_sort_list (GtkCList *clist)
725 gtk_sctree_sort_recursive (GTK_CTREE (clist), NULL);
729 gtk_sctree_sort_node (GtkCTree *ctree,
733 GtkCTreeNode *focus_node = NULL;
735 g_return_if_fail (ctree != NULL);
736 g_return_if_fail (GTK_IS_CTREE (ctree));
738 clist = GTK_CLIST (ctree);
740 gtk_clist_freeze (clist);
742 if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
743 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
745 g_list_free (clist->undo_selection);
746 g_list_free (clist->undo_unselection);
747 clist->undo_selection = NULL;
748 clist->undo_unselection = NULL;
751 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
752 focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
754 tree_sort (ctree, node, NULL);
757 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
758 clist->undo_anchor = clist->focus_row;
761 gtk_clist_thaw (clist);
764 /************************************************************************/
767 gtk_ctree_unlink (GtkCTree *ctree,
769 gboolean update_focus_row)
776 GtkCTreeNode *parent;
779 g_return_if_fail (ctree != NULL);
780 g_return_if_fail (GTK_IS_CTREE (ctree));
781 g_return_if_fail (node != NULL);
783 clist = GTK_CLIST (ctree);
785 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
786 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
788 g_list_free (clist->undo_selection);
789 g_list_free (clist->undo_unselection);
790 clist->undo_selection = NULL;
791 clist->undo_unselection = NULL;
794 visible = gtk_ctree_is_viewable (ctree, node);
796 /* clist->row_list_end unlinked ? */
797 if (visible && (GTK_CTREE_NODE_NEXT (node) == NULL ||
798 (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node,
799 GTK_CTREE_NODE (clist->row_list_end)))))
800 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
804 level = GTK_CTREE_ROW (node)->level;
805 work = GTK_CTREE_NODE_NEXT (node);
806 while (work && GTK_CTREE_ROW (work)->level > level) {
807 work = GTK_CTREE_NODE_NEXT (work);
812 clist->rows -= (rows + 1);
814 if (update_focus_row) {
817 pos = g_list_position (clist->row_list, (GList *)node);
818 if (pos + rows < clist->focus_row)
819 clist->focus_row -= (rows + 1);
820 else if (pos <= clist->focus_row) {
821 if (!GTK_CTREE_ROW (node)->sibling)
822 clist->focus_row = MAX (pos - 1, 0);
824 clist->focus_row = pos;
826 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
828 clist->undo_anchor = clist->focus_row;
833 list = (GList *)GTK_CTREE_NODE_PREV (work);
835 list = (GList *)work;
836 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
839 if (GTK_CTREE_NODE_PREV (node) &&
840 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) {
841 list = (GList *)GTK_CTREE_NODE_PREV (node);
842 list->next = (GList *)work;
846 parent = GTK_CTREE_ROW (node)->parent;
848 if (GTK_CTREE_ROW (parent)->children == node) {
849 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
850 if (!GTK_CTREE_ROW (parent)->children)
851 gtk_ctree_collapse (ctree, parent);
854 GtkCTreeNode *sibling;
856 sibling = GTK_CTREE_ROW (parent)->children;
857 while (GTK_CTREE_ROW (sibling)->sibling != node)
858 sibling = GTK_CTREE_ROW (sibling)->sibling;
859 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
863 if (clist->row_list == (GList *)node)
864 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
866 GtkCTreeNode *sibling;
868 sibling = GTK_CTREE_NODE (clist->row_list);
869 while (GTK_CTREE_ROW (sibling)->sibling != node)
870 sibling = GTK_CTREE_ROW (sibling)->sibling;
871 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
877 gtk_ctree_link (GtkCTree *ctree,
879 GtkCTreeNode *parent,
880 GtkCTreeNode *sibling,
881 gboolean update_focus_row)
887 gboolean visible = FALSE;
891 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
892 g_return_if_fail (node != NULL);
893 g_return_if_fail (node != sibling);
894 g_return_if_fail (node != parent);
896 clist = GTK_CLIST (ctree);
898 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
899 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
901 g_list_free (clist->undo_selection);
902 g_list_free (clist->undo_unselection);
903 clist->undo_selection = NULL;
904 clist->undo_unselection = NULL;
907 for (rows = 1, list_end = (GList *)node; list_end->next;
908 list_end = list_end->next)
911 GTK_CTREE_ROW (node)->parent = parent;
912 GTK_CTREE_ROW (node)->sibling = sibling;
914 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
915 GTK_CTREE_ROW (parent)->expanded))) {
921 work = (GList *)(GTK_CTREE_ROW (parent)->children);
923 work = clist->row_list;
926 if (work != (GList *)sibling) {
927 while (GTK_CTREE_ROW (work)->sibling != sibling)
928 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
929 GTK_CTREE_ROW (work)->sibling = node;
932 if (sibling == GTK_CTREE_NODE (clist->row_list))
933 clist->row_list = (GList *) node;
934 if (GTK_CTREE_NODE_PREV (sibling) &&
935 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) {
936 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
937 list->next = (GList *)node;
940 list = (GList *)node;
941 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
942 list_end->next = (GList *)sibling;
943 list = (GList *)sibling;
944 list->prev = list_end;
945 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
946 GTK_CTREE_ROW (parent)->children = node;
951 while (GTK_CTREE_ROW (work)->sibling)
952 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
953 GTK_CTREE_ROW (work)->sibling = node;
955 /* find last visible child of sibling */
956 work = (GList *) gtk_ctree_last_visible (ctree,
957 GTK_CTREE_NODE (work));
959 list_end->next = work->next;
961 list = work->next->prev = list_end;
962 work->next = (GList *)node;
963 list = (GList *)node;
968 GTK_CTREE_ROW (parent)->children = node;
969 list = (GList *)node;
970 list->prev = (GList *)parent;
971 if (GTK_CTREE_ROW (parent)->expanded) {
972 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
973 if (GTK_CTREE_NODE_NEXT(parent)) {
974 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
975 list->prev = list_end;
977 list = (GList *)parent;
978 list->next = (GList *)node;
981 list_end->next = NULL;
984 clist->row_list = (GList *)node;
985 list = (GList *)node;
987 list_end->next = NULL;
992 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
994 if (clist->row_list_end == NULL ||
995 clist->row_list_end->next == (GList *)node)
996 clist->row_list_end = list_end;
998 if (visible && update_focus_row) {
1001 pos = g_list_position (clist->row_list, (GList *)node);
1003 if (pos <= clist->focus_row) {
1004 clist->focus_row += rows;
1005 clist->undo_anchor = clist->focus_row;
1011 tree_update_level (GtkCTree *ctree,
1018 if (GTK_CTREE_ROW (node)->parent)
1019 GTK_CTREE_ROW (node)->level =
1020 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
1022 GTK_CTREE_ROW (node)->level = 1;
1025 static GtkCTreeNode *
1026 gtk_ctree_last_visible (GtkCTree *ctree,
1034 work = GTK_CTREE_ROW (node)->children;
1036 if (!work || !GTK_CTREE_ROW (node)->expanded)
1039 while (GTK_CTREE_ROW (work)->sibling)
1040 work = GTK_CTREE_ROW (work)->sibling;
1042 return gtk_ctree_last_visible (ctree, work);