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,
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, TRUE);
680 g_ptr_array_free( viewable_array, TRUE);
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 gtk_sctree_sort_node (GtkCTree *ctree,
727 GtkCTreeNode *focus_node = NULL;
729 g_return_if_fail (ctree != NULL);
730 g_return_if_fail (GTK_IS_CTREE (ctree));
732 clist = GTK_CLIST (ctree);
734 gtk_clist_freeze (clist);
736 if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
737 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
739 g_list_free (clist->undo_selection);
740 g_list_free (clist->undo_unselection);
741 clist->undo_selection = NULL;
742 clist->undo_unselection = NULL;
745 if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
746 focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
748 tree_sort (ctree, node, NULL);
751 clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
752 clist->undo_anchor = clist->focus_row;
755 gtk_clist_thaw (clist);
758 /************************************************************************/
761 gtk_ctree_unlink (GtkCTree *ctree,
763 gboolean update_focus_row)
770 GtkCTreeNode *parent;
773 g_return_if_fail (ctree != NULL);
774 g_return_if_fail (GTK_IS_CTREE (ctree));
775 g_return_if_fail (node != NULL);
777 clist = GTK_CLIST (ctree);
779 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
780 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
782 g_list_free (clist->undo_selection);
783 g_list_free (clist->undo_unselection);
784 clist->undo_selection = NULL;
785 clist->undo_unselection = NULL;
788 visible = gtk_ctree_is_viewable (ctree, node);
790 /* clist->row_list_end unlinked ? */
791 if (visible && (GTK_CTREE_NODE_NEXT (node) == NULL ||
792 (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node,
793 GTK_CTREE_NODE (clist->row_list_end)))))
794 clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
798 level = GTK_CTREE_ROW (node)->level;
799 work = GTK_CTREE_NODE_NEXT (node);
800 while (work && GTK_CTREE_ROW (work)->level > level) {
801 work = GTK_CTREE_NODE_NEXT (work);
806 clist->rows -= (rows + 1);
808 if (update_focus_row) {
811 pos = g_list_position (clist->row_list, (GList *)node);
812 if (pos + rows < clist->focus_row)
813 clist->focus_row -= (rows + 1);
814 else if (pos <= clist->focus_row) {
815 if (!GTK_CTREE_ROW (node)->sibling)
816 clist->focus_row = MAX (pos - 1, 0);
818 clist->focus_row = pos;
820 clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
822 clist->undo_anchor = clist->focus_row;
827 list = (GList *)GTK_CTREE_NODE_PREV (work);
829 list = (GList *)work;
830 list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
833 if (GTK_CTREE_NODE_PREV (node) &&
834 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) {
835 list = (GList *)GTK_CTREE_NODE_PREV (node);
836 list->next = (GList *)work;
840 parent = GTK_CTREE_ROW (node)->parent;
842 if (GTK_CTREE_ROW (parent)->children == node) {
843 GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
844 if (!GTK_CTREE_ROW (parent)->children)
845 gtk_ctree_collapse (ctree, parent);
848 GtkCTreeNode *sibling;
850 sibling = GTK_CTREE_ROW (parent)->children;
851 while (GTK_CTREE_ROW (sibling)->sibling != node)
852 sibling = GTK_CTREE_ROW (sibling)->sibling;
853 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
857 if (clist->row_list == (GList *)node)
858 clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
860 GtkCTreeNode *sibling;
862 sibling = GTK_CTREE_NODE (clist->row_list);
863 while (GTK_CTREE_ROW (sibling)->sibling != node)
864 sibling = GTK_CTREE_ROW (sibling)->sibling;
865 GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
871 gtk_ctree_link (GtkCTree *ctree,
873 GtkCTreeNode *parent,
874 GtkCTreeNode *sibling,
875 gboolean update_focus_row)
881 gboolean visible = FALSE;
885 g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
886 g_return_if_fail (node != NULL);
887 g_return_if_fail (node != sibling);
888 g_return_if_fail (node != parent);
890 clist = GTK_CLIST (ctree);
892 if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
893 GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
895 g_list_free (clist->undo_selection);
896 g_list_free (clist->undo_unselection);
897 clist->undo_selection = NULL;
898 clist->undo_unselection = NULL;
901 for (rows = 1, list_end = (GList *)node; list_end->next;
902 list_end = list_end->next)
905 GTK_CTREE_ROW (node)->parent = parent;
906 GTK_CTREE_ROW (node)->sibling = sibling;
908 if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
909 GTK_CTREE_ROW (parent)->expanded))) {
915 work = (GList *)(GTK_CTREE_ROW (parent)->children);
917 work = clist->row_list;
920 if (work != (GList *)sibling) {
921 while (GTK_CTREE_ROW (work)->sibling != sibling)
922 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
923 GTK_CTREE_ROW (work)->sibling = node;
926 if (sibling == GTK_CTREE_NODE (clist->row_list))
927 clist->row_list = (GList *) node;
928 if (GTK_CTREE_NODE_PREV (sibling) &&
929 GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) {
930 list = (GList *)GTK_CTREE_NODE_PREV (sibling);
931 list->next = (GList *)node;
934 list = (GList *)node;
935 list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
936 list_end->next = (GList *)sibling;
937 list = (GList *)sibling;
938 list->prev = list_end;
939 if (parent && GTK_CTREE_ROW (parent)->children == sibling)
940 GTK_CTREE_ROW (parent)->children = node;
945 while (GTK_CTREE_ROW (work)->sibling)
946 work = (GList *)(GTK_CTREE_ROW (work)->sibling);
947 GTK_CTREE_ROW (work)->sibling = node;
949 /* find last visible child of sibling */
950 work = (GList *) gtk_ctree_last_visible (ctree,
951 GTK_CTREE_NODE (work));
953 list_end->next = work->next;
955 list = work->next->prev = list_end;
956 work->next = (GList *)node;
957 list = (GList *)node;
962 GTK_CTREE_ROW (parent)->children = node;
963 list = (GList *)node;
964 list->prev = (GList *)parent;
965 if (GTK_CTREE_ROW (parent)->expanded) {
966 list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
967 if (GTK_CTREE_NODE_NEXT(parent)) {
968 list = (GList *)GTK_CTREE_NODE_NEXT (parent);
969 list->prev = list_end;
971 list = (GList *)parent;
972 list->next = (GList *)node;
975 list_end->next = NULL;
978 clist->row_list = (GList *)node;
979 list = (GList *)node;
981 list_end->next = NULL;
986 gtk_ctree_pre_recursive (ctree, node, tree_update_level, NULL);
988 if (clist->row_list_end == NULL ||
989 clist->row_list_end->next == (GList *)node)
990 clist->row_list_end = list_end;
992 if (visible && update_focus_row) {
995 pos = g_list_position (clist->row_list, (GList *)node);
997 if (pos <= clist->focus_row) {
998 clist->focus_row += rows;
999 clist->undo_anchor = clist->focus_row;
1005 tree_update_level (GtkCTree *ctree,
1012 if (GTK_CTREE_ROW (node)->parent)
1013 GTK_CTREE_ROW (node)->level =
1014 GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
1016 GTK_CTREE_ROW (node)->level = 1;
1019 static GtkCTreeNode *
1020 gtk_ctree_last_visible (GtkCTree *ctree,
1028 work = GTK_CTREE_ROW (node)->children;
1030 if (!work || !GTK_CTREE_ROW (node)->expanded)
1033 while (GTK_CTREE_ROW (work)->sibling)
1034 work = GTK_CTREE_ROW (work)->sibling;
1036 return gtk_ctree_last_visible (ctree, work);
1039 void gtk_sctree_reanchor (GtkSCTree *sctree, GtkCTreeNode *node)
1041 g_return_if_fail (sctree != NULL);
1042 g_return_if_fail (node != NULL);
1043 sctree->anchor_row = node;