diff options
author | Lars Hamann <lars@src.gnome.org> | 1998-07-15 23:40:00 +0000 |
---|---|---|
committer | Lars Hamann <lars@src.gnome.org> | 1998-07-15 23:40:00 +0000 |
commit | 8b9b7b9d04c1f11118f28a9ec7b4c65a7a3f967c (patch) | |
tree | c85c8864d97e7306662c535a3680878f103376cc /gtk/gtkctree.c | |
parent | b6656088162e00c77f9d84f96e5721c0b84dd5ec (diff) | |
download | gtk+-8b9b7b9d04c1f11118f28a9ec7b4c65a7a3f967c.tar.gz |
Added focus handling, horizontal and vertical autoscrolling, extended
* gtk/gtkctree.h :
* gtk/gtkctree.c :
Added focus handling, horizontal and vertical autoscrolling,
extended Selection Mode, key bindings
Added gtk_ctree_toggle_expansion & gtk_ctree_toggle_expansion_recursive
Changed gtk_ctree_scroll_to to gtk_ctree_moveto.
Removed gtk_ctree_clear.
* gtk/gtkclist.h :
* gtk/gtkclist.c :
Added focus handling, horizontal and vertical autoscrolling,
extended Selection Mode, key bindings
Diffstat (limited to 'gtk/gtkctree.c')
-rw-r--r-- | gtk/gtkctree.c | 1226 |
1 files changed, 945 insertions, 281 deletions
diff --git a/gtk/gtkctree.c b/gtk/gtkctree.c index 5e001c1782..503b163fe6 100644 --- a/gtk/gtkctree.c +++ b/gtk/gtkctree.c @@ -23,7 +23,9 @@ #include <stdlib.h> #include "gtkctree.h" +#include "gtkbindings.h" #include <gdk/gdkx.h> +#include <gdk/gdkkeysyms.h> #define PM_SIZE 8 #define TAB_SIZE (PM_SIZE + 6) @@ -41,6 +43,9 @@ + (clist)->hoffset) #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x) +#define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (GTK_OBJECT (_widget_)->klass) + + static void gtk_ctree_class_init (GtkCTreeClass *klass); static void gtk_ctree_init (GtkCTree *ctree); static void gtk_ctree_destroy (GtkObject *object); @@ -102,6 +107,7 @@ static void tree_delete (GtkCTree *ctree, static void tree_delete_row (GtkCTree *ctree, GList *node, gpointer data); +static void real_clear (GtkCList *clist); static void tree_update_level (GtkCTree *ctree, GList *node, gpointer data); @@ -111,12 +117,27 @@ static void tree_select (GtkCTree *ctree, static void tree_unselect (GtkCTree *ctree, GList *node, gpointer data); +static void real_select_all (GtkCList *clist); +static void real_unselect_all (GtkCList *clist); static void tree_expand (GtkCTree *ctree, GList *node, gpointer data); static void tree_collapse (GtkCTree *ctree, GList *node, gpointer data); +static void tree_toggle_expansion (GtkCTree *ctree, + GList *node, + gpointer data); +static void change_focus_row_expansion (GtkCTree *ctree, + GtkCTreeExpansion expansion); +static void real_select_row (GtkCList *clist, + gint row, + gint column, + GdkEvent *event); +static void real_unselect_row (GtkCList *clist, + gint row, + gint column, + GdkEvent *event); static void real_tree_select (GtkCTree *ctree, GList *node, gint column); @@ -137,9 +158,11 @@ static void real_tree_move (GtkCTree *ctree, static void gtk_ctree_link (GtkCTree *ctree, GList *node, GList *parent, - GList *sibling); + GList *sibling, + gboolean update_focus_row); static void gtk_ctree_unlink (GtkCTree *ctree, - GList *node); + GList *node, + gboolean update_focus_row); static GList * gtk_ctree_last_visible (GtkCTree *ctree, GList *node); static void gtk_ctree_marshal_signal_1 (GtkObject *object, @@ -154,6 +177,10 @@ static void gtk_ctree_marshal_signal_3 (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args); +static void gtk_ctree_marshal_signal_4 (GtkObject *object, + GtkSignalFunc func, + gpointer func_data, + GtkArg *args); static gboolean ctree_is_hot_spot (GtkCTree *ctree, GList *node, gint row, @@ -166,6 +193,23 @@ static gint default_compare (GtkCTree *ctree, const GList *node1, const GList *node2); + + +static void fake_unselect_all (GtkCList *clist, + gint row); +static GList* selection_find (GtkCList *clist, + gint row_number, + GList *row_list_element); +static void resync_selection (GtkCList *clist, + GdkEvent *event); +static void real_undo_selection (GtkCList *clist); +static void select_row_recursive (GtkCTree *ctree, + GList *node, + gpointer data); + + + + enum { TREE_SELECT_ROW, @@ -173,6 +217,7 @@ enum TREE_EXPAND, TREE_COLLAPSE, TREE_MOVE, + CHANGE_FOCUS_ROW_EXPANSION, LAST_SIGNAL }; @@ -191,6 +236,10 @@ typedef void (*GtkCTreeSignal3) (GtkObject *object, GList *arg1, gpointer data); +typedef void (*GtkCTreeSignal4) (GtkObject *object, + GtkCTreeExpansion arg1, + gpointer data); + static GtkCListClass *parent_class = NULL; static GtkContainerClass *container_class = NULL; @@ -264,6 +313,19 @@ gtk_ctree_marshal_signal_3 (GtkObject *object, } static void +gtk_ctree_marshal_signal_4 (GtkObject *object, + GtkSignalFunc func, + gpointer func_data, + GtkArg *args) +{ + GtkCTreeSignal4 rfunc; + + rfunc = (GtkCTreeSignal4) func; + + (*rfunc) (object, GTK_VALUE_ENUM (args[0]), func_data); +} + +static void gtk_ctree_class_init (GtkCTreeClass *klass) { GtkObjectClass *object_class; @@ -314,6 +376,14 @@ gtk_ctree_class_init (GtkCTreeClass *klass) gtk_ctree_marshal_signal_2, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_POINTER); + ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] = + gtk_signal_new ("change_focus_row_expansion", + GTK_RUN_LAST | GTK_RUN_ACTION, + object_class->type, + GTK_SIGNAL_OFFSET (GtkCTreeClass, + change_focus_row_expansion), + gtk_ctree_marshal_signal_4, + GTK_TYPE_NONE, 1, GTK_TYPE_ENUM); gtk_object_class_add_signals (object_class, ctree_signals, LAST_SIGNAL); @@ -325,16 +395,70 @@ gtk_ctree_class_init (GtkCTreeClass *klass) widget_class->button_release_event = gtk_ctree_button_release; widget_class->motion_notify_event = gtk_ctree_button_motion; - clist_class->select_row = NULL; - clist_class->unselect_row = NULL; + clist_class->select_row = real_select_row; + clist_class->unselect_row = real_unselect_row; + clist_class->undo_selection = real_undo_selection; + clist_class->resync_selection = resync_selection; + clist_class->selection_find = selection_find; clist_class->click_column = NULL; clist_class->draw_row = draw_row; + clist_class->clear = real_clear; + clist_class->select_all = real_select_all; + clist_class->unselect_all = real_unselect_all; + clist_class->fake_unselect_all = fake_unselect_all; klass->tree_select_row = real_tree_select; klass->tree_unselect_row = real_tree_unselect; klass->tree_expand = real_tree_expand; klass->tree_collapse = real_tree_collapse; klass->tree_move = real_tree_move; + klass->change_focus_row_expansion = change_focus_row_expansion; + + { + GtkBindingSet *binding_set; + + binding_set = gtk_binding_set_by_class (klass); + gtk_binding_entry_add_signal (binding_set, + '+', GDK_SHIFT_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_EXPAND); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Add, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_EXPAND_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + '-', 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Subtract, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_COLLAPSE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Subtract, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE); + gtk_binding_entry_add_signal (binding_set, + '=', 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Multiply, 0, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, GTK_CTREE_EXPANSION_TOGGLE); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Multiply, GDK_CONTROL_MASK, + "change_focus_row_expansion", 1, + GTK_TYPE_ENUM, + GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE); + } + } static void @@ -344,7 +468,6 @@ gtk_ctree_init (GtkCTree *ctree) ctree->drag_icon = NULL; ctree->tree_indent = 20; ctree->tree_column = 0; - ctree->selection_last = NULL; ctree->drag_row = -1; ctree->drag_source = NULL; ctree->drag_target = NULL; @@ -371,7 +494,7 @@ gtk_ctree_destroy (GtkObject *object) GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN); - gtk_ctree_clear (GTK_CTREE (object)); + gtk_clist_clear (GTK_CLIST (object)); if (clist->vscrollbar) { @@ -458,6 +581,7 @@ gtk_ctree_button_press (GtkWidget *widget, if (event->window == clist->clist_window) { + gboolean collapse_expand = FALSE; GList *work; gint x; gint y; @@ -466,40 +590,105 @@ gtk_ctree_button_press (GtkWidget *widget, x = event->x; y = event->y; - if (gtk_clist_get_selection_info (clist, x, y, &row, &column)) - { - if (event->button == 1) - ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y); - work = g_list_nth (clist->row_list, row); + if (!gtk_clist_get_selection_info (clist, x, y, &row, &column)) + return FALSE; + + if (event->button == 2) + ctree->drag_row = - 1 - ROW_FROM_YPIXEL (clist, y); + + work = g_list_nth (clist->row_list, row); - if (GTK_CTREE_ROW (work)->children && - (event->type == GDK_2BUTTON_PRESS || - (ctree_is_hot_spot (ctree, work, row, x, y) - && event->button == 1))) - { - if (GTK_CTREE_ROW (work)->expanded) - gtk_ctree_collapse (ctree, work); - else - gtk_ctree_expand (ctree, work); - } - else if (ctree->reorderable && event->button == 1 && !ctree->in_drag) + if (ctree->reorderable && event->button == 2 && !ctree->in_drag && + clist->anchor == -1) + { + gdk_pointer_grab (event->window, FALSE, + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, + NULL, NULL, event->time); + ctree->in_drag = TRUE; + ctree->drag_source = work; + ctree->drag_target = NULL; + return FALSE; + } + else if (event->button == 1 && + (GTK_CTREE_ROW (work)->children && + (event->type == GDK_2BUTTON_PRESS || + ctree_is_hot_spot (ctree, work, row, x, y)))) + { + if (GTK_CTREE_ROW (work)->expanded) + gtk_ctree_collapse (ctree, work); + else + gtk_ctree_expand (ctree, work); + + collapse_expand = TRUE; + } + if (event->button == 1) + { + gint old_row = clist->focus_row; + gboolean no_focus_row = FALSE; + + switch (clist->selection_mode) { - gdk_pointer_grab (event->window, FALSE, + case GTK_SELECTION_MULTIPLE: + case GTK_SELECTION_SINGLE: + if (!collapse_expand) + break; + + if (clist->focus_row == -1) + { + old_row = row; + no_focus_row = TRUE; + } + + GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION); + gdk_pointer_grab (clist->clist_window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); - ctree->in_drag = TRUE; - ctree->drag_source = work; - ctree->drag_target = NULL; + + if (GTK_CLIST_ADD_MODE (clist)) + { + GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE); + if (GTK_WIDGET_HAS_FOCUS (widget)) + { + gtk_widget_draw_focus (widget); + gdk_gc_set_line_attributes (clist->xor_gc, 1, + GDK_LINE_SOLID, 0, 0); + clist->focus_row = row; + gtk_widget_draw_focus (widget); + } + else + { + gdk_gc_set_line_attributes (clist->xor_gc, 1, + GDK_LINE_SOLID, 0, 0); + clist->focus_row = row; + } + } + else if (row != clist->focus_row) + { + if (GTK_WIDGET_HAS_FOCUS (widget)) + { + gtk_widget_draw_focus (widget); + clist->focus_row = row; + gtk_widget_draw_focus (widget); + } + else + clist->focus_row = row; + } + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + return FALSE; + + default: + break; } } - return FALSE; } - return - (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event); + return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); } static gint @@ -520,11 +709,12 @@ gtk_ctree_button_motion (GtkWidget *widget, ctree = GTK_CTREE (widget); clist = GTK_CLIST (widget); - if (!ctree->reorderable) - return - (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event); + if (GTK_CLIST_IN_DRAG (clist)) + return GTK_WIDGET_CLASS (parent_class)->motion_notify_event + (widget, event); - if (event->window == clist->clist_window && ctree->in_drag) + if (event->window == clist->clist_window && + ctree->in_drag && ctree->reorderable) { GdkModifierType modmask; gint root_x; @@ -540,8 +730,7 @@ gtk_ctree_button_motion (GtkWidget *widget, y >= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) && y <= ROW_TOP_YPIXEL (clist, -ctree->drag_row-1) + clist->row_height) return - (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) - (widget, event); + GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); if (ctree->use_icons) { @@ -585,7 +774,7 @@ gtk_ctree_button_motion (GtkWidget *widget, if (y < 0 || y > clist->clist_window_height || ROW_TOP_YPIXEL (clist, row + 1) > clist->clist_window_height || row >= clist->rows) - return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) + return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4) @@ -632,8 +821,7 @@ gtk_ctree_button_motion (GtkWidget *widget, } } } - return - (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event); + return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); } static gint @@ -650,7 +838,7 @@ gtk_ctree_button_release (GtkWidget *widget, ctree = GTK_CTREE (widget); clist = GTK_CLIST (widget); - if (event->button == 1) + if (event->button == 2 && clist->anchor == -1) { gdk_pointer_ungrab (event->time); ctree->in_drag = FALSE; @@ -672,40 +860,13 @@ gtk_ctree_button_release (GtkWidget *widget, draw_xor_line (ctree); ctree->drag_row = -1; } - else - { - if (event->window == clist->clist_window) - { - gint row; - gint column; - GList *work; - - if (gtk_clist_get_selection_info (clist, event->x, event->y, - &row, &column)) - if (row == - (ctree->drag_row + 1) && - (work = g_list_nth (clist->row_list, row))) - { - if (GTK_CTREE_ROW (work)->children && - ctree_is_hot_spot (ctree, work, row, event->x, - event->y)) - return (* GTK_WIDGET_CLASS (parent_class) - ->button_release_event) (widget, event); - tree_toggle_selection (ctree, work, column); - } - return FALSE; - } - return - (* GTK_WIDGET_CLASS (parent_class)->button_release_event) - (widget, event); - } /* nop if out of bounds / source == target */ if (event->x < 0 || event->y < -3 || event->x > clist->clist_window_width || event->y > clist->clist_window_height + 3 || ctree->drag_target == ctree->drag_source) - return - (* GTK_WIDGET_CLASS (parent_class)->button_release_event) + return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); if (!GTK_CTREE_ROW (ctree->drag_source)->children || @@ -746,8 +907,24 @@ gtk_ctree_button_release (GtkWidget *widget, ctree->drag_source = NULL; ctree->drag_target = NULL; } - return - (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event); + else if (event->button == 1 && GTK_CLIST_DRAG_SELECTION (clist) && + (clist->selection_mode == GTK_SELECTION_SINGLE || + clist->selection_mode == GTK_SELECTION_MULTIPLE)) + { + gint row; + gint column; + GList *work; + + if (gtk_clist_get_selection_info + (clist, event->x, event->y, &row, &column)) + { + if (clist->anchor == clist->focus_row && + (work = g_list_nth (clist->row_list, row))) + tree_toggle_selection (ctree, work, column); + } + clist->anchor = -1; + } + return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); } static void @@ -2246,6 +2423,26 @@ draw_row (GtkCList *clist, } } } + if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget)) + { + if (area) + { + if (gdk_rectangle_intersect (area, &row_rectangle, + &intersect_rectangle)) + { + gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle); + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, + row_rectangle.x, row_rectangle.y, + row_rectangle.width - 1, + row_rectangle.height - 1); + gdk_gc_set_clip_rectangle (clist->xor_gc, NULL); + } + } + else + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, + row_rectangle.x, row_rectangle.y, + row_rectangle.width - 1, row_rectangle.height - 1); + } } static void @@ -2268,8 +2465,8 @@ tree_draw_row (GtkCTree *ctree, num++; } if (gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE) - (GTK_CLIST_CLASS (GTK_OBJECT (clist)->klass)->draw_row) - (clist, NULL, num, &(GTK_CTREE_ROW (row)->row)); + GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, num, + GTK_CLIST_ROW (row)); } } @@ -2297,11 +2494,12 @@ static void gtk_ctree_link (GtkCTree *ctree, GList *node, GList *parent, - GList *sibling) + GList *sibling, + gboolean update_focus_row) { GtkCList *clist; GList *list_end; - gint visible = TRUE; + gboolean visible = FALSE; gint rows = 0; g_return_if_fail (!sibling || GTK_CTREE_ROW (sibling)->parent == parent); @@ -2311,20 +2509,30 @@ gtk_ctree_link (GtkCTree *ctree, clist = GTK_CLIST (ctree); + if (update_focus_row && clist->selection_mode == GTK_SELECTION_BROWSE) + { + if (clist->anchor != -1) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + } + for (rows = 1, list_end = node; list_end->next; list_end = list_end->next) rows++; GTK_CTREE_ROW (node)->parent = parent; GTK_CTREE_ROW (node)->sibling = sibling; - if (parent) + if (!parent || (parent && (gtk_ctree_is_visible (ctree, parent) && + GTK_CTREE_ROW (parent)->expanded))) { - if ((visible = gtk_ctree_is_visible (ctree, parent)) && - GTK_CTREE_ROW (parent)->expanded) - clist->rows += rows; + visible = TRUE; + clist->rows += rows; } - else - clist->rows += rows; + if (sibling) { @@ -2407,13 +2615,24 @@ gtk_ctree_link (GtkCTree *ctree, if (clist->row_list_end == NULL || clist->row_list_end->next == node) clist->row_list_end = list_end; - if (!GTK_CLIST_FROZEN (clist) && visible) - gtk_clist_thaw (clist); + if (visible && update_focus_row) + { + gint pos; + + pos = g_list_position (clist->row_list, node); + + if (pos <= clist->focus_row) + { + clist->focus_row += rows; + clist->undo_anchor = clist->focus_row; + } + } } static void gtk_ctree_unlink (GtkCTree *ctree, - GList *node) + GList *node, + gboolean update_focus_row) { GtkCList *clist; gint rows; @@ -2428,6 +2647,17 @@ gtk_ctree_unlink (GtkCTree *ctree, clist = GTK_CLIST (ctree); + if (update_focus_row && clist->selection_mode == GTK_SELECTION_BROWSE) + { + if (clist->anchor != -1) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + } + visible = gtk_ctree_is_visible (ctree, node); /* clist->row_list_end unlinked ? */ @@ -2446,6 +2676,24 @@ gtk_ctree_unlink (GtkCTree *ctree, rows++; } + if (visible) + { + clist->rows -= (rows + 1); + + if (update_focus_row) + { + gint pos; + + pos = g_list_position (clist->row_list, node); + if (pos + rows + 1 < clist->focus_row) + clist->focus_row -= (rows + 1); + else if (pos <= clist->focus_row) + clist->focus_row = pos - 1; + clist->undo_anchor = clist->focus_row; + } + } + + if (work) { work->prev->next = NULL; @@ -2499,14 +2747,6 @@ gtk_ctree_unlink (GtkCTree *ctree, GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling; } } - - if (visible) - { - clist->rows -= (rows + 1); - - if (!GTK_CLIST_FROZEN (clist)) - gtk_clist_thaw (clist); - } } static void @@ -2534,6 +2774,17 @@ real_tree_move (GtkCTree *ctree, clist = GTK_CLIST (ctree); + if (clist->selection_mode == GTK_SELECTION_BROWSE) + { + if (clist->anchor != -1) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + } + if (ctree->auto_sort) { if (new_parent == GTK_CTREE_ROW (node)->parent) @@ -2558,23 +2809,87 @@ real_tree_move (GtkCTree *ctree, thaw = TRUE; } - gtk_ctree_unlink (ctree, node); - gtk_ctree_link (ctree, node, new_parent, new_sibling); + work = NULL; + if (gtk_ctree_is_visible (ctree, node) || + gtk_ctree_is_visible (ctree, new_sibling)) + work = g_list_nth (clist->row_list, clist->focus_row); + + gtk_ctree_unlink (ctree, node, FALSE); + gtk_ctree_link (ctree, node, new_parent, new_sibling, FALSE); + + if (work) + { + while (work && !gtk_ctree_is_visible (ctree, work)) + work = GTK_CTREE_ROW (work)->parent; + clist->focus_row = g_list_position (clist->row_list, work); + clist->undo_anchor = clist->focus_row; + } if (thaw) gtk_clist_thaw (clist); } +static void +change_focus_row_expansion (GtkCTree *ctree, + GtkCTreeExpansion action) +{ + GtkCList *clist; + GList *node; + + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + + clist = GTK_CLIST (ctree); + + if (gdk_pointer_is_grabbed ()) + return; + + if (!(node = g_list_nth (clist->row_list, clist->focus_row)) || + GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children)) + return; + + switch (action) + { + case GTK_CTREE_EXPANSION_EXPAND: + gtk_ctree_expand (ctree, node); + break; + case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE: + gtk_ctree_expand_recursive (ctree, node); + break; + case GTK_CTREE_EXPANSION_COLLAPSE: + gtk_ctree_collapse (ctree, node); + break; + case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE: + gtk_ctree_collapse_recursive (ctree, node); + break; + case GTK_CTREE_EXPANSION_TOGGLE: + gtk_ctree_toggle_expansion (ctree, node); + break; + case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE: + gtk_ctree_toggle_expansion_recursive (ctree, node); + break; + } +} + static void real_tree_expand (GtkCTree *ctree, GList *node) { + GtkCList *clist; GList *work; gint level; + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + if (!node || GTK_CTREE_ROW (node)->expanded) return; + clist = GTK_CLIST (ctree); + + if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CTREE_ROW (node)->expanded = TRUE; level = GTK_CTREE_ROW (node)->level; @@ -2591,7 +2906,11 @@ real_tree_expand (GtkCTree *ctree, work = GTK_CTREE_ROW (node)->children; if (work) { + GtkCList *clist; gint tmp = 0; + gint row; + + clist = GTK_CLIST (ctree); while (work->next) { @@ -2604,15 +2923,18 @@ real_tree_expand (GtkCTree *ctree, if (node->next) node->next->prev = work; else - GTK_CLIST (ctree)->row_list_end = work; + clist->row_list_end = work; node->next = GTK_CTREE_ROW (node)->children; if (gtk_ctree_is_visible (ctree, node)) { - GTK_CLIST (ctree)->rows += tmp + 1; + row = g_list_position (clist->row_list, node); + if (row < clist->focus_row) + clist->focus_row += tmp + 1; + clist->rows += tmp + 1; if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (GTK_CLIST (ctree)); + gtk_clist_thaw (clist); } } } @@ -2621,12 +2943,21 @@ static void real_tree_collapse (GtkCTree *ctree, GList *node) { + GtkCList *clist; GList *work; gint level; + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + if (!node || !GTK_CTREE_ROW (node)->expanded) return; + clist = GTK_CLIST (ctree); + + if (clist->selection_mode == GTK_SELECTION_EXTENDED && clist->anchor >= 0) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + GTK_CTREE_ROW (node)->expanded = FALSE; level = GTK_CTREE_ROW (node)->level; @@ -2643,7 +2974,11 @@ real_tree_collapse (GtkCTree *ctree, work = GTK_CTREE_ROW (node)->children; if (work) { + GtkCList *clist; gint tmp = 0; + gint row; + + clist = GTK_CLIST (ctree); while (work && GTK_CTREE_ROW (work)->level > level) { @@ -2660,14 +2995,17 @@ real_tree_collapse (GtkCTree *ctree, else { node->next = NULL; - GTK_CLIST (ctree)->row_list_end = node; + clist->row_list_end = node; } if (gtk_ctree_is_visible (ctree, node)) { - GTK_CLIST (ctree)->rows -= tmp; + row = g_list_position (clist->row_list, node); + if (row < clist->focus_row) + clist->focus_row -= tmp; + clist->rows -= tmp; if (!GTK_CLIST_FROZEN (ctree)) - gtk_clist_thaw (GTK_CLIST (ctree)); + gtk_clist_thaw (clist); } } } @@ -2812,8 +3150,8 @@ tree_delete (GtkCTree *ctree, work = g_list_find (clist->selection, node); if (work) { - if (ctree->selection_last && ctree->selection_last == work) - ctree->selection_last = ctree->selection_last->prev; + if (clist->selection_end && clist->selection_end == work) + clist->selection_end = clist->selection_end->prev; clist->selection = g_list_remove (clist->selection, node); } } @@ -2886,6 +3224,22 @@ tree_collapse (GtkCTree *ctree, data); } +static void +tree_toggle_expansion (GtkCTree *ctree, + GList *node, + gpointer data) +{ + if (!node) + return; + + if (GTK_CTREE_ROW (node)->expanded) + gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node, + data); + else + gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node, + data); +} + static GtkCTreeRow * row_new (GtkCTree *ctree) { @@ -3003,12 +3357,46 @@ cell_empty (GtkCList *clist, } static void +real_select_row (GtkCList *clist, + gint row, + gint column, + GdkEvent *event) +{ + GList *node; + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); + + if ((node = g_list_nth (clist->row_list, row))) + gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW], + node, event); +} + +static void +real_unselect_row (GtkCList *clist, + gint row, + gint column, + GdkEvent *event) +{ + GList *node; + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); + + if ((node = g_list_nth (clist->row_list, row))) + gtk_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW], + node, event); +} + +static void real_tree_select (GtkCTree *ctree, GList *node, gint column) { GtkCList *clist; - GList *selection; + GList *list; + GList *sel_row; + gboolean node_selected; g_return_if_fail (ctree != NULL); @@ -3017,15 +3405,12 @@ real_tree_select (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) - return; - - if (clist->selection_mode == GTK_SELECTION_SINGLE || - clist->selection_mode == GTK_SELECTION_BROWSE) + switch (clist->selection_mode) { - GList *list; - GList *sel_row; + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_BROWSE: + node_selected = FALSE; list = clist->selection; while (list) @@ -3033,27 +3418,29 @@ real_tree_select (GtkCTree *ctree, sel_row = list->data; list = list->next; - if (node != sel_row && - GTK_CTREE_ROW (sel_row)->row.state == GTK_STATE_SELECTED) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_UNSELECT_ROW], sel_row, - column); + if (node == sel_row) + node_selected = TRUE; + else + gtk_signal_emit (GTK_OBJECT (ctree), + ctree_signals[TREE_UNSELECT_ROW], sel_row, column); } + + if (node_selected) + return; + + default: + break; } GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; - selection = g_list_alloc (); - selection->data = node; - if (ctree->selection_last) + if (!clist->selection) { - ctree->selection_last->next = selection; - selection->prev = ctree->selection_last; + clist->selection = g_list_append (clist->selection, node); + clist->selection_end = clist->selection; } - else - clist->selection = selection; - - ctree->selection_last = selection; + else + clist->selection_end = g_list_append (clist->selection_end, node)->next; tree_draw_row (ctree, node); } @@ -3070,15 +3457,16 @@ real_tree_unselect (GtkCTree *ctree, if (!node) return; + clist = GTK_CLIST (ctree); + if (GTK_CTREE_ROW (node)->row.state != GTK_STATE_SELECTED) return; - clist = GTK_CLIST (ctree); - - if (ctree->selection_last && ctree->selection_last->data == node) - ctree->selection_last = ctree->selection_last->prev; + if (clist->selection_end && clist->selection_end->data == node) + clist->selection_end = clist->selection_end->prev; clist->selection = g_list_remove (clist->selection, node); + GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL; tree_draw_row (ctree, node); @@ -3089,7 +3477,14 @@ tree_toggle_selection (GtkCTree *ctree, GList *node, gint column) { - switch (GTK_CLIST (ctree)->selection_mode) + GtkCList *clist; + + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + + clist = GTK_CLIST (ctree); + + switch (clist->selection_mode) { case GTK_SELECTION_SINGLE: case GTK_SELECTION_MULTIPLE: @@ -3109,10 +3504,117 @@ tree_toggle_selection (GtkCTree *ctree, case GTK_SELECTION_EXTENDED: break; + } +} + +static void +select_row_recursive (GtkCTree *ctree, + GList *node, + gpointer data) +{ + if (!node || GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + return; + + GTK_CLIST (ctree)->undo_unselection = + g_list_prepend (GTK_CLIST (ctree)->undo_unselection, node); + gtk_ctree_select (ctree, node); +} + +static void +real_select_all (GtkCList *clist) +{ + GtkCTree *ctree; + GList *node; + gboolean thaw = FALSE; + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); + + ctree = GTK_CTREE (clist); + + switch (clist->selection_mode) + { + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_BROWSE: + return; + + case GTK_SELECTION_EXTENDED: + + if (!GTK_CLIST_FROZEN (clist)) + { + gtk_clist_freeze (clist); + thaw = TRUE; + } + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + + clist->anchor_state = GTK_STATE_SELECTED; + clist->anchor = -1; + clist->drag_pos = -1; + clist->undo_anchor = clist->focus_row; + + for (node = clist->row_list; node; node = node->next) + gtk_ctree_pre_recursive (ctree, node, select_row_recursive, NULL); + + if (thaw) + gtk_clist_thaw (clist); + break; + + case GTK_SELECTION_MULTIPLE: + gtk_ctree_select_recursive (ctree, NULL); + break;; + } +} + +static void +real_unselect_all (GtkCList *clist) +{ + GtkCTree *ctree; + GList *list; + GList *node; + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); + + ctree = GTK_CTREE (clist); + + switch (clist->selection_mode) + { + case GTK_SELECTION_BROWSE: + if (clist->focus_row >= 0) + { + gtk_ctree_select + (ctree, g_list_nth (clist->row_list, clist->focus_row)); + return; + } + break; + + case GTK_SELECTION_EXTENDED: + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + + clist->anchor = -1; + clist->drag_pos = -1; + clist->undo_anchor = clist->focus_row; + break; default: break; } + + list = clist->selection; + + while (list) + { + node = list->data; + list = list->next; + gtk_ctree_unselect (ctree, node); + } } static gboolean @@ -3290,7 +3792,10 @@ gtk_ctree_insert (GtkCTree *ctree, sibling = GTK_CTREE_ROW (sibling)->sibling; } - gtk_ctree_link (ctree, node, parent, sibling); + gtk_ctree_link (ctree, node, parent, sibling, TRUE); + + if (!GTK_CLIST_FROZEN (clist)) + gtk_clist_thaw (clist); return node; } @@ -3315,55 +3820,40 @@ gtk_ctree_remove (GtkCTree *ctree, if (node) { - gtk_ctree_unlink (ctree, node); - gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete), + gtk_ctree_unlink (ctree, node, TRUE); + gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete), NULL); } else - { - GList *work; - GList *ptr; - - work = clist->row_list; - clist->row_list = NULL; - clist->row_list_end = NULL; - clist->rows = 0; - - while (work) - { - ptr = work; - work = GTK_CTREE_ROW (work)->sibling; - gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete), - NULL); - } - } + gtk_clist_clear (clist); if (thaw) gtk_clist_thaw (clist); } -void -gtk_ctree_clear (GtkCTree *ctree) +static void +real_clear (GtkCList *clist) { - GtkCList *clist; + GtkCTree *ctree; GList *work; GList *ptr; - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); - clist = GTK_CLIST (ctree); + ctree = GTK_CTREE (clist); - /* free up the selection list */ - g_list_free (clist->selection); - clist->selection = NULL; - ctree->selection_last = NULL; + ctree->drag_row = -1; + ctree->drag_rect = FALSE; + ctree->in_drag = FALSE; + ctree->drag_source = NULL; + ctree->drag_target = NULL; + ctree->drag_icon = NULL; /* remove all the rows */ work = clist->row_list; clist->row_list = NULL; clist->row_list_end = NULL; - clist->rows = 0; while (work) { @@ -3373,25 +3863,7 @@ gtk_ctree_clear (GtkCTree *ctree) NULL); } - clist->voffset = 0; - - ctree->drag_row = -1; - ctree->drag_rect = FALSE; - ctree->in_drag = FALSE; - ctree->drag_source = NULL; - ctree->drag_target = NULL; - ctree->drag_icon = NULL; - - /* zero-out the scrollbars */ - if (clist->vscrollbar) - { - GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0; - gtk_signal_emit_by_name - (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed"); - - if (!GTK_CLIST_FROZEN (clist)) - gtk_clist_thaw (clist); - } + (parent_class->clear) (clist); } @@ -3422,7 +3894,8 @@ gtk_ctree_post_recursive (GtkCTree *ctree, work = tmp; } - (* func) (ctree, node, data); + if (node) + func (ctree, node, data); } void @@ -3434,10 +3907,12 @@ gtk_ctree_pre_recursive (GtkCTree *ctree, GList *work; GList *tmp; - (* func) (ctree, node, data); if (node) - work = GTK_CTREE_ROW (node)->children; + { + work = GTK_CTREE_ROW (node)->children; + func (ctree, node, data); + } else work = GTK_CLIST (ctree)->row_list; @@ -3595,6 +4070,9 @@ gtk_ctree_expand (GtkCTree *ctree, g_return_if_fail (ctree != NULL); g_return_if_fail (node != NULL); + if (GTK_CTREE_ROW (node)->is_leaf) + return; + gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], node); } @@ -3609,7 +4087,7 @@ gtk_ctree_expand_recursive (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (node && !GTK_CTREE_ROW (node)->children) + if (node && GTK_CTREE_ROW (node)->is_leaf) return; if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && @@ -3632,6 +4110,9 @@ gtk_ctree_collapse (GtkCTree *ctree, g_return_if_fail (ctree != NULL); g_return_if_fail (node != NULL); + if (GTK_CTREE_ROW (node)->is_leaf) + return; + gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], node); } @@ -3644,11 +4125,11 @@ gtk_ctree_collapse_recursive (GtkCTree *ctree, g_return_if_fail (ctree != NULL); - clist = GTK_CLIST (ctree); - - if (node && !GTK_CTREE_ROW (node)->children) + if (node && GTK_CTREE_ROW (node)->is_leaf) return; + clist = GTK_CLIST (ctree); + if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && !GTK_CLIST_FROZEN (clist)) { @@ -3663,6 +4144,47 @@ gtk_ctree_collapse_recursive (GtkCTree *ctree, } void +gtk_ctree_toggle_expansion (GtkCTree *ctree, + GList *node) +{ + g_return_if_fail (ctree != NULL); + g_return_if_fail (node != NULL); + + if (GTK_CTREE_ROW (node)->is_leaf) + return; + + tree_toggle_expansion (ctree, node, NULL); +} + +void +gtk_ctree_toggle_expansion_recursive (GtkCTree *ctree, + GList *node) +{ + GtkCList *clist; + gboolean thaw = FALSE; + + g_return_if_fail (ctree != NULL); + + if (node && GTK_CTREE_ROW (node)->is_leaf) + return; + + clist = GTK_CLIST (ctree); + + if (((node && gtk_ctree_is_visible (ctree, node)) || !node) && + !GTK_CLIST_FROZEN (clist)) + { + gtk_clist_freeze (clist); + thaw = TRUE; + } + + gtk_ctree_post_recursive (ctree, node, + GTK_CTREE_FUNC (tree_toggle_expansion), NULL); + + if (thaw) + gtk_clist_thaw (clist); +} + +void gtk_ctree_select (GtkCTree *ctree, GList *node) { @@ -3708,8 +4230,9 @@ gtk_ctree_real_select_recursive (GtkCTree *ctree, clist = GTK_CLIST (ctree); - if (clist->selection_mode == GTK_SELECTION_EXTENDED || - (state && clist->selection_mode != GTK_SELECTION_MULTIPLE) || + if ((state && + (clist->selection_mode != GTK_SELECTION_MULTIPLE || + clist->selection_mode == GTK_SELECTION_EXTENDED)) || (!state && clist->selection_mode == GTK_SELECTION_BROWSE)) return; @@ -4053,53 +4576,6 @@ gtk_ctree_set_background (GtkCTree *ctree, } void -gtk_ctree_set_selection_mode (GtkCTree *ctree, - GtkSelectionMode mode) -{ - GtkCList *clist; - GList *selection; - GList *work; - gboolean thaw = FALSE; - - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); - - clist = GTK_CLIST (ctree); - - if (mode == clist->selection_mode) - return; - - clist->selection_mode = mode; - - if (mode == GTK_SELECTION_MULTIPLE) - return; - - selection = clist->selection; - if (selection && mode == GTK_SELECTION_BROWSE) - selection = selection->next; - - if (!selection) - return; - - if (!GTK_CLIST_FROZEN (clist)) - { - gtk_clist_freeze (clist); - thaw = TRUE; - } - - while (selection) - { - work = selection->data; - selection = selection->next; - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_UNSELECT_ROW], work); - } - - if (thaw) - gtk_clist_thaw (clist); -} - -void gtk_ctree_set_row_data (GtkCTree *ctree, GList *node, gpointer data) @@ -4131,62 +4607,27 @@ gtk_ctree_get_row_data (GtkCTree *ctree, } void -gtk_ctree_scroll_to (GtkCTree *ctree, - GList *node, - gint column, - gfloat row_align, - gfloat col_align) +gtk_ctree_moveto (GtkCTree *ctree, + GList *node, + gint column, + gfloat row_align, + gfloat col_align) { - gint x; - gint y; - gint row = 0; + gint row = -1; GtkCList *clist; - GList *work; - GtkAdjustment *adj; g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); clist = GTK_CLIST (ctree); - if (node && !gtk_ctree_is_visible (ctree, node)) - return; + while (node && !gtk_ctree_is_visible (ctree, node)) + node = GTK_CTREE_ROW (node)->parent; - /* adjust vertical scrollbar */ if (node) - { - adj = GTK_RANGE (clist->vscrollbar)->adjustment; - work = clist->row_list; - while (work && work != node) - { - work = work->next; - row++; - } - - if (!work) - return; - - y = ROW_TOP_YPIXEL (clist, row) - clist->voffset; - - y = y - row_align * (clist->clist_window_height - clist->row_height) - + (2 * row_align - 1) * CELL_SPACING; - - if (y + adj->page_size > adj->upper) - gtk_adjustment_set_value (adj, adj->upper - adj->page_size); - else - gtk_adjustment_set_value (adj, y); - } - - /* adjust horizontal scrollbar */ - if (column >= 0) - { - adj = GTK_RANGE (clist->hscrollbar)->adjustment; - x = COLUMN_LEFT (clist, column); - x = x - col_align * - (clist->clist_window_width - clist->column[column].area.width) - + (2 * col_align - 1) * COLUMN_INSET; - gtk_adjustment_set_value (adj, x); - } + row = g_list_position (clist->row_list, node); + + gtk_clist_moveto (clist, row, column, row_align, col_align); } @@ -4350,8 +4791,8 @@ tree_sort (GtkCTree *ctree, list_start = GTK_CTREE_ROW (max)->sibling; else { - gtk_ctree_unlink (ctree,max); - gtk_ctree_link (ctree, max, node, list_start); + gtk_ctree_unlink (ctree, max, FALSE); + gtk_ctree_link (ctree, max, node, list_start, FALSE); } } } @@ -4361,6 +4802,7 @@ gtk_ctree_sort_recursive (GtkCTree *ctree, GList *node) { GtkCList *clist; + GList *focus_node = NULL; gboolean thaw = FALSE; g_return_if_fail (ctree != NULL); @@ -4374,8 +4816,28 @@ gtk_ctree_sort_recursive (GtkCTree *ctree, thaw = TRUE; } + if (clist->selection_mode == GTK_SELECTION_BROWSE) + { + if (clist->anchor != -1) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + } + + if (gtk_ctree_is_visible (ctree, node)) + focus_node = g_list_nth (clist->row_list, clist->focus_row); + gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_sort), NULL); + if (focus_node) + { + clist->focus_row = g_list_position (clist->row_list, focus_node); + clist->undo_anchor = clist->focus_row; + } + if (thaw) gtk_clist_thaw (clist); } @@ -4385,6 +4847,7 @@ gtk_ctree_sort (GtkCTree *ctree, GList *node) { GtkCList *clist; + GList *focus_node = NULL; gboolean thaw = FALSE; g_return_if_fail (ctree != NULL); @@ -4398,8 +4861,209 @@ gtk_ctree_sort (GtkCTree *ctree, thaw = TRUE; } + if (clist->selection_mode == GTK_SELECTION_BROWSE) + { + if (clist->anchor != -1) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + } + + if (gtk_ctree_is_visible (ctree, node)) + focus_node = g_list_nth (clist->row_list, clist->focus_row); + tree_sort (ctree, node, NULL); + if (focus_node) + { + clist->focus_row = g_list_position (clist->row_list, focus_node); + clist->undo_anchor = clist->focus_row; + } + if (thaw) gtk_clist_thaw (clist); } + +/************************************************************************/ + +static void +fake_unselect_all (GtkCList *clist, + gint row) +{ + GList *list; + GList *focus_node = NULL; + + if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row))) + { + if (GTK_CTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL) + { + GTK_CTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED; + + if (!GTK_CLIST_FROZEN (clist) && + gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE) + GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, + GTK_CLIST_ROW (focus_node)); + } + } + + clist->undo_selection = clist->selection; + clist->selection = NULL; + clist->selection_end = NULL; + + for (list = clist->undo_selection; list; list = list->next) + { + if (list->data == focus_node) + continue; + + GTK_CTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL; + tree_draw_row (GTK_CTREE (clist), (GList *)(list->data)); + } +} + +static GList * +selection_find (GtkCList *clist, + gint row_number, + GList *row_list_element) +{ + return g_list_find (clist->selection, row_list_element); +} + +static void +resync_selection (GtkCList *clist, GdkEvent *event) +{ + GtkCTree *ctree; + GList *list; + GList *node; + gint i; + gint e; + gint row; + gboolean thaw = FALSE; + gboolean unselect; + + if (clist->anchor < 0) + return; + + ctree = GTK_CTREE (clist); + + if (!GTK_CLIST_FROZEN (clist)) + { + GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN); + thaw = TRUE; + } + + i = MIN (clist->anchor, clist->drag_pos); + e = MAX (clist->anchor, clist->drag_pos); + + if (clist->undo_selection) + { + list = clist->selection; + clist->selection = clist->undo_selection; + clist->selection_end = g_list_last (clist->selection); + clist->undo_selection = list; + list = clist->selection; + + while (list) + { + node = list->data; + list = list->next; + + unselect = TRUE; + + if (gtk_ctree_is_visible (ctree, node)) + { + row = g_list_position (clist->row_list, node); + if (row >= i && row <= e) + unselect = FALSE; + } + if (unselect) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; + gtk_ctree_unselect (ctree, node); + clist->undo_selection = g_list_prepend (clist->undo_selection, + node); + } + } + } + + + for (node = g_list_nth (clist->row_list, i); i <= e; i++, node = node->next) + if (g_list_find (clist->selection, node)) + { + if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_SELECTED; + gtk_ctree_unselect (ctree, node); + clist->undo_selection = g_list_prepend (clist->undo_selection, + node); + } + } + else if (GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) + { + GTK_CTREE_ROW (node)->row.state = GTK_STATE_NORMAL; + clist->undo_unselection = g_list_prepend (clist->undo_unselection, + node); + } + + for (list = clist->undo_unselection; list; list = list->next) + gtk_ctree_select (ctree, list->data); + + clist->anchor = -1; + clist->drag_pos = -1; + + if (thaw) + GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN); +} + +static void +real_undo_selection (GtkCList *clist) +{ + GtkCTree *ctree; + GList *work; + + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CLIST (clist)); + + if (clist->selection_mode != GTK_SELECTION_EXTENDED) + return; + + if (!(clist->undo_selection || clist->undo_unselection)) + { + gtk_clist_unselect_all (clist); + return; + } + + ctree = GTK_CTREE (clist); + + for (work = clist->undo_selection; work; work = work->next) + gtk_ctree_select (ctree, (GList *) work->data); + + for (work = clist->undo_unselection; work; work = work->next) + gtk_ctree_unselect (ctree, (GList *) work->data); + + if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor) + { + gtk_widget_draw_focus (GTK_WIDGET (clist)); + clist->focus_row = clist->undo_anchor; + gtk_widget_draw_focus (GTK_WIDGET (clist)); + } + else + clist->focus_row = clist->undo_anchor; + + clist->undo_anchor = -1; + + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + + if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height > + clist->clist_window_height) + gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0); + else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0) + gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0); + +} |