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 void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
45 static void gtk_ctree_link (GtkCTree *ctree,
48 GtkCTreeNode *sibling,
49 gboolean update_focus_row);
51 static void gtk_ctree_unlink (GtkCTree *ctree,
53 gboolean update_focus_row);
55 static void tree_update_level (GtkCTree *ctree,
59 static GtkCTreeNode * gtk_ctree_last_visible (GtkCTree *ctree,
62 static GtkCTreeClass *parent_class;
64 static guint sctree_signals[LAST_SIGNAL];
67 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
70 * gtk_sctree_get_type:
73 * Creates the GtkSCTree class and its type information
75 * Return value: The type ID for GtkSCTreeClass
78 gtk_sctree_get_type (void)
80 static GtkType sctree_type = 0;
83 GtkTypeInfo sctree_info = {
86 sizeof (GtkSCTreeClass),
87 (GtkClassInitFunc) gtk_sctree_class_init,
88 (GtkObjectInitFunc) gtk_sctree_init,
89 NULL, /* reserved_1 */
90 NULL, /* reserved_2 */
91 (GtkClassInitFunc) NULL
94 sctree_type = gtk_type_unique (gtk_ctree_get_type (), &sctree_info);
100 /* Standard class initialization function */
102 gtk_sctree_class_init (GtkSCTreeClass *klass)
104 GtkObjectClass *object_class;
105 GtkWidgetClass *widget_class;
106 GtkCListClass *clist_class;
107 GtkCTreeClass *ctree_class;
109 object_class = (GtkObjectClass *) klass;
110 widget_class = (GtkWidgetClass *) klass;
111 clist_class = (GtkCListClass *) klass;
112 ctree_class = (GtkCTreeClass *) klass;
114 parent_class = gtk_type_class (gtk_ctree_get_type ());
116 sctree_signals[ROW_POPUP_MENU] =
117 gtk_signal_new ("row_popup_menu",
120 GTK_SIGNAL_OFFSET (GtkSCTreeClass, row_popup_menu),
121 gtk_marshal_NONE__POINTER,
124 sctree_signals[EMPTY_POPUP_MENU] =
125 gtk_signal_new ("empty_popup_menu",
128 GTK_SIGNAL_OFFSET (GtkSCTreeClass, empty_popup_menu),
129 gtk_marshal_NONE__POINTER,
132 sctree_signals[OPEN_ROW] =
133 gtk_signal_new ("open_row",
136 GTK_SIGNAL_OFFSET (GtkSCTreeClass, open_row),
137 gtk_marshal_NONE__NONE,
139 sctree_signals[START_DRAG] =
140 gtk_signal_new ("start_drag",
143 GTK_SIGNAL_OFFSET (GtkSCTreeClass, start_drag),
144 gtk_marshal_NONE__INT_POINTER,
149 gtk_object_class_add_signals (object_class, sctree_signals, LAST_SIGNAL);
151 clist_class->clear = gtk_sctree_clear;
152 ctree_class->tree_collapse = gtk_sctree_collapse;
154 widget_class->button_press_event = gtk_sctree_button_press;
155 widget_class->button_release_event = gtk_sctree_button_release;
156 widget_class->motion_notify_event = gtk_sctree_motion;
157 widget_class->drag_begin = gtk_sctree_drag_begin;
158 widget_class->drag_end = gtk_sctree_drag_end;
159 widget_class->drag_data_get = gtk_sctree_drag_data_get;
160 widget_class->drag_leave = gtk_sctree_drag_leave;
161 widget_class->drag_motion = gtk_sctree_drag_motion;
162 widget_class->drag_drop = gtk_sctree_drag_drop;
163 widget_class->drag_data_received = gtk_sctree_drag_data_received;
166 /* Standard object initialization function */
168 gtk_sctree_init (GtkSCTree *sctree)
170 sctree->anchor_row = NULL;
172 /* GtkCTree does not specify pointer motion by default */
173 gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
174 gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
177 /* Get information the specified row is selected. */
180 row_is_selected(GtkSCTree *sctree, gint row)
182 GtkCListRow *clist_row;
183 clist_row = g_list_nth (GTK_CLIST(sctree)->row_list, row)->data;
184 return clist_row ? clist_row->state == GTK_STATE_SELECTED : FALSE;
187 /* Selects the rows between the anchor to the specified row, inclusive. */
189 select_range (GtkSCTree *sctree, gint row)
195 if (sctree->anchor_row == NULL) {
197 sctree->anchor_row = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
199 prev_row = g_list_position(GTK_CLIST(sctree)->row_list,
200 (GList *)sctree->anchor_row);
202 if (row < prev_row) {
205 GTK_CLIST(sctree)->focus_row = max;
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, gint tree_column,
545 sctree = gtk_type_new (gtk_sctree_get_type ());
546 gtk_ctree_construct (GTK_CTREE (sctree), columns, tree_column, titles);
547 gtk_clist_set_selection_mode(GTK_CLIST(sctree), GTK_SELECTION_EXTENDED);
549 return GTK_WIDGET (sctree);
552 void gtk_sctree_select (GtkSCTree *sctree, GtkCTreeNode *node)
555 g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
559 void gtk_sctree_unselect_all (GtkSCTree *sctree)
561 gtk_clist_unselect_all(GTK_CLIST(sctree));
562 sctree->anchor_row = NULL;
565 void gtk_sctree_set_anchor_row (GtkSCTree *sctree, GtkCTreeNode *node)
567 sctree->anchor_row = node;
570 /***********************************************************
571 * Tree sorting functions *
572 ***********************************************************/
574 static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
582 /* find the maximum element of numbers[root],
583 numbers[2*root] and numbers[2*root+1] */
585 if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, root)),
586 GTK_CTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
589 if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, k)),
590 GTK_CTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
592 /* if numbers[root] wasn't the maximum element then
595 temp = g_ptr_array_index( numbers,root);
596 g_ptr_array_index( numbers, root) = g_ptr_array_index( numbers, j);
597 g_ptr_array_index( numbers, j) = temp;
598 sink( clist, numbers, j, bottom);
603 static void heap_sort(GtkCList *clist, GPtrArray *numbers, gint array_size)
609 for (i = (array_size / 2); i >= 1; i--)
610 sink( clist, numbers, i, array_size);
611 /* output the Heap */
612 for (i = array_size; i >= 2; i--) {
613 temp = g_ptr_array_index( numbers, 1);
614 g_ptr_array_index( numbers, 1) = g_ptr_array_index( numbers, i);
615 g_ptr_array_index( numbers, i) = temp;
616 sink( clist, numbers, 1, i-1);
621 tree_sort (GtkCTree *ctree,
625 GtkCTreeNode *list_start, *work, *next;
626 GPtrArray *row_array, *viewable_array;
631 clist = GTK_CLIST (ctree);
634 work = GTK_CTREE_ROW (node)->children;
636 work = GTK_CTREE_NODE (clist->row_list);
638 row_array = g_ptr_array_new();
639 viewable_array = g_ptr_array_new();
642 g_ptr_array_add( row_array, NULL);
644 /* add all rows to row_array */
645 g_ptr_array_add( row_array, work);
646 if (GTK_CTREE_ROW (work)->parent && gtk_ctree_is_viewable( ctree, work))
647 g_ptr_array_add( viewable_array, GTK_CTREE_ROW (work)->parent);
648 next = GTK_CTREE_ROW (work)->sibling;
649 gtk_ctree_unlink( ctree, work, FALSE);
653 heap_sort( clist, row_array, (row_array->len)-1);
656 list_start = GTK_CTREE_ROW (node)->children;
658 list_start = GTK_CTREE_NODE (clist->row_list);
660 if (clist->sort_type == GTK_SORT_ASCENDING) {
661 for (i=(row_array->len)-1; i>=1; i--) {
662 work = g_ptr_array_index( row_array, i);
663 gtk_ctree_link( ctree, work, node, list_start, FALSE);
665 /* insert work at the beginning of the list */
668 for (i=1; i<row_array->len; i++) {
669 work = g_ptr_array_index( row_array, i);
670 gtk_ctree_link( ctree, work, node, list_start, FALSE);
672 /* insert work at the beginning of the list */
676 for (i=0; i<viewable_array->len; i++) {
677 gtk_ctree_expand( ctree, g_ptr_array_index( viewable_array, i));
682 g_ptr_array_free( row_array, TRUE);
683 g_ptr_array_free( viewable_array, TRUE);
687 gtk_sctree_sort_recursive (GtkCTree *ctree,
691 GtkCTreeNode *focus_node = NULL;
693 g_return_if_fail (ctree != NULL);
694 g_return_if_fail (GTK_IS_CTREE (ctree));
696 clist = GTK_CLIST (ctree);
698 gtk_clist_freeze (clist);
700 if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
701 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
703 g_list_free (clist->undo_selection);
704 g_list_free (clist->undo_unselection);
705 clist->undo_selection = NULL;
706 clist->undo_unselection = NULL;
709 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
710 focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
712 gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL);
715 tree_sort (ctree, NULL, NULL);
718 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
719 clist->undo_anchor = clist->focus_row;
722 gtk_clist_thaw (clist);
726 gtk_sctree_sort_node (GtkCTree *ctree,
730 GtkCTreeNode *focus_node = NULL;
732 g_return_if_fail (ctree != NULL);
733 g_return_if_fail (GTK_IS_CTREE (ctree));
735 clist = GTK_CLIST (ctree);
737 gtk_clist_freeze (clist);
739 if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
740 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
742 g_list_free (clist->undo_selection);
743 g_list_free (clist->undo_unselection);
744 clist->undo_selection = NULL;
745 clist->undo_unselection = NULL;
748 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
749 focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
751 tree_sort (ctree, node, NULL);
754 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
755 clist->undo_anchor = clist->focus_row;
758 gtk_clist_thaw (clist);
761 /************************************************************************/
764 gtk_ctree_unlink (GtkCTree *ctree,
766 gboolean update_focus_row)
773 GtkCTreeNode *parent;
776 g_return_if_fail (ctree != NULL);
777 g_return_if_fail (GTK_IS_CTREE (ctree));
778 g_return_if_fail (node != NULL);
780 clist = GTK_CLIST (ctree);
782 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
783 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
785 g_list_free (clist->undo_selection);
786 g_list_free (clist->undo_unselection);
787 clist->undo_selection = NULL;
788 clist->undo_unselection = NULL;
791 visible = gtk_ctree_is_viewable (ctree, node);
793 /* clist->row_list_end unlinked ? */
794 if (visible && (GTK_CTREE_NODE_NEXT (node) == NULL ||
795 (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node,
796 GTK_CTREE_NODE (clist->row_list_end)))))
797 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
801 level = GTK_CTREE_ROW (node)->level;
802 work = GTK_CTREE_NODE_NEXT (node);
803 while (work && GTK_CTREE_ROW (work)->level > level) {
804 work = GTK_CTREE_NODE_NEXT (work);
809 clist->rows -= (rows + 1);
811 if (update_focus_row) {
814 pos = g_list_position (clist->row_list, (GList *)node);
815 if (pos + rows < clist->focus_row)
816 clist->focus_row -= (rows + 1);
817 else if (pos <= clist->focus_row) {
818 if (!GTK_CTREE_ROW (node)->sibling)
819 clist->focus_row = MAX (pos - 1, 0);
821 clist->focus_row = pos;
823 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
825 clist->undo_anchor = clist->focus_row;
830 list = (GList *)GTK_CTREE_NODE_PREV (work);
832 list = (GList *)work;
833 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
836 if (GTK_CTREE_NODE_PREV (node) &&
837 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) {
838 list = (GList *)GTK_CTREE_NODE_PREV (node);
839 list->next = (GList *)work;
843 parent = GTK_CTREE_ROW (node)->parent;
845 if (GTK_CTREE_ROW (parent)->children == node) {
846 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
847 if (!GTK_CTREE_ROW (parent)->children)
848 gtk_ctree_collapse (ctree, parent);
851 GtkCTreeNode *sibling;
853 sibling = GTK_CTREE_ROW (parent)->children;
854 while (GTK_CTREE_ROW (sibling)->sibling != node)
855 sibling = GTK_CTREE_ROW (sibling)->sibling;
856 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
860 if (clist->row_list == (GList *)node)
861 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
863 GtkCTreeNode *sibling;
865 sibling = GTK_CTREE_NODE (clist->row_list);
866 while (GTK_CTREE_ROW (sibling)->sibling != node)
867 sibling = GTK_CTREE_ROW (sibling)->sibling;
868 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
874 gtk_ctree_link (GtkCTree *ctree,
876 GtkCTreeNode *parent,
877 GtkCTreeNode *sibling,
878 gboolean update_focus_row)
884 gboolean visible = FALSE;
888 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
889 g_return_if_fail (node != NULL);
890 g_return_if_fail (node != sibling);
891 g_return_if_fail (node != parent);
893 clist = GTK_CLIST (ctree);
895 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
896 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
898 g_list_free (clist->undo_selection);
899 g_list_free (clist->undo_unselection);
900 clist->undo_selection = NULL;
901 clist->undo_unselection = NULL;
904 for (rows = 1, list_end = (GList *)node; list_end->next;
905 list_end = list_end->next)
908 GTK_CTREE_ROW (node)->parent = parent;
909 GTK_CTREE_ROW (node)->sibling = sibling;
911 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
912 GTK_CTREE_ROW (parent)->expanded))) {
918 work = (GList *)(GTK_CTREE_ROW (parent)->children);
920 work = clist->row_list;
923 if (work != (GList *)sibling) {
924 while (GTK_CTREE_ROW (work)->sibling != sibling)
925 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
926 GTK_CTREE_ROW (work)->sibling = node;
929 if (sibling == GTK_CTREE_NODE (clist->row_list))
930 clist->row_list = (GList *) node;
931 if (GTK_CTREE_NODE_PREV (sibling) &&
932 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) {
933 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
934 list->next = (GList *)node;
937 list = (GList *)node;
938 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
939 list_end->next = (GList *)sibling;
940 list = (GList *)sibling;
941 list->prev = list_end;
942 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
943 GTK_CTREE_ROW (parent)->children = node;
948 while (GTK_CTREE_ROW (work)->sibling)
949 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
950 GTK_CTREE_ROW (work)->sibling = node;
952 /* find last visible child of sibling */
953 work = (GList *) gtk_ctree_last_visible (ctree,
954 GTK_CTREE_NODE (work));
956 list_end->next = work->next;
958 list = work->next->prev = list_end;
959 work->next = (GList *)node;
960 list = (GList *)node;
965 GTK_CTREE_ROW (parent)->children = node;
966 list = (GList *)node;
967 list->prev = (GList *)parent;
968 if (GTK_CTREE_ROW (parent)->expanded) {
969 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
970 if (GTK_CTREE_NODE_NEXT(parent)) {
971 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
972 list->prev = list_end;
974 list = (GList *)parent;
975 list->next = (GList *)node;
978 list_end->next = NULL;
981 clist->row_list = (GList *)node;
982 list = (GList *)node;
984 list_end->next = NULL;
989 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
991 if (clist->row_list_end == NULL ||
992 clist->row_list_end->next == (GList *)node)
993 clist->row_list_end = list_end;
995 if (visible && update_focus_row) {
998 pos = g_list_position (clist->row_list, (GList *)node);
1000 if (pos <= clist->focus_row) {
1001 clist->focus_row += rows;
1002 clist->undo_anchor = clist->focus_row;
1008 tree_update_level (GtkCTree *ctree,
1015 if (GTK_CTREE_ROW (node)->parent)
1016 GTK_CTREE_ROW (node)->level =
1017 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
1019 GTK_CTREE_ROW (node)->level = 1;
1022 static GtkCTreeNode *
1023 gtk_ctree_last_visible (GtkCTree *ctree,
1031 work = GTK_CTREE_ROW (node)->children;
1033 if (!work || !GTK_CTREE_ROW (node)->expanded)
1036 while (GTK_CTREE_ROW (work)->sibling)
1037 work = GTK_CTREE_ROW (work)->sibling;
1039 return gtk_ctree_last_visible (ctree, work);