From 8a202e6f5b6303b612fe80b90934089e71b71908 Mon Sep 17 00:00:00 2001 From: Lars Hamann Date: Wed, 16 Dec 1998 01:28:31 +0000 Subject: [PATCH] removed clist flag : GTK_CLIST_DRAG_SELECTION added flags : Tue Dec 15 22:30:44 1998 Lars Hamann * gtk/gtkclist.h : removed clist flag : GTK_CLIST_DRAG_SELECTION added flags : GTK_CLIST_REORDERABLE, GTK_CLIST_USE_DRAG_ICONS, GTK_CLIST_DRAW_DRAG_LINE, GTK_CLIST_DRAW_DRAG_RECT (GtkCListDragPos) : new enum for DND (GtkButtonAction) : new enum of possible mouse button actions (struct _GtkCList): added button_actions array. Added drag_button and click_cell struct, to store cell and mouse button of last button_press_event (struct _GtkCListClass): new class method draw_drag_highlight. (gtk_clist_set_reorderable) (gtk_clist_set_use_drag_icons) : new functions. Moved from gtkctree.h. Now clist is reorderable as well. (gtk_clist_set_button_actions) new function to customize mouse button actions. * gtk/gtkclist.c: (gtk_clist_drag_begin) (gtk_clist_drag_motion) (gtk_clist_drag_leave) (gtk_clist_drag_end) (gtk_clist_drag_drop) (gtk_clist_drag_data_get) (gtk_clist_drag_data_received) : new dnd widget methods to implement clists reorderability via DND (remove_grab) : new function. remove mouse grab if necessary. (draw_drag_highlight) : new method. Draw dnd highlight depending on clist flags GTK_CLIST_DRAW_DRAG_LINE and GTK_CLIST_DRAW_DRAG_RECT (gtk_clist_class_init): added object args "reorderable" and "use_drag_icons" (gtk_clist_button_press) (gtk_clist_button_release) : use button_actions array to decide which action to perform. (gtk_clist_motion) : start reorder operation if necessary. * gtk/gtkctree.h : (struct _GtkCTree): removed drag_icon, icon_widht, icon_height, drag_row, drag_source, drag_target, reorderable, use_icons, in_drag, drag_rect (gtk_ctree_set_reorderable) : deprecated function. use gtk_clist_set_reorderable instead. (gtk_ctree_set_use_drag_icons) : deprecated function. use gtk_clist_set_use_drag_icons instead. * gtk/gtkctree.c : (gtk_ctree_class_init): removed object args "reorderable" and and "use_drag_icons" (draw_xor_line) (draw_xor_rect) (create_drag_icon) (check_cursor) (tree_toggle_selection) (set_mouse_cursor) : removed (draw_drag_highlight) : new clist method. replacement for draw_xor_line and draw_xor_rect functions (check_drag) renamed check_cursor function (gtk_ctree_drag_begin) (gtk_ctree_drag_motion) (gtk_ctree_drag_data_received) : new dnd methods to implement ctrees reorderability via DND (gtk_ctree_button_release) (gtk_ctree_button_motion) : removed. * gtk/testgtk.c: (create_clist) : added new reorderable toggle button --- gtk/gtkclist.c | 1270 ++++++++++++++++++++++++++++++++++------------- gtk/gtkclist.h | 77 ++- gtk/gtkctree.c | 1257 ++++++++++++++++++++-------------------------- gtk/gtkctree.h | 22 +- gtk/testgtk.c | 102 +--- tests/testgtk.c | 102 +--- 6 files changed, 1581 insertions(+), 1249 deletions(-) diff --git a/gtk/gtkclist.c b/gtk/gtkclist.c index ca65edfd3..8b6b92c56 100644 --- a/gtk/gtkclist.c +++ b/gtk/gtkclist.c @@ -23,9 +23,14 @@ #include "gtkmain.h" #include "gtkclist.h" #include "gtkbindings.h" +#include "gtkdnd.h" #include "gtkprivate.h" +#include #include +/* length of button_actions array */ +#define MAX_BUTTON 5 + /* the number rows memchunk expands at a time */ #define CLIST_OPTIMUM_SIZE 512 @@ -154,7 +159,9 @@ enum { ARG_N_COLUMNS, ARG_SHADOW_TYPE, ARG_SELECTION_MODE, - ARG_ROW_HEIGHT + ARG_ROW_HEIGHT, + ARG_REORDERABLE, + ARG_USE_DRAG_ICONS, }; /* GtkCList Methods */ @@ -204,6 +211,35 @@ static gint gtk_clist_focus (GtkContainer *container, GtkDirectionType direction); static void gtk_clist_style_set (GtkWidget *widget, GtkStyle *previous_style); +static void gtk_clist_drag_begin (GtkWidget *widget, + GdkDragContext *context); +static gint gtk_clist_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void gtk_clist_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static void gtk_clist_drag_end (GtkWidget *widget, + GdkDragContext *context); +static gboolean gtk_clist_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void gtk_clist_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time); +static void gtk_clist_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time); /* GtkContainer Methods */ static void gtk_clist_set_focus_child (GtkContainer *container, @@ -256,15 +292,6 @@ static void start_selection (GtkCList *clist); static void end_selection (GtkCList *clist); static void toggle_add_mode (GtkCList *clist); static void toggle_focus_row (GtkCList *clist); -static void move_focus_row (GtkCList *clist, - GtkScrollType scroll_type, - gfloat position); -static void scroll_horizontal (GtkCList *clist, - GtkScrollType scroll_type, - gfloat position); -static void scroll_vertical (GtkCList *clist, - GtkScrollType scroll_type, - gfloat position); static void extend_selection (GtkCList *clist, GtkScrollType scroll_type, gfloat position, @@ -275,6 +302,26 @@ static gint get_selection_info (GtkCList *clist, gint *row, gint *column); +/* Scrolling */ +static void move_focus_row (GtkCList *clist, + GtkScrollType scroll_type, + gfloat position); +static void scroll_horizontal (GtkCList *clist, + GtkScrollType scroll_type, + gfloat position); +static void scroll_vertical (GtkCList *clist, + GtkScrollType scroll_type, + gfloat position); +static void move_horizontal (GtkCList *clist, + gint diff); +static void move_vertical (GtkCList *clist, + gint row, + gfloat align); +static gint horizontal_timeout (GtkCList *clist); +static gint vertical_timeout (GtkCList *clist); +static void remove_grab (GtkCList *clist); + + /* Resize Columns */ static void draw_xor_line (GtkCList *clist); static gint new_column_width (GtkCList *clist, @@ -336,6 +383,10 @@ static void draw_row (GtkCList *clist, static void draw_rows (GtkCList *clist, GdkRectangle *area); static void clist_refresh (GtkCList *clist); +static void draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos); /* Size Allocation / Requisition */ static void size_allocate_title_buttons (GtkCList *clist); @@ -386,9 +437,11 @@ static void real_row_move (GtkCList *clist, gint dest_row); + static GtkContainerClass *parent_class = NULL; static guint clist_signals[LAST_SIGNAL] = {0}; +static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0}; GtkType gtk_clist_get_type (void) @@ -444,6 +497,14 @@ gtk_clist_class_init (GtkCListClass *klass) GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_ROW_HEIGHT); + gtk_object_add_arg_type ("GtkCList::reorderable", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_REORDERABLE); + gtk_object_add_arg_type ("GtkCList::use_drag_icons", + GTK_TYPE_BOOL, + GTK_ARG_READWRITE, + ARG_USE_DRAG_ICONS); object_class->set_arg = gtk_clist_set_arg; object_class->get_arg = gtk_clist_get_arg; @@ -595,6 +656,13 @@ gtk_clist_class_init (GtkCListClass *klass) widget_class->focus_out_event = gtk_clist_focus_out; widget_class->draw_focus = gtk_clist_draw_focus; widget_class->style_set = gtk_clist_style_set; + widget_class->drag_begin = gtk_clist_drag_begin; + widget_class->drag_end = gtk_clist_drag_end; + widget_class->drag_motion = gtk_clist_drag_motion; + widget_class->drag_leave = gtk_clist_drag_leave; + widget_class->drag_drop = gtk_clist_drag_drop; + widget_class->drag_data_get = gtk_clist_drag_data_get; + widget_class->drag_data_received = gtk_clist_drag_data_received; /* container_class->add = NULL; use the default GtkContainerClass warning */ /* container_class->remove=NULL; use the default GtkContainerClass warning */ @@ -614,6 +682,7 @@ gtk_clist_class_init (GtkCListClass *klass) klass->click_column = NULL; klass->resize_column = real_resize_column; klass->draw_row = draw_row; + klass->draw_drag_highlight = draw_drag_highlight; klass->insert_row = real_insert_row; klass->remove_row = real_remove_row; klass->clear = real_clear; @@ -854,6 +923,12 @@ gtk_clist_set_arg (GtkObject *object, case ARG_ROW_HEIGHT: gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg)); break; + case ARG_REORDERABLE: + gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg)); + break; + case ARG_USE_DRAG_ICONS: + gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg)); + break; default: break; } @@ -880,7 +955,13 @@ gtk_clist_get_arg (GtkObject *object, GTK_VALUE_ENUM (*arg) = clist->selection_mode; break; case ARG_ROW_HEIGHT: - GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET (clist) ? clist->row_height : 0; + GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0; + break; + case ARG_REORDERABLE: + GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist); + break; + case ARG_USE_DRAG_ICONS: + GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist); break; default: arg->type = GTK_TYPE_INVALID; @@ -894,6 +975,10 @@ gtk_clist_init (GtkCList *clist) clist->flags = 0; GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW); + GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS); + GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS); + GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE); + GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS); clist->row_mem_chunk = NULL; clist->cell_mem_chunk = NULL; @@ -925,6 +1010,12 @@ gtk_clist_init (GtkCList *clist) clist->vadjustment = NULL; clist->hadjustment = NULL; + clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS; + clist->button_actions[1] = GTK_BUTTON_IGNORED; + clist->button_actions[2] = GTK_BUTTON_IGNORED; + clist->button_actions[3] = GTK_BUTTON_IGNORED; + clist->button_actions[4] = GTK_BUTTON_IGNORED; + clist->cursor_drag = NULL; clist->xor_gc = NULL; clist->fg_gc = NULL; @@ -937,8 +1028,6 @@ gtk_clist_init (GtkCList *clist) clist->undo_selection = NULL; clist->undo_unselection = NULL; - GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS); - GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS); clist->focus_row = -1; clist->undo_anchor = -1; @@ -948,6 +1037,9 @@ gtk_clist_init (GtkCList *clist) clist->htimer = 0; clist->vtimer = 0; + clist->click_cell.row = -1; + clist->click_cell.column = -1; + clist->compare = default_compare; clist->sort_type = GTK_SORT_ASCENDING; clist->sort_column = 0; @@ -1252,7 +1344,7 @@ gtk_clist_column_titles_show (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (!GTK_CLIST_SHOW_TITLES (clist)) + if (!GTK_CLIST_SHOW_TITLES(clist)) { GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES); if (clist->title_window) @@ -1267,7 +1359,7 @@ gtk_clist_column_titles_hide (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (GTK_CLIST_SHOW_TITLES (clist)) + if (GTK_CLIST_SHOW_TITLES(clist)) { GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES); if (clist->title_window) @@ -1328,6 +1420,9 @@ gtk_clist_column_titles_active (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); + if (!GTK_CLIST_SHOW_TITLES(clist)) + return; + for (i = 0; i < clist->columns; i++) gtk_clist_column_title_active (clist, i); } @@ -1340,7 +1435,7 @@ gtk_clist_column_titles_passive (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (!GTK_CLIST_SHOW_TITLES (clist)) + if (!GTK_CLIST_SHOW_TITLES(clist)) return; for (i = 0; i < clist->columns; i++) @@ -1608,7 +1703,7 @@ gtk_clist_set_column_auto_resize (GtkCList *clist, if (auto_resize) { clist->column[column].resizeable = FALSE; - if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) { gint width; @@ -1658,7 +1753,7 @@ gtk_clist_optimal_column_width (GtkCList *clist, if (column < 0 || column > clist->columns) return 0; - if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button) + if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button) width = (clist->column[column].button->requisition.width - (CELL_SPACING + (2 * COLUMN_INSET))); else @@ -1756,7 +1851,7 @@ column_auto_resize (GtkCList *clist, GtkRequisition requisition; if (!clist->column[column].auto_resize || - GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) return; if (clist_row) @@ -1775,7 +1870,7 @@ column_auto_resize (GtkCList *clist, /* run a "gtk_clist_optimal_column_width" but break, if * the column doesn't shrink */ - if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button) + if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button) new_width = (clist->column[column].button->requisition.width - (CELL_SPACING + (2 * COLUMN_INSET))); else @@ -1831,7 +1926,7 @@ abort_column_resize (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (!GTK_CLIST_IN_DRAG (clist)) + if (!GTK_CLIST_IN_DRAG(clist)) return; GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG); @@ -1842,7 +1937,7 @@ abort_column_resize (GtkCList *clist) if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1) draw_xor_line (clist); - if (GTK_CLIST_ADD_MODE (clist)) + if (GTK_CLIST_ADD_MODE(clist)) { gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0); gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2); @@ -1947,7 +2042,7 @@ size_allocate_columns (GtkCList *clist, clist->column[i].area.x = xoffset; if (clist->column[i].width_set) { - if (!block_resize && GTK_CLIST_SHOW_TITLES (clist) && + if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].auto_resize && clist->column[i].button) { gint width; @@ -1962,7 +2057,7 @@ size_allocate_columns (GtkCList *clist, clist->column[i].area.width = clist->column[i].width; xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET); } - else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button) + else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button) { clist->column[i].area.width = clist->column[i].button->requisition.width - @@ -1991,7 +2086,7 @@ list_requisition_width (GtkCList *clist) if (clist->column[i].width_set) width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET); - else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button) + else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button) width += clist->column[i].button->requisition.width; } @@ -2107,7 +2202,7 @@ gtk_clist_set_row_height (GtkCList *clist, if (GTK_WIDGET_REALIZED (clist)) { - if (!GTK_CLIST_ROW_HEIGHT_SET (clist)) + if (!GTK_CLIST_ROW_HEIGHT_SET(clist)) { clist->row_height = (widget->style->font->ascent + widget->style->font->descent + 1); @@ -2407,7 +2502,7 @@ gtk_clist_set_shift (GtkCList *clist, clist_row = (g_list_nth (clist->row_list, row))->data; if (clist->column[column].auto_resize && - !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row, column, &requisition); @@ -2441,7 +2536,7 @@ set_cell_contents (GtkCList *clist, g_return_if_fail (clist_row != NULL); if (clist->column[column].auto_resize && - !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row, column, &requisition); @@ -2505,7 +2600,7 @@ set_cell_contents (GtkCList *clist, } if (clist->column[column].auto_resize && - !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) column_auto_resize (clist, clist_row, column, requisition.width); } @@ -2659,7 +2754,7 @@ real_insert_row (GtkCList *clist, } else { - if (GTK_CLIST_AUTO_SORT (clist)) /* override insertion pos */ + if (GTK_CLIST_AUTO_SORT(clist)) /* override insertion pos */ { GList *work; @@ -2819,7 +2914,7 @@ real_clear (GtkCList *clist) for (i = 0; i < clist->columns; i++) if (clist->column[i].auto_resize) { - if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button) + if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button) gtk_clist_set_column_width (clist, i, (clist->column[i].button->requisition.width - (CELL_SPACING + (2 * COLUMN_INSET)))); @@ -2849,7 +2944,7 @@ real_row_move (GtkCList *clist, g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (GTK_CLIST_AUTO_SORT (clist)) + if (GTK_CLIST_AUTO_SORT(clist)) return; if (source_row < 0 || source_row >= clist->rows || @@ -2985,7 +3080,7 @@ gtk_clist_swap_rows (GtkCList *clist, g_return_if_fail (GTK_IS_CLIST (clist)); g_return_if_fail (row1 != row2); - if (GTK_CLIST_AUTO_SORT (clist)) + if (GTK_CLIST_AUTO_SORT(clist)) return; gtk_clist_freeze (clist); @@ -3007,7 +3102,7 @@ gtk_clist_row_move (GtkCList *clist, g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (GTK_CLIST_AUTO_SORT (clist)) + if (GTK_CLIST_AUTO_SORT(clist)) return; if (source_row < 0 || source_row >= clist->rows || @@ -3139,7 +3234,7 @@ gtk_clist_set_cell_style (GtkCList *clist, return; if (clist->column[column].auto_resize && - !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row, column, &requisition); @@ -3213,7 +3308,7 @@ gtk_clist_set_row_style (GtkCList *clist, old_width = g_new (gint, clist->columns); - if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) { for (i = 0; i < clist->columns; i++) if (clist->column[i].auto_resize) @@ -3242,7 +3337,7 @@ gtk_clist_set_row_style (GtkCList *clist, clist->clist_window); } - if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + if (GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) for (i = 0; i < clist->columns; i++) column_auto_resize (clist, clist_row, i, old_width[i]); @@ -3307,22 +3402,8 @@ gtk_clist_set_selectable (GtkCList *clist, if (clist->anchor >= 0 && clist->selection_mode == GTK_SELECTION_EXTENDED) { - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist))) - { - GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION); - gtk_grab_remove (GTK_WIDGET (clist)); - gdk_pointer_ungrab (GDK_CURRENT_TIME); - if (clist->htimer) - { - gtk_timeout_remove (clist->htimer); - clist->htimer = 0; - } - if (clist->vtimer) - { - gtk_timeout_remove (clist->vtimer); - clist->vtimer = 0; - } - } + clist->drag_button = 0; + remove_grab (clist); GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); } gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], @@ -3513,7 +3594,7 @@ toggle_focus_row (GtkCList *clist) clist->drag_pos = clist->focus_row; clist->undo_anchor = clist->focus_row; - if (GTK_CLIST_ADD_MODE (clist)) + if (GTK_CLIST_ADD_MODE(clist)) fake_toggle_row (clist, clist->focus_row); else GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row); @@ -3536,7 +3617,7 @@ toggle_add_mode (GtkCList *clist) return; gtk_clist_draw_focus (GTK_WIDGET (clist)); - if (!GTK_CLIST_ADD_MODE (clist)) + if (!GTK_CLIST_ADD_MODE(clist)) { GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE); gdk_gc_set_line_attributes (clist->xor_gc, 1, @@ -3814,7 +3895,7 @@ real_undo_selection (GtkCList *clist) gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], GPOINTER_TO_INT (work->data), -1, NULL); - if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor) + if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor) { gtk_clist_draw_focus (GTK_WIDGET (clist)); clist->focus_row = clist->undo_anchor; @@ -4109,7 +4190,7 @@ start_selection (GtkCList *clist) if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) return; - set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row, + set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row, clist->focus_row); } @@ -4119,7 +4200,7 @@ end_selection (GtkCList *clist) g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) || + if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist)) || clist->anchor == -1) return; @@ -4140,7 +4221,7 @@ extend_selection (GtkCList *clist, return; if (auto_start_selection) - set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row, + set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row, clist->focus_row); else if (clist->anchor == -1) return; @@ -4243,16 +4324,7 @@ gtk_clist_destroy (GtkObject *object) clist->vadjustment = NULL; } - if (clist->htimer) - { - gtk_timeout_remove (clist->htimer); - clist->htimer = 0; - } - if (clist->vtimer) - { - gtk_timeout_remove (clist->vtimer); - clist->vtimer = 0; - } + remove_grab (clist); /* destroy the column buttons */ for (i = 0; i < clist->columns; i++) @@ -4700,7 +4772,7 @@ gtk_clist_style_set (GtkWidget *widget, /* Fill in data after widget has correct style */ /* text properties */ - if (!GTK_CLIST_ROW_HEIGHT_SET (clist)) + if (!GTK_CLIST_ROW_HEIGHT_SET(clist)) { clist->row_height = (widget->style->font->ascent + widget->style->font->descent + 1); @@ -4712,7 +4784,7 @@ gtk_clist_style_set (GtkWidget *widget, widget->style->font->descent - 1) / 2; /* Column widths */ - if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist)) + if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist)) { gint width; gint i; @@ -4765,6 +4837,7 @@ gtk_clist_button_press (GtkWidget *widget, gint y; gint row; gint column; + gint button_actions; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); @@ -4772,10 +4845,11 @@ gtk_clist_button_press (GtkWidget *widget, clist = GTK_CLIST (widget); - /* we don't handle button 2 and 3 */ - if (event->button != 1) + button_actions = clist->button_actions[event->button - 1]; + + if (button_actions == GTK_BUTTON_IGNORED) return FALSE; - + /* selections on the list */ if (event->window == clist->clist_window) { @@ -4791,123 +4865,141 @@ gtk_clist_button_press (GtkWidget *widget, if (event->type == GDK_BUTTON_PRESS) { - 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, + GdkEventMask mask = ((1 << (4 + event->button)) | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_RELEASE_MASK); + + clist->click_cell.row = row; + clist->click_cell.column = column; + + clist->drag_button = event->button; + gdk_pointer_grab (clist->clist_window, FALSE, mask, NULL, NULL, event->time); gtk_grab_add (widget); } - else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget)) + else { - GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION); - gtk_grab_remove (widget); - gdk_pointer_ungrab (event->time); + if (clist->drag_button == 0) + return FALSE; + + clist->click_cell.row = -1; + clist->click_cell.column = -1; + + clist->drag_button = 0; + remove_grab (clist); } - if (GTK_CLIST_ADD_MODE (clist)) + if (button_actions & GTK_BUTTON_SELECTS) { - GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE); - if (GTK_WIDGET_HAS_FOCUS (widget)) - { - gtk_clist_draw_focus (widget); - gdk_gc_set_line_attributes (clist->xor_gc, 1, - GDK_LINE_SOLID, 0, 0); - clist->focus_row = row; - gtk_clist_draw_focus (widget); - } - else + if (GTK_CLIST_ADD_MODE(clist)) { - gdk_gc_set_line_attributes (clist->xor_gc, 1, - GDK_LINE_SOLID, 0, 0); - clist->focus_row = row; + GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE); + if (GTK_WIDGET_HAS_FOCUS(widget)) + { + gtk_clist_draw_focus (widget); + gdk_gc_set_line_attributes (clist->xor_gc, 1, + GDK_LINE_SOLID, 0, 0); + clist->focus_row = row; + gtk_clist_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)) + else if (row != clist->focus_row) { - gtk_clist_draw_focus (widget); - clist->focus_row = row; - gtk_clist_draw_focus (widget); + if (GTK_WIDGET_HAS_FOCUS(widget)) + { + gtk_clist_draw_focus (widget); + clist->focus_row = row; + gtk_clist_draw_focus (widget); + } + else + clist->focus_row = row; } - else - clist->focus_row = row; } - if (!GTK_WIDGET_HAS_FOCUS (widget)) + if (!GTK_WIDGET_HAS_FOCUS(widget)) gtk_widget_grab_focus (widget); - switch (clist->selection_mode) + if (button_actions & GTK_BUTTON_SELECTS) { - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: - if (event->type != GDK_BUTTON_PRESS) - gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], - row, column, event); - else - clist->anchor = row; - break; - case GTK_SELECTION_BROWSE: - gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], - row, column, event); - break; - case GTK_SELECTION_EXTENDED: - if (event->type != GDK_BUTTON_PRESS) + switch (clist->selection_mode) { - if (clist->anchor != -1) - { - update_extended_selection (clist, clist->focus_row); - GTK_CLIST_CLASS_FW (clist)->resync_selection - (clist, (GdkEvent *) event); - } + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: + if (event->type != GDK_BUTTON_PRESS) + gtk_signal_emit (GTK_OBJECT (clist), + clist_signals[SELECT_ROW], + row, column, event); + else + clist->anchor = row; + break; + case GTK_SELECTION_BROWSE: gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], row, column, event); break; - } - - if (event->state & GDK_CONTROL_MASK) - { - if (event->state & GDK_SHIFT_MASK) + case GTK_SELECTION_EXTENDED: + if (event->type != GDK_BUTTON_PRESS) { - if (clist->anchor < 0) + if (clist->anchor != -1) { - g_list_free (clist->undo_selection); - g_list_free (clist->undo_unselection); - clist->undo_selection = NULL; - clist->undo_unselection = NULL; - clist->anchor = old_row; - clist->drag_pos = old_row; - clist->undo_anchor = old_row; + update_extended_selection (clist, clist->focus_row); + GTK_CLIST_CLASS_FW (clist)->resync_selection + (clist, (GdkEvent *) event); } - update_extended_selection (clist, clist->focus_row); + gtk_signal_emit (GTK_OBJECT (clist), + clist_signals[SELECT_ROW], + row, column, event); + break; } - else + + if (event->state & GDK_CONTROL_MASK) { - if (clist->anchor == -1) - set_anchor (clist, TRUE, row, old_row); + if (event->state & GDK_SHIFT_MASK) + { + if (clist->anchor < 0) + { + g_list_free (clist->undo_selection); + g_list_free (clist->undo_unselection); + clist->undo_selection = NULL; + clist->undo_unselection = NULL; + clist->anchor = old_row; + clist->drag_pos = old_row; + clist->undo_anchor = old_row; + } + update_extended_selection (clist, clist->focus_row); + } else - update_extended_selection (clist, clist->focus_row); + { + if (clist->anchor == -1) + set_anchor (clist, TRUE, row, old_row); + else + update_extended_selection (clist, + clist->focus_row); + } + break; } - break; - } - if (event->state & GDK_SHIFT_MASK) - { - set_anchor (clist, FALSE, old_row, old_row); - update_extended_selection (clist, clist->focus_row); + if (event->state & GDK_SHIFT_MASK) + { + set_anchor (clist, FALSE, old_row, old_row); + update_extended_selection (clist, clist->focus_row); + break; + } + + if (clist->anchor == -1) + set_anchor (clist, FALSE, row, old_row); + else + update_extended_selection (clist, clist->focus_row); + break; + default: break; } - - if (clist->anchor == -1) - set_anchor (clist, FALSE, row, old_row); - else - update_extended_selection (clist, clist->focus_row); - break; - default: - break; } } @@ -4927,14 +5019,14 @@ gtk_clist_button_press (GtkWidget *widget, gtk_grab_add (widget); GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG); - if (!GTK_WIDGET_HAS_FOCUS (widget)) + if (!GTK_WIDGET_HAS_FOCUS(widget)) gtk_widget_grab_focus (widget); clist->drag_pos = i; clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET + clist->column[i].area.width + CELL_SPACING); - if (GTK_CLIST_ADD_MODE (clist)) + if (GTK_CLIST_ADD_MODE(clist)) gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0); draw_xor_line (clist); @@ -4948,6 +5040,7 @@ gtk_clist_button_release (GtkWidget *widget, GdkEventButton *event) { GtkCList *clist; + gint button_actions; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); @@ -4955,12 +5048,12 @@ gtk_clist_button_release (GtkWidget *widget, clist = GTK_CLIST (widget); - /* we don't handle button 2 and 3 */ - if (event->button != 1) + button_actions = clist->button_actions[event->button - 1]; + if (button_actions == GTK_BUTTON_IGNORED) return FALSE; /* release on resize windows */ - if (GTK_CLIST_IN_DRAG (clist)) + if (GTK_CLIST_IN_DRAG(clist)) { gint width; gint x; @@ -4977,7 +5070,7 @@ gtk_clist_button_release (GtkWidget *widget, if (clist->x_drag >= 0) draw_xor_line (clist); - if (GTK_CLIST_ADD_MODE (clist)) + if (GTK_CLIST_ADD_MODE(clist)) { gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0); @@ -4989,134 +5082,46 @@ gtk_clist_button_release (GtkWidget *widget, return FALSE; } - if (GTK_CLIST_DRAG_SELECTION (clist)) + if (clist->drag_button) { gint row; gint column; - GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION); - gtk_grab_remove (widget); - gdk_pointer_ungrab (event->time); - if (clist->htimer) - { - gtk_timeout_remove (clist->htimer); - clist->htimer = 0; - } - if (clist->vtimer) - { - gtk_timeout_remove (clist->vtimer); - clist->vtimer = 0; - } - switch (clist->selection_mode) - { - case GTK_SELECTION_EXTENDED: - if (!(event->state & GDK_SHIFT_MASK) || - event->x < 0 || event->x >= clist->clist_window_width || - event->y < 0 || event->y >= clist->clist_window_height) - GTK_CLIST_CLASS_FW (clist)->resync_selection - (clist, (GdkEvent *) event); - break; + clist->drag_button = 0; + clist->click_cell.row = -1; + clist->click_cell.column = -1; - case GTK_SELECTION_SINGLE: - case GTK_SELECTION_MULTIPLE: - if (get_selection_info (clist, event->x, event->y, &row, &column)) + remove_grab (clist); + + if (button_actions & GTK_BUTTON_SELECTS) + { + switch (clist->selection_mode) { - if (row >= 0 && row < clist->rows && clist->anchor == row) - toggle_row (clist, row, column, (GdkEvent *) event); + case GTK_SELECTION_EXTENDED: + if (!(event->state & GDK_SHIFT_MASK) || + event->x < 0 || event->x >= clist->clist_window_width || + event->y < 0 || event->y >= clist->clist_window_height) + GTK_CLIST_CLASS_FW (clist)->resync_selection + (clist, (GdkEvent *) event); + break; + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: + if (get_selection_info (clist, event->x, event->y, + &row, &column)) + { + if (row >= 0 && row < clist->rows && clist->anchor == row) + toggle_row (clist, row, column, (GdkEvent *) event); + } + clist->anchor = -1; + break; + default: + break; } - clist->anchor = -1; - break; - - default: - break; } } - - return FALSE; -} - -static gint -horizontal_timeout (GtkCList *clist) -{ - gint x, y; - GdkEventMotion event; - GdkModifierType mask; - - GTK_THREADS_ENTER; - - clist->htimer = 0; - gdk_window_get_pointer (clist->clist_window, &x, &y, &mask); - - event.is_hint = 0; - event.x = x; - event.y = y; - event.state = mask; - - gtk_clist_motion (GTK_WIDGET (clist), &event); - - GTK_THREADS_LEAVE; - - return FALSE; -} - -static gint -vertical_timeout (GtkCList *clist) -{ - gint x, y; - GdkEventMotion event; - GdkModifierType mask; - - GTK_THREADS_ENTER; - - clist->vtimer = 0; - gdk_window_get_pointer (clist->clist_window, &x, &y, &mask); - - event.is_hint = 0; - event.x = x; - event.y = y; - event.state = mask; - - gtk_clist_motion (GTK_WIDGET (clist), &event); - - GTK_THREADS_LEAVE; - return FALSE; } -static void -move_vertical (GtkCList *clist, - gint row, - gfloat align) -{ - gfloat value; - - if (!clist->vadjustment) - return; - - value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset - - align * (clist->clist_window_height - clist->row_height) + - (2 * align - 1) * CELL_SPACING); - - if (value + clist->vadjustment->page_size > clist->vadjustment->upper) - value = clist->vadjustment->upper - clist->vadjustment->page_size; - - gtk_adjustment_set_value(clist->vadjustment, value); -} - -static void -move_horizontal (GtkCList *clist, - gint diff) -{ - gfloat value; - - if (!clist->hadjustment) - return; - - value = CLAMP (clist->hadjustment->value + diff, 0.0, - clist->hadjustment->upper - clist->hadjustment->page_size); - gtk_adjustment_set_value(clist->hadjustment, value); -} - static gint gtk_clist_motion (GtkWidget *widget, GdkEventMotion *event) @@ -5126,6 +5131,7 @@ gtk_clist_motion (GtkWidget *widget, gint y; gint row; gint new_width; + gint button_actions; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); @@ -5134,7 +5140,9 @@ gtk_clist_motion (GtkWidget *widget, if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))) return FALSE; - if (GTK_CLIST_IN_DRAG (clist)) + button_actions = clist->button_actions[clist->drag_button - 1]; + + if (GTK_CLIST_IN_DRAG(clist)) { if (event->is_hint || event->window != widget->window) gtk_widget_get_pointer (widget, &x, NULL); @@ -5177,6 +5185,49 @@ gtk_clist_motion (GtkWidget *widget, if (event->is_hint || event->window != clist->clist_window) gdk_window_get_pointer (clist->clist_window, &x, &y, NULL); + if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS) + { + /* delayed drag start */ + if (clist->click_cell.row >= 0 && clist->click_cell.column >= 0 && + (y < 0 || y >= clist->clist_window_height || + x < 0 || x >= clist->clist_window_width || + y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) || + y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) + + clist->row_height) || + x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) || + x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) + + clist->column[clist->click_cell.column].area.width))) + { + GdkDragContext *context; + GtkTargetList *target_list; + gint button; + + button = clist->drag_button; + clist->drag_button = 0; + remove_grab (clist); + + switch (clist->selection_mode) + { + case GTK_SELECTION_EXTENDED: + update_extended_selection (clist, clist->focus_row); + GTK_CLIST_CLASS_FW (clist)->resync_selection + (clist, (GdkEvent *) event); + break; + case GTK_SELECTION_SINGLE: + case GTK_SELECTION_MULTIPLE: + clist->anchor = -1; + case GTK_SELECTION_BROWSE: + break; + } + + target_list = gtk_target_list_new (&clist_target_table, 1); + context = gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE, + button, (GdkEvent *)event); + + } + return TRUE; + } + /* horizontal autoscrolling */ if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width && (x < 0 || x >= clist->clist_window_width)) @@ -5199,7 +5250,7 @@ gtk_clist_motion (GtkWidget *widget, } } - if (GTK_CLIST_IN_DRAG (clist)) + if (GTK_CLIST_IN_DRAG(clist)) return FALSE; /* vertical autoscrolling */ @@ -5219,18 +5270,16 @@ gtk_clist_motion (GtkWidget *widget, clist->vtimer = gtk_timeout_add (SCROLL_TIME, (GtkFunction) vertical_timeout, clist); - if (GTK_CLIST_DRAG_SELECTION (clist)) - { - if ((y < 0 && clist->focus_row == 0) || - (y >= clist->clist_window_height && - clist->focus_row == clist->rows-1)) - return FALSE; - } + if (clist->drag_button && + ((y < 0 && clist->focus_row == 0) || + (y >= clist->clist_window_height && + clist->focus_row == clist->rows - 1))) + return FALSE; } row = CLAMP (row, 0, clist->rows - 1); - if (GTK_CLIST_DRAG_SELECTION (clist)) + if (button_actions & GTK_BUTTON_SELECTS) { if (row == clist->focus_row) return FALSE; @@ -5280,7 +5329,7 @@ gtk_clist_size_request (GtkWidget *widget, /* compute the size of the column title (title) area */ clist->column_title_area.height = 0; - if (GTK_CLIST_SHOW_TITLES (clist)) + if (GTK_CLIST_SHOW_TITLES(clist)) for (i = 0; i < clist->columns; i++) if (clist->column[i].button) { @@ -5772,7 +5821,7 @@ draw_row (GtkCList *clist, } /* draw focus rectangle */ - if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget)) + if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS(widget)) { if (!area) gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, @@ -5922,10 +5971,7 @@ gtk_clist_get_selection_info (GtkCList *clist, return get_selection_info (clist, x, y, row, column); } -/* - * SCROLLBARS - * - * functions: +/* PRIVATE ADJUSTMENT FUNCTIONS * adjust_adjustments * vadjustment_changed * hadjustment_changed @@ -6145,8 +6191,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment, return; } - if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) && - GTK_CLIST_ADD_MODE (clist)) + if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist) && + GTK_CLIST_ADD_MODE(clist)) { y = ROW_TOP_YPIXEL (clist, clist->focus_row); @@ -6180,8 +6226,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment, return; } - if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) && - GTK_CLIST_ADD_MODE (clist)) + if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist) && + GTK_CLIST_ADD_MODE(clist)) { y = ROW_TOP_YPIXEL (clist, clist->focus_row); @@ -6208,9 +6254,9 @@ hadjustment_value_changed (GtkAdjustment *adjustment, check_exposures (clist); - if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist)) + if (GTK_WIDGET_HAS_FOCUS(clist) && !GTK_CLIST_CHILD_HAS_FOCUS(clist)) { - if (GTK_CLIST_ADD_MODE (clist)) + if (GTK_CLIST_ADD_MODE(clist)) { gint focus_row; @@ -6273,7 +6319,7 @@ check_exposures (GtkCList *clist) } } -/* +/* PRIVATE * Memory Allocation/Distruction Routines for GtkCList stuctures * * functions: @@ -6426,7 +6472,7 @@ gtk_clist_focus (GtkContainer *container, { case GTK_DIR_LEFT: case GTK_DIR_RIGHT: - if (GTK_CLIST_CHILD_HAS_FOCUS (clist)) + if (GTK_CLIST_CHILD_HAS_FOCUS(clist)) { if (title_focus (clist, direction)) return TRUE; @@ -6437,7 +6483,7 @@ gtk_clist_focus (GtkContainer *container, return TRUE; case GTK_DIR_DOWN: case GTK_DIR_TAB_FORWARD: - if (GTK_CLIST_CHILD_HAS_FOCUS (clist)) + if (GTK_CLIST_CHILD_HAS_FOCUS(clist)) { gboolean tf = FALSE; @@ -6469,7 +6515,7 @@ gtk_clist_focus (GtkContainer *container, case GTK_DIR_UP: case GTK_DIR_TAB_BACKWARD: if (!focus_child && - GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows) + GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows) { if (clist->focus_row < 0) { @@ -6600,7 +6646,7 @@ title_focus (GtkCList *clist, gint i = 0; gint j; - if (!GTK_CLIST_SHOW_TITLES (clist)) + if (!GTK_CLIST_SHOW_TITLES(clist)) return FALSE; focus_child = GTK_CONTAINER (clist)->focus_child; @@ -6609,7 +6655,7 @@ title_focus (GtkCList *clist, { case GTK_DIR_TAB_BACKWARD: case GTK_DIR_UP: - if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS (clist)) + if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist)) { if (dir == GTK_DIR_UP) i = COLUMN_FROM_XPIXEL (clist, 0); @@ -6646,7 +6692,7 @@ title_focus (GtkCList *clist, if (clist->column[i].button && GTK_WIDGET_VISIBLE (clist->column[i].button) && GTK_IS_CONTAINER (clist->column[i].button) && - !GTK_WIDGET_HAS_FOCUS (clist->column[i].button)) + !GTK_WIDGET_HAS_FOCUS(clist->column[i].button)) if (gtk_container_focus (GTK_CONTAINER (clist->column[i].button), dir)) { @@ -6702,10 +6748,15 @@ title_focus (GtkCList *clist, return return_val; } -/* SCROLLING FUNCTIONS +/* PRIVATE SCROLLING FUNCTIONS * move_focus_row * scroll_horizontal * scroll_vertical + * move_horizontal + * move_vertical + * horizontal_timeout + * vertical_timeout + * remove_grab */ static void move_focus_row (GtkCList *clist, @@ -6852,7 +6903,7 @@ scroll_vertical (GtkCList *clist, if (clist->selection_mode == GTK_SELECTION_BROWSE) gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], old_focus_row, -1, NULL); - else if (!GTK_CLIST_ADD_MODE (clist)) + else if (!GTK_CLIST_ADD_MODE(clist)) { gtk_clist_unselect_all (clist); clist->undo_anchor = old_focus_row; @@ -6864,7 +6915,7 @@ scroll_vertical (GtkCList *clist, case GTK_VISIBILITY_NONE: if (old_focus_row != clist->focus_row && !(clist->selection_mode == GTK_SELECTION_EXTENDED && - GTK_CLIST_ADD_MODE (clist))) + GTK_CLIST_ADD_MODE(clist))) gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], clist->focus_row, -1, NULL); switch (scroll_type) @@ -6904,7 +6955,7 @@ scroll_vertical (GtkCList *clist, default: if (old_focus_row != clist->focus_row && !(clist->selection_mode == GTK_SELECTION_EXTENDED && - GTK_CLIST_ADD_MODE (clist))) + GTK_CLIST_ADD_MODE(clist))) gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], clist->focus_row, -1, NULL); break; @@ -6922,25 +6973,129 @@ scroll_vertical (GtkCList *clist, } } -/* PUBLIC SORTING FUNCTIONS - * gtk_clist_sort - * gtk_clist_set_compare_func - * gtk_clist_set_auto_sort - * gtk_clist_set_sort_type - * gtk_clist_set_sort_column - */ -void -gtk_clist_sort (GtkCList *clist) +static void +move_horizontal (GtkCList *clist, + gint diff) { - g_return_if_fail (clist != NULL); - g_return_if_fail (GTK_IS_CLIST (clist)); + gfloat value; - GTK_CLIST_CLASS_FW (clist)->sort_list (clist); + if (!clist->hadjustment) + return; + + value = CLAMP (clist->hadjustment->value + diff, 0.0, + clist->hadjustment->upper - clist->hadjustment->page_size); + gtk_adjustment_set_value(clist->hadjustment, value); } -void -gtk_clist_set_compare_func (GtkCList *clist, - GtkCListCompareFunc cmp_func) +static void +move_vertical (GtkCList *clist, + gint row, + gfloat align) +{ + gfloat value; + + if (!clist->vadjustment) + return; + + value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset - + align * (clist->clist_window_height - clist->row_height) + + (2 * align - 1) * CELL_SPACING); + + if (value + clist->vadjustment->page_size > clist->vadjustment->upper) + value = clist->vadjustment->upper - clist->vadjustment->page_size; + + gtk_adjustment_set_value(clist->vadjustment, value); +} + +static gint +horizontal_timeout (GtkCList *clist) +{ + gint x, y; + GdkEventMotion event; + GdkModifierType mask; + + GTK_THREADS_ENTER; + + clist->htimer = 0; + gdk_window_get_pointer (clist->clist_window, &x, &y, &mask); + + event.is_hint = 0; + event.x = x; + event.y = y; + event.state = mask; + + gtk_clist_motion (GTK_WIDGET (clist), &event); + + GTK_THREADS_LEAVE; + + return FALSE; +} + +static gint +vertical_timeout (GtkCList *clist) +{ + gint x, y; + GdkEventMotion event; + GdkModifierType mask; + + GTK_THREADS_ENTER; + + clist->vtimer = 0; + gdk_window_get_pointer (clist->clist_window, &x, &y, &mask); + + event.is_hint = 0; + event.x = x; + event.y = y; + event.state = mask; + + gtk_clist_motion (GTK_WIDGET (clist), &event); + + GTK_THREADS_LEAVE; + + return FALSE; +} + +static void +remove_grab (GtkCList *clist) +{ + if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) + { + gtk_grab_remove (GTK_WIDGET (clist)); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + } + + if (clist->htimer) + { + gtk_timeout_remove (clist->htimer); + clist->htimer = 0; + } + + if (clist->vtimer) + { + gtk_timeout_remove (clist->vtimer); + clist->vtimer = 0; + } +} + +/* PUBLIC SORTING FUNCTIONS + * gtk_clist_sort + * gtk_clist_set_compare_func + * gtk_clist_set_auto_sort + * gtk_clist_set_sort_type + * gtk_clist_set_sort_column + */ +void +gtk_clist_sort (GtkCList *clist) +{ + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CLIST (clist)); + + GTK_CLIST_CLASS_FW (clist)->sort_list (clist); +} + +void +gtk_clist_set_compare_func (GtkCList *clist, + GtkCListCompareFunc cmp_func) { g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); @@ -6955,9 +7110,9 @@ gtk_clist_set_auto_sort (GtkCList *clist, g_return_if_fail (clist != NULL); g_return_if_fail (GTK_IS_CLIST (clist)); - if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort) + if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort) GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT); - else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort) + else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort) { GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT); gtk_clist_sort (clist); @@ -7166,3 +7321,454 @@ gtk_clist_mergesort (GtkCList *clist, gtk_clist_mergesort (clist, half, num - num / 2)); } } + +/************************/ + +static void +drag_source_info_destroy (gpointer data) +{ + GtkCListCellInfo *info = data; + + g_free (info); +} + +static void +drag_dest_info_destroy (gpointer data) +{ + GtkCListDestInfo *info = data; + + g_free (info); +} + +static void +gtk_clist_drag_begin (GtkWidget *widget, + GdkDragContext *context) +{ + GtkCList *clist; + GtkCListCellInfo *info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CLIST (widget)); + g_return_if_fail (context != NULL); + + clist = GTK_CLIST (widget); + + info = g_dataset_get_data (context, "gtk-clist-drag-source"); + + if (!info) + { + info = g_new (GtkCListCellInfo, 1); + + if (clist->click_cell.row < 0) + clist->click_cell.row = 0; + else if (clist->click_cell.row >= clist->rows) + clist->click_cell.row = clist->rows - 1; + info->row = clist->click_cell.row; + info->column = clist->click_cell.column; + + g_dataset_set_data_full (context, "gtk-clist-drag-source", info, + drag_source_info_destroy); + } + + if (GTK_CLIST_USE_DRAG_ICONS (clist)) + gtk_drag_set_icon_default (context); +} + +static void +gtk_clist_drag_end (GtkWidget *widget, + GdkDragContext *context) +{ + GtkCList *clist; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CLIST (widget)); + g_return_if_fail (context != NULL); + + clist = GTK_CLIST (widget); + + clist->click_cell.row = -1; + clist->click_cell.column = -1; +} + +static void +gtk_clist_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time) +{ + GtkCList *clist; + GtkCListDestInfo *dest_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CLIST (widget)); + g_return_if_fail (context != NULL); + + clist = GTK_CLIST (widget); + + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (dest_info) + { + if (dest_info->cell.row >= 0 && + GTK_CLIST_REORDERABLE(clist) && + gtk_drag_get_source_widget (context) == widget) + { + GList *list; + GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE); + + list = context->targets; + while (list) + { + if (atom == GPOINTER_TO_INT (list->data)) + { + GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight + (clist, + g_list_nth (clist->row_list, dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + break; + } + list = list->next; + } + } + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + } +} + +static gint +gtk_clist_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkCList *clist; + gint row, column; + GtkCListDestInfo *dest_info; + gint h = 0; + gint insert_pos = GTK_CLIST_DRAG_NONE; + gint y_delta; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); + + clist = GTK_CLIST (widget); + + y -= (GTK_CONTAINER (widget)->border_width + + widget->style->klass->ythickness + clist->column_title_area.height); + row = ROW_FROM_YPIXEL (clist, y); + + if (row >= clist->rows) + { + row = clist->rows - 1; + y = ROW_TOP_YPIXEL (clist, row) + clist->row_height; + } + if (row < -1) + row = -1; + + x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness; + column = COLUMN_FROM_XPIXEL (clist, x); + + if (row >= 0) + { + y_delta = y - ROW_TOP_YPIXEL (clist, row); + + if (GTK_CLIST_DRAW_DRAG_RECT(clist)) + { + insert_pos = GTK_CLIST_DRAG_INTO; + h = clist->row_height / 4; + } + else if (GTK_CLIST_DRAW_DRAG_LINE(clist)) + { + insert_pos = GTK_CLIST_DRAG_BEFORE; + h = clist->row_height / 2; + } + + if (GTK_CLIST_DRAW_DRAG_LINE(clist)) + { + if (y_delta < h) + insert_pos = GTK_CLIST_DRAG_BEFORE; + else if (clist->row_height - y_delta < h) + insert_pos = GTK_CLIST_DRAG_AFTER; + } + } + + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (!dest_info) + { + dest_info = g_new (GtkCListDestInfo, 1); + + dest_info->insert_pos = GTK_CLIST_DRAG_NONE; + dest_info->cell.row = -1; + dest_info->cell.column = -1; + + g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info, + drag_dest_info_destroy); + } + + if (GTK_CLIST_REORDERABLE (clist)) + { + GList *list; + GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE); + + list = context->targets; + while (list) + { + if (atom == GPOINTER_TO_INT (list->data)) + break; + list = list->next; + } + + if (list) + { + if (gtk_drag_get_source_widget (context) != widget || + insert_pos == GTK_CLIST_DRAG_NONE || + row == clist->click_cell.row || + (row == clist->click_cell.row - 1 && + insert_pos == GTK_CLIST_DRAG_AFTER) || + (row == clist->click_cell.row + 1 && + insert_pos == GTK_CLIST_DRAG_BEFORE)) + { + if (dest_info->cell.row < 0) + { + gdk_drag_status (context, GDK_ACTION_DEFAULT, time); + return FALSE; + } + return TRUE; + } + + if (row != dest_info->cell.row || + (row == dest_info->cell.row && + dest_info->insert_pos != insert_pos)) + { + if (dest_info->cell.row >= 0) + GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight + (clist, g_list_nth (clist->row_list, + dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + dest_info->insert_pos = insert_pos; + dest_info->cell.row = row; + dest_info->cell.column = column; + + GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight + (clist, g_list_nth (clist->row_list, + dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + gdk_drag_status (context, context->suggested_action, time); + } + return TRUE; + } + } + + dest_info->insert_pos = insert_pos; + dest_info->cell.row = row; + dest_info->cell.column = column; + return TRUE; +} + +static gboolean +gtk_clist_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE); + g_return_val_if_fail (context != NULL, FALSE); + + if (GTK_CLIST_REORDERABLE (widget) && + gtk_drag_get_source_widget (context) == widget) + { + GList *list; + GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE); + + list = context->targets; + while (list) + { + if (atom == GPOINTER_TO_INT (list->data)) + return TRUE; + list = list->next; + } + } + return FALSE; +} + +static void +gtk_clist_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time) +{ + GtkCList *clist; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CLIST (widget)); + g_return_if_fail (context != NULL); + g_return_if_fail (selection_data != NULL); + + clist = GTK_CLIST (widget); + + if (GTK_CLIST_REORDERABLE (clist) && + gtk_drag_get_source_widget (context) == widget && + selection_data->target == + gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) && + selection_data->format == GTK_TYPE_POINTER && + selection_data->length == sizeof (GtkCListCellInfo)) + { + GtkCListCellInfo *source_info; + GtkCListDestInfo *dest_info; + + source_info = (GtkCListCellInfo *)(selection_data->data); + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (dest_info && source_info) + { + if (dest_info->insert_pos == GTK_CLIST_DRAG_AFTER) + dest_info->cell.row++; + if (source_info->row < dest_info->cell.row) + dest_info->cell.row--; + + if (dest_info->cell.row != source_info->row) + gtk_clist_row_move (GTK_CLIST (widget), + source_info->row, + dest_info->cell.row); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + } + } +} + +static void +gtk_clist_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CLIST (widget)); + g_return_if_fail (context != NULL); + g_return_if_fail (selection_data != NULL); + + if (selection_data->target == + gdk_atom_intern ("gtk-clist-drag-reorder", FALSE)) + { + GtkCListCellInfo *info; + + info = g_dataset_get_data (context, "gtk-clist-drag-source"); + + if (info) + { + GtkCListCellInfo *ret_info; + + ret_info = g_new (GtkCListCellInfo, 1); + ret_info->row = info->row; + ret_info->column = info->column; + + gtk_selection_data_set (selection_data, + selection_data->target, + GTK_TYPE_POINTER, + (guchar *) ret_info, + sizeof (GtkCListCellInfo)); + } + else + gtk_selection_data_set (selection_data, selection_data->target, + GTK_TYPE_POINTER, NULL, 0); + } +} + +static void +draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos) +{ + gint y; + + y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1; + + switch (drag_pos) + { + case GTK_CLIST_DRAG_NONE: + break; + case GTK_CLIST_DRAG_AFTER: + y += clist->row_height + 1; + case GTK_CLIST_DRAG_BEFORE: + gdk_draw_line (clist->clist_window, clist->xor_gc, + 0, y, clist->clist_window_width, y); + break; + case GTK_CLIST_DRAG_INTO: + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y, + clist->clist_window_width - 1, clist->row_height); + break; + } +} + +void +gtk_clist_set_reorderable (GtkCList *clist, + gboolean reorderable) +{ + GtkWidget *widget; + + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CLIST (clist)); + + if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable) + return; + + widget = GTK_WIDGET (clist); + + if (reorderable) + { + GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE); + gtk_drag_dest_set (widget, + GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, + &clist_target_table, 1, GDK_ACTION_MOVE); + } + else + { + GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE); + gtk_drag_dest_unset (GTK_WIDGET (clist)); + } +} + +void +gtk_clist_set_use_drag_icons (GtkCList *clist, + gboolean use_icons) +{ + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CLIST (clist)); + + if (use_icons != 0) + GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS); + else + GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS); +} + +void +gtk_clist_set_button_actions (GtkCList *clist, + guint button, + guint8 button_actions) +{ + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CLIST (clist)); + + if (button <= MAX_BUTTON) + { + if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist)) + { + remove_grab (clist); + clist->drag_button = 0; + } + + if (clist->anchor >= 0 && + clist->selection_mode == GTK_SELECTION_EXTENDED) + GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL); + + clist->button_actions[button] = button_actions; + } +} diff --git a/gtk/gtkclist.h b/gtk/gtkclist.h index 548f591f0..87fa02f42 100644 --- a/gtk/gtkclist.h +++ b/gtk/gtkclist.h @@ -36,14 +36,17 @@ extern "C" { /* clist flags */ enum { - GTK_CLIST_IN_DRAG = 1 << 0, - GTK_CLIST_DRAG_SELECTION = 1 << 1, - GTK_CLIST_ROW_HEIGHT_SET = 1 << 2, - GTK_CLIST_SHOW_TITLES = 1 << 3, - GTK_CLIST_CHILD_HAS_FOCUS = 1 << 4, - GTK_CLIST_ADD_MODE = 1 << 5, - GTK_CLIST_AUTO_SORT = 1 << 6, - GTK_CLIST_AUTO_RESIZE_BLOCKED = 1 << 7 + GTK_CLIST_IN_DRAG = 1 << 0, + GTK_CLIST_ROW_HEIGHT_SET = 1 << 1, + GTK_CLIST_SHOW_TITLES = 1 << 2, + GTK_CLIST_CHILD_HAS_FOCUS = 1 << 3, + GTK_CLIST_ADD_MODE = 1 << 4, + GTK_CLIST_AUTO_SORT = 1 << 5, + GTK_CLIST_AUTO_RESIZE_BLOCKED = 1 << 6, + GTK_CLIST_REORDERABLE = 1 << 7, + GTK_CLIST_USE_DRAG_ICONS = 1 << 8, + GTK_CLIST_DRAW_DRAG_LINE = 1 << 9, + GTK_CLIST_DRAW_DRAG_RECT = 1 << 10 }; /* cell types */ @@ -56,6 +59,22 @@ typedef enum GTK_CELL_WIDGET } GtkCellType; +typedef enum +{ + GTK_CLIST_DRAG_NONE, + GTK_CLIST_DRAG_BEFORE, + GTK_CLIST_DRAG_INTO, + GTK_CLIST_DRAG_AFTER +} GtkCListDragPos; + +typedef enum +{ + GTK_BUTTON_IGNORED = 0, + GTK_BUTTON_SELECTS = 1 << 0, + GTK_BUTTON_DRAGS = 1 << 1, + GTK_BUTTON_EXPANDS = 1 << 2 +} GtkButtonAction; + #define GTK_TYPE_CLIST (gtk_clist_get_type ()) #define GTK_CLIST(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CLIST, GtkCList)) #define GTK_CLIST_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CLIST, GtkCListClass)) @@ -70,10 +89,13 @@ typedef enum #define GTK_CLIST_ROW_HEIGHT_SET(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_ROW_HEIGHT_SET) #define GTK_CLIST_SHOW_TITLES(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_SHOW_TITLES) #define GTK_CLIST_CHILD_HAS_FOCUS(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_CHILD_HAS_FOCUS) -#define GTK_CLIST_DRAG_SELECTION(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAG_SELECTION) #define GTK_CLIST_ADD_MODE(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_ADD_MODE) #define GTK_CLIST_AUTO_SORT(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_SORT) #define GTK_CLIST_AUTO_RESIZE_BLOCKED(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_RESIZE_BLOCKED) +#define GTK_CLIST_REORDERABLE(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_REORDERABLE) +#define GTK_CLIST_USE_DRAG_ICONS(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_USE_DRAG_ICONS) +#define GTK_CLIST_DRAW_DRAG_LINE(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAW_DRAG_LINE) +#define GTK_CLIST_DRAW_DRAG_RECT(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAW_DRAG_RECT) #define GTK_CLIST_ROW(_glist_) ((GtkCListRow *)((_glist_)->data)) @@ -98,6 +120,21 @@ typedef gint (*GtkCListCompareFunc) (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2); +typedef struct _GtkCListCellInfo GtkCListCellInfo; +typedef struct _GtkCListDestInfo GtkCListDestInfo; + +struct _GtkCListCellInfo +{ + gint row; + gint column; +}; + +struct _GtkCListDestInfo +{ + GtkCListCellInfo cell; + GtkCListDragPos insert_pos; +}; + struct _GtkCList { GtkContainer container; @@ -153,6 +190,14 @@ struct _GtkCList GList *undo_unselection; gint undo_anchor; + /* mouse buttons */ + guint8 button_actions[5]; + + guint8 drag_button; + + /* dnd */ + GtkCListCellInfo click_cell; + /* scroll adjustments */ GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; @@ -236,6 +281,10 @@ struct _GtkCListClass GdkRectangle *area, gint row, GtkCListRow *clist_row); + void (*draw_drag_highlight) (GtkCList *clist, + GtkCListRow *target_row, + gint target_row_number, + GtkCListDragPos drag_pos); void (*clear) (GtkCList *clist); void (*fake_unselect_all) (GtkCList *clist, gint row); @@ -257,6 +306,7 @@ struct _GtkCListClass GtkCListRow *clist_row, gint column, GtkRequisition *requisition); + }; struct _GtkCListColumn @@ -407,6 +457,15 @@ void gtk_clist_set_shadow_type (GtkCList *clist, void gtk_clist_set_selection_mode (GtkCList *clist, GtkSelectionMode mode); +/* enable clists reorder ability */ +void gtk_clist_set_reorderable (GtkCList *clist, + gboolean reorderable); +void gtk_clist_set_use_drag_icons (GtkCList *clist, + gboolean use_icons); +void gtk_clist_set_button_actions (GtkCList *clist, + guint button, + guint8 button_actions); + /* freeze all visual updates of the list, and then thaw the list after * you have made a number of changes and the updates wil occure in a * more efficent mannor than if you made them on a unfrozen list diff --git a/gtk/gtkctree.c b/gtk/gtkctree.c index 0a4179df9..ec02c895c 100644 --- a/gtk/gtkctree.c +++ b/gtk/gtkctree.c @@ -25,6 +25,7 @@ #include "gtkctree.h" #include "gtkbindings.h" #include "gtkmain.h" +#include "gtkdnd.h" #include #include @@ -44,6 +45,26 @@ + (clist)->hoffset) #define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x) +static inline gint +COLUMN_FROM_XPIXEL (GtkCList * clist, + gint x) +{ + gint i, cx; + + for (i = 0; i < clist->columns; i++) + if (clist->column[i].visible) + { + cx = clist->column[i].area.x + clist->hoffset; + + if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) && + x <= (cx + clist->column[i].area.width + COLUMN_INSET)) + return i; + } + + /* no match */ + return -1; +} + #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass) #define CLIST_UNFROZEN(clist) (((GtkCList*) (clist))->freeze_count == 0) #define CLIST_REFRESH(clist) G_STMT_START { \ @@ -59,8 +80,6 @@ enum { ARG_INDENT, ARG_SPACING, ARG_SHOW_STUB, - ARG_REORDERABLE, - ARG_USE_DRAG_ICONS, ARG_LINE_STYLE, ARG_EXPANDER_STYLE }; @@ -78,10 +97,6 @@ static void gtk_ctree_realize (GtkWidget *widget); static void gtk_ctree_unrealize (GtkWidget *widget); static gint gtk_ctree_button_press (GtkWidget *widget, GdkEventButton *event); -static gint gtk_ctree_button_release (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_ctree_button_motion (GtkWidget *widget, - GdkEventMotion *event); static void ctree_attach_styles (GtkCTree *ctree, GtkCTreeNode *node, gpointer data); @@ -122,11 +137,11 @@ static gint gtk_ctree_draw_lines (GtkCTree *ctree, static void draw_row (GtkCList *clist, GdkRectangle *area, gint row, - GtkCListRow *clist_row); -static void draw_xor_line (GtkCTree *ctree); -static void draw_xor_rect (GtkCTree *ctree); -static void create_drag_icon (GtkCTree *ctree, - GtkCTreeRow *row); + GtkCListRow *clist_row); +static void draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos); static void tree_draw_node (GtkCTree *ctree, GtkCTreeNode *node); static void set_cell_contents (GtkCList *clist, @@ -196,9 +211,6 @@ static void real_tree_select (GtkCTree *ctree, static void real_tree_unselect (GtkCTree *ctree, GtkCTreeNode *node, gint column); -static void tree_toggle_selection (GtkCTree *ctree, - GtkCTreeNode *node, - gint column); static void real_tree_expand (GtkCTree *ctree, GtkCTreeNode *node); static void real_tree_collapse (GtkCTree *ctree, @@ -245,9 +257,6 @@ static gint real_insert_row (GtkCList *clist, static void real_remove_row (GtkCList *clist, gint row); static void real_sort_list (GtkCList *clist); -static void set_mouse_cursor (GtkCTree *ctree, - gboolean enable); -static void check_cursor (GtkCTree *ctree); static void cell_size_request (GtkCList *clist, GtkCListRow *clist_row, gint column, @@ -258,6 +267,27 @@ static void column_auto_resize (GtkCList *clist, gint old_width); static void auto_resize_columns (GtkCList *clist); + +static gboolean check_drag (GtkCTree *ctree, + GtkCTreeNode *drag_source, + GtkCTreeNode *drag_target, + GtkCListDragPos insert_pos); +static void gtk_ctree_drag_begin (GtkWidget *widget, + GdkDragContext *context); +static gint gtk_ctree_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void gtk_ctree_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time); + + enum { TREE_SELECT_ROW, @@ -269,26 +299,6 @@ enum LAST_SIGNAL }; -typedef void (*GtkCTreeSignal1) (GtkObject *object, - GtkCTreeNode *arg1, - gint arg2, - gpointer data); - -typedef void (*GtkCTreeSignal2) (GtkObject *object, - GtkCTreeNode *arg1, - GtkCTreeNode *arg2, - GtkCTreeNode *arg3, - gpointer data); - -typedef void (*GtkCTreeSignal3) (GtkObject *object, - GtkCTreeNode *arg1, - gpointer data); - -typedef void (*GtkCTreeSignal4) (GtkObject *object, - GtkCTreeExpansionType arg1, - gpointer data); - - static GtkCListClass *parent_class = NULL; static GtkContainerClass *container_class = NULL; static guint ctree_signals[LAST_SIGNAL] = {0}; @@ -354,14 +364,6 @@ gtk_ctree_class_init (GtkCTreeClass *klass) GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_STUB); - gtk_object_add_arg_type ("GtkCTree::reorderable", - GTK_TYPE_BOOL, - GTK_ARG_READWRITE, - ARG_REORDERABLE); - gtk_object_add_arg_type ("GtkCTree::use_drag_icons", - GTK_TYPE_BOOL, - GTK_ARG_READWRITE, - ARG_USE_DRAG_ICONS); gtk_object_add_arg_type ("GtkCTree::line_style", GTK_TYPE_CTREE_LINE_STYLE, GTK_ARG_READWRITE, @@ -422,8 +424,10 @@ gtk_ctree_class_init (GtkCTreeClass *klass) widget_class->realize = gtk_ctree_realize; widget_class->unrealize = gtk_ctree_unrealize; widget_class->button_press_event = gtk_ctree_button_press; - widget_class->button_release_event = gtk_ctree_button_release; - widget_class->motion_notify_event = gtk_ctree_button_motion; + + widget_class->drag_begin = gtk_ctree_drag_begin; + widget_class->drag_motion = gtk_ctree_drag_motion; + widget_class->drag_data_received = gtk_ctree_drag_data_received; clist_class->select_row = real_select_row; clist_class->unselect_row = real_unselect_row; @@ -433,6 +437,7 @@ gtk_ctree_class_init (GtkCTreeClass *klass) clist_class->selection_find = selection_find; clist_class->click_column = NULL; clist_class->draw_row = draw_row; + clist_class->draw_drag_highlight = draw_drag_highlight; clist_class->clear = real_clear; clist_class->select_all = real_select_all; clist_class->unselect_all = real_unselect_all; @@ -534,12 +539,6 @@ gtk_ctree_set_arg (GtkObject *object, case ARG_SHOW_STUB: gtk_ctree_set_show_stub (ctree, GTK_VALUE_BOOL (*arg)); break; - case ARG_REORDERABLE: - gtk_ctree_set_reorderable (ctree, GTK_VALUE_BOOL (*arg)); - break; - case ARG_USE_DRAG_ICONS: - gtk_ctree_set_use_drag_icons (ctree, GTK_VALUE_BOOL (*arg)); - break; case ARG_LINE_STYLE: gtk_ctree_set_line_style (ctree, GTK_VALUE_ENUM (*arg)); break; @@ -577,12 +576,6 @@ gtk_ctree_get_arg (GtkObject *object, case ARG_SHOW_STUB: GTK_VALUE_BOOL (*arg) = ctree->show_stub; break; - case ARG_REORDERABLE: - GTK_VALUE_BOOL (*arg) = ctree->reorderable; - break; - case ARG_USE_DRAG_ICONS: - GTK_VALUE_BOOL (*arg) = ctree->use_icons; - break; case ARG_LINE_STYLE: GTK_VALUE_ENUM (*arg) = ctree->line_style; break; @@ -598,22 +591,22 @@ gtk_ctree_get_arg (GtkObject *object, static void gtk_ctree_init (GtkCTree *ctree) { - ctree->drag_icon = NULL; + GtkCList *clist; + + GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_RECT); + GTK_CLIST_SET_FLAG (ctree, CLIST_DRAW_DRAG_LINE); + + clist = GTK_CLIST (ctree); + ctree->tree_indent = 20; ctree->tree_spacing = 5; ctree->tree_column = 0; - ctree->drag_row = -1; - ctree->drag_source = NULL; - ctree->drag_target = NULL; - ctree->insert_pos = GTK_CTREE_POS_AS_CHILD; - ctree->reorderable = FALSE; - ctree->use_icons = TRUE; - ctree->in_drag = FALSE; - ctree->drag_rect = FALSE; ctree->line_style = GTK_CTREE_LINES_SOLID; ctree->expander_style = GTK_CTREE_EXPANDER_SQUARE; ctree->drag_compare = NULL; ctree->show_stub = TRUE; + + clist->button_actions[0] |= GTK_BUTTON_EXPANDS; } static void @@ -753,6 +746,7 @@ gtk_ctree_button_press (GtkWidget *widget, { GtkCTree *ctree; GtkCList *clist; + gint button_actions; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); @@ -761,9 +755,13 @@ gtk_ctree_button_press (GtkWidget *widget, ctree = GTK_CTREE (widget); clist = GTK_CLIST (widget); + button_actions = clist->button_actions[event->button - 1]; + + if (button_actions == GTK_BUTTON_IGNORED) + return FALSE; + if (event->window == clist->clist_window) { - gboolean collapse_expand = FALSE; GtkCTreeNode *work; gint x; gint y; @@ -776,566 +774,175 @@ gtk_ctree_button_press (GtkWidget *widget, 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 = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - 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); - gtk_grab_add (widget); - ctree->in_drag = TRUE; - ctree->drag_source = work; - ctree->drag_target = NULL; - gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, - None, None); - gdk_gc_set_dashes (clist->xor_gc, 0, "\2\2", 2); - 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 (button_actions & GTK_BUTTON_EXPANDS && + (GTK_CTREE_ROW (work)->children && !GTK_CTREE_ROW (work)->is_leaf && + (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) - { - 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); - gtk_grab_add (widget); - - 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); } -static gint -gtk_ctree_button_motion (GtkWidget *widget, - GdkEventMotion *event) -{ - GtkCTree *ctree; - GtkCList *clist; - gint x; - gint y; - gint row; - gint insert_pos = GTK_CTREE_POS_AS_CHILD; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - ctree = GTK_CTREE (widget); - clist = GTK_CLIST (widget); - - 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 && ctree->reorderable) - { - GdkModifierType modmask; - gint root_x; - gint root_y; - - x = event->x; - y = event->y; - if (event->is_hint) - gdk_window_get_pointer (event->window, &x, &y, NULL); - - /* delayed drag start */ - if (!ctree->drag_target && - 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); - - if (ctree->use_icons) - { - if (!ctree->drag_icon) - create_drag_icon (ctree, GTK_CTREE_ROW (ctree->drag_source)); - else - { - gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask); - gdk_window_move (ctree->drag_icon, root_x - ctree->icon_width /2, - root_y - ctree->icon_height); - } - } - - /* out of bounds check */ - if (x < 0 || y < -3 || x > clist->clist_window_width || - y > clist->clist_window_height + 3 || - y > ROW_TOP_YPIXEL (clist, clist->rows-1) + clist->row_height + 3) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; - } - else - draw_xor_line (ctree); - ctree->drag_row = -1; - } - return - (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) - (widget, event); - } - - row = ROW_FROM_YPIXEL (clist, y); - - /* re-calculate target (mouse left the window) */ - if (ctree->drag_target && ctree->drag_row == -1) - ctree->drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list,row)); - - 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 - (widget, event); - - if (y - ROW_TOP_YPIXEL (clist, row) < clist->row_height / 4) - insert_pos = GTK_CTREE_POS_BEFORE; - else if (ROW_TOP_YPIXEL (clist, row) + clist->row_height - y - < clist->row_height / 4) - insert_pos = GTK_CTREE_POS_AFTER; - - if (row != ctree->drag_row || - (row == ctree->drag_row && ctree->insert_pos != insert_pos)) - { - if (insert_pos != GTK_CTREE_POS_AS_CHILD) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; - } - else - draw_xor_line (ctree); - } - ctree->insert_pos = insert_pos; - ctree->drag_target = - GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - ctree->drag_row = row; - draw_xor_line (ctree); - check_cursor(ctree); - } - else if (ctree->drag_target && - !GTK_CTREE_ROW (ctree->drag_target)->is_leaf) - { - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - draw_xor_rect (ctree); - else - draw_xor_line (ctree); - } - ctree->drag_rect = TRUE; - ctree->insert_pos = insert_pos; - ctree->drag_target = - GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); - ctree->drag_row = row; - draw_xor_rect (ctree); - check_cursor(ctree); - } - } - } - return GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); -} - -static gint -gtk_ctree_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - GtkCTree *ctree; - GtkCList *clist; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - ctree = GTK_CTREE (widget); - clist = GTK_CLIST (widget); - - if (event->button == 2 && clist->anchor == -1) - { - gtk_grab_remove (widget); - gdk_pointer_ungrab (event->time); - - ctree->in_drag = FALSE; - - set_mouse_cursor(ctree, TRUE); - - if (ctree->use_icons && ctree->drag_icon) - { - gdk_window_destroy (ctree->drag_icon); - ctree->drag_icon = NULL; - } - - if (ctree->drag_row >= 0) - { - if (ctree->drag_rect) - { - draw_xor_rect (ctree); - ctree->drag_rect = FALSE; - } - else - draw_xor_line (ctree); - ctree->drag_row = -1; - } - - if (GTK_CLIST_ADD_MODE (clist)) - gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2); - else - gdk_gc_set_line_attributes (clist->xor_gc, 1, - GDK_LINE_SOLID, 0, 0); - - /* 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 || - !ctree->drag_target) - return GTK_WIDGET_CLASS (parent_class)->button_release_event - (widget, event); - - if (!GTK_CTREE_ROW (ctree->drag_source)->children || - !gtk_ctree_is_ancestor (ctree, ctree->drag_source, - ctree->drag_target)) - { - if (ctree->insert_pos == GTK_CTREE_POS_AFTER) - { - if (GTK_CTREE_ROW (ctree->drag_target)->sibling != - ctree->drag_source) - if (!ctree->drag_compare || - ctree->drag_compare (ctree, - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - GTK_CTREE_ROW (ctree->drag_target)->sibling)) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - GTK_CTREE_ROW (ctree->drag_target)->sibling); - } - else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE) - { - if (GTK_CTREE_ROW (ctree->drag_source)->sibling != - ctree->drag_target) - if (!ctree->drag_compare || - ctree->drag_compare (ctree, - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - ctree->drag_target)) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - ctree->drag_target); - } - else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf) - { - if (GTK_CTREE_ROW (ctree->drag_target)->children != - ctree->drag_source) - if (!ctree->drag_compare || - ctree->drag_compare (ctree, - ctree->drag_source, - ctree->drag_target, - GTK_CTREE_ROW (ctree->drag_target)->children)) - gtk_signal_emit (GTK_OBJECT (ctree), - ctree_signals[TREE_MOVE], - ctree->drag_source, - ctree->drag_target, - GTK_CTREE_ROW (ctree->drag_target)->children); - } - } - ctree->drag_source = NULL; - ctree->drag_target = NULL; - } - 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; - GtkCTreeNode *work; - - if (gtk_clist_get_selection_info - (clist, event->x, event->y, &row, &column)) - { - if (clist->anchor == clist->focus_row && - (work = GTK_CTREE_NODE (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 -create_drag_icon (GtkCTree *ctree, - GtkCTreeRow *row) +draw_drag_highlight (GtkCList *clist, + GtkCListRow *dest_row, + gint dest_row_number, + GtkCListDragPos drag_pos) { - GtkCList *clist; - GtkWidget *widget; - GdkWindow *window = NULL; - GdkWindowAttr attributes; - gint attributes_mask; - GdkPixmap *pixmap; - GdkBitmap *mask; - GdkModifierType modmask; - gint root_x; - gint root_y; - - clist = GTK_CLIST (ctree); - widget = GTK_WIDGET (ctree); - - if (!(pixmap = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->pixmap)) - return; - mask = GTK_CELL_PIXTEXT (row->row.cell[ctree->tree_column])->mask; - - gdk_window_get_pointer (NULL, &root_x, &root_y, &modmask); - gdk_window_get_size (pixmap, &ctree->icon_width, &ctree->icon_height); - - attributes.window_type = GDK_WINDOW_TEMP; - attributes.x = root_x - ctree->icon_width / 2; - attributes.y = root_y - ctree->icon_height; - attributes.width = ctree->icon_width; - attributes.height = ctree->icon_height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget); - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - window = gdk_window_new (widget->window, &attributes, attributes_mask); - gdk_window_set_back_pixmap (window, pixmap, FALSE); - if (mask) - gdk_window_shape_combine_mask (window, mask, 0, 0); - gdk_window_show (window); - - ctree->drag_icon = window; -} - -static void -draw_xor_line (GtkCTree *ctree) -{ - GtkCList *clist; + GtkCTree *ctree; + GdkPoint points[4]; gint level; + gint i; gint y = 0; - clist = GTK_CLIST (ctree); + g_return_if_fail (clist != NULL); + g_return_if_fail (GTK_IS_CTREE (clist)); - level = GTK_CTREE_ROW (ctree->drag_target)->level; + ctree = GTK_CTREE (clist); - if (ctree->insert_pos == GTK_CTREE_POS_AFTER) - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height; - else - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) - 1; + level = ((GtkCTreeRow *)(dest_row))->level; - if (clist->column[ctree->tree_column].visible) - switch (clist->column[ctree->tree_column].justification) - { - case GTK_JUSTIFY_CENTER: - case GTK_JUSTIFY_FILL: - case GTK_JUSTIFY_LEFT: - if (ctree->tree_column > 0) - gdk_draw_line (clist->clist_window, clist->xor_gc, - COLUMN_LEFT_XPIXEL(clist, 0), y, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) + - clist->column[ctree->tree_column - 1].area.width, y); + y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1; + + switch (drag_pos) + { + case GTK_CLIST_DRAG_NONE: + break; + case GTK_CLIST_DRAG_AFTER: + y += clist->row_height + 1; + case GTK_CLIST_DRAG_BEFORE: - gdk_draw_line (clist->clist_window, clist->xor_gc, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + - ctree->tree_indent * level - - (ctree->tree_indent - PM_SIZE) / 2, y, - GTK_WIDGET (ctree)->allocation.width, y); - break; - case GTK_JUSTIFY_RIGHT: - if (ctree->tree_column < clist->columns - 1) - gdk_draw_line (clist->clist_window, clist->xor_gc, - COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), y, - COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) + - clist->column[clist->columns - 1].area.width, y); + if (clist->column[ctree->tree_column].visible) + switch (clist->column[ctree->tree_column].justification) + { + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + if (ctree->tree_column > 0) + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, 0), y, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+ + clist->column[ctree->tree_column - 1].area.width, + y); + + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + ctree->tree_indent * level - + (ctree->tree_indent - PM_SIZE) / 2, y, + GTK_WIDGET (ctree)->allocation.width, y); + break; + case GTK_JUSTIFY_RIGHT: + if (ctree->tree_column < clist->columns - 1) + gdk_draw_line (clist->clist_window, clist->xor_gc, + COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1), + y, + COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) + + clist->column[clist->columns - 1].area.width, y); + gdk_draw_line (clist->clist_window, clist->xor_gc, + 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + clist->column[ctree->tree_column].area.width - + ctree->tree_indent * level + + (ctree->tree_indent - PM_SIZE) / 2, y); + break; + } + else gdk_draw_line (clist->clist_window, clist->xor_gc, - 0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - + clist->column[ctree->tree_column].area.width - - ctree->tree_indent * level + - (ctree->tree_indent - PM_SIZE) / 2, y); - break; - } - else - gdk_draw_line (clist->clist_window, clist->xor_gc, - 0, y, clist->clist_window_width, y); -} - -static void -draw_xor_rect (GtkCTree *ctree) -{ - GtkCList *clist; - GdkPoint points[4]; - guint level; - gint i; - gint y; - - clist = GTK_CLIST (ctree); - - level = GTK_CTREE_ROW (ctree->drag_target)->level; - - y = ROW_TOP_YPIXEL (clist, ctree->drag_row) + clist->row_height; + 0, y, clist->clist_window_width, y); + break; + case GTK_CLIST_DRAG_INTO: + y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height; - if (clist->column[ctree->tree_column].visible) - switch (clist->column[ctree->tree_column].justification) - { - case GTK_JUSTIFY_CENTER: - case GTK_JUSTIFY_FILL: - case GTK_JUSTIFY_LEFT: - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + - ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2; - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = clist->clist_window_width - 1; - points[1].y = points[0].y; - points[2].x = points[1].x; - points[2].y = points[3].y; - - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, clist->xor_gc, - points[i].x, points[i].y, - points[i+1].x, points[i+1].y); - - if (ctree->tree_column > 0) + if (clist->column[ctree->tree_column].visible) + switch (clist->column[ctree->tree_column].justification) { - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1) + - clist->column[ctree->tree_column - 1].area.width ; + case GTK_JUSTIFY_CENTER: + case GTK_JUSTIFY_FILL: + case GTK_JUSTIFY_LEFT: + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + + ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2; points[0].y = y; points[3].x = points[0].x; points[3].y = y - clist->row_height - 1; - points[1].x = 0; + points[1].x = clist->clist_window_width - 1; points[1].y = points[0].y; - points[2].x = 0; + points[2].x = points[1].x; points[2].y = points[3].y; for (i = 0; i < 3; i++) gdk_draw_line (clist->clist_window, clist->xor_gc, - points[i].x, points[i].y, points[i+1].x, - points[i+1].y); - } - break; - case GTK_JUSTIFY_RIGHT: - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - - ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 + - clist->column[ctree->tree_column].area.width; - points[0].y = y; - points[3].x = points[0].x; - points[3].y = y - clist->row_height - 1; - points[1].x = 0; - points[1].y = points[0].y; - points[2].x = 0; - points[2].y = points[3].y; - - for (i = 0; i < 3; i++) - gdk_draw_line (clist->clist_window, clist->xor_gc, - points[i].x, points[i].y, - points[i+1].x, points[i+1].y); - - if (ctree->tree_column < clist->columns - 1) - { - points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1); + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + + if (ctree->tree_column > 0) + { + points[0].x = COLUMN_LEFT_XPIXEL(clist, + ctree->tree_column - 1) + + clist->column[ctree->tree_column - 1].area.width ; + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = 0; + points[1].y = points[0].y; + points[2].x = 0; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, points[i+1].x, + points[i+1].y); + } + break; + case GTK_JUSTIFY_RIGHT: + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - + ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 + + clist->column[ctree->tree_column].area.width; points[0].y = y; points[3].x = points[0].x; points[3].y = y - clist->row_height - 1; - points[1].x = clist->clist_window_width - 1; + points[1].x = 0; points[1].y = points[0].y; - points[2].x = points[1].x; + points[2].x = 0; points[2].y = points[3].y; for (i = 0; i < 3; i++) gdk_draw_line (clist->clist_window, clist->xor_gc, points[i].x, points[i].y, points[i+1].x, points[i+1].y); + + if (ctree->tree_column < clist->columns - 1) + { + points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1); + points[0].y = y; + points[3].x = points[0].x; + points[3].y = y - clist->row_height - 1; + points[1].x = clist->clist_window_width - 1; + points[1].y = points[0].y; + points[2].x = points[1].x; + points[2].y = points[3].y; + + for (i = 0; i < 3; i++) + gdk_draw_line (clist->clist_window, clist->xor_gc, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + break; } - break; - } - else - gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, - 0, y - clist->row_height, - clist->clist_window_width - 1, clist->row_height); + else + gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, + 0, y - clist->row_height, + clist->clist_window_width - 1, clist->row_height); + break; + } } static gint @@ -3748,42 +3355,6 @@ real_tree_unselect (GtkCTree *ctree, tree_draw_node (ctree, node); } -static void -tree_toggle_selection (GtkCTree *ctree, - GtkCTreeNode *node, - gint column) -{ - 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: - if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_SELECTED) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], - node, column); - else if (node && GTK_CTREE_ROW (node)->row.selectable) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], - node, column); - break; - - case GTK_SELECTION_BROWSE: - if (node && GTK_CTREE_ROW (node)->row.state == GTK_STATE_NORMAL && - GTK_CTREE_ROW (node)->row.selectable) - gtk_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], - node, column); - break; - - case GTK_SELECTION_EXTENDED: - break; - } -} - static void select_row_recursive (GtkCTree *ctree, GtkCTreeNode *node, @@ -4276,13 +3847,6 @@ real_clear (GtkCList *clist) ctree = GTK_CTREE (clist); - 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 rows */ work = GTK_CTREE_NODE (clist->row_list); clist->row_list = NULL; @@ -5186,7 +4750,7 @@ gtk_ctree_node_set_shift (GtkCTree *ctree, void gtk_ctree_node_set_selectable (GtkCTree *ctree, GtkCTreeNode *node, - gboolean selectable) + gboolean selectable) { g_return_if_fail (ctree != NULL); g_return_if_fail (GTK_IS_CTREE (ctree)); @@ -5208,7 +4772,7 @@ gtk_ctree_node_set_selectable (GtkCTree *ctree, { if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist))) { - GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION); + clist->drag_button = 0; gtk_grab_remove (GTK_WIDGET (clist)); gdk_pointer_ungrab (GDK_CURRENT_TIME); if (clist->htimer) @@ -5687,14 +5251,6 @@ gtk_ctree_set_spacing (GtkCTree *ctree, CLIST_REFRESH (ctree); } -void -gtk_ctree_show_stub (GtkCTree *ctree, - gboolean show_stub) -{ - g_message ("gtk_ctree_show_stub() is deprecated"); - gtk_ctree_set_show_stub (ctree, show_stub); -} - void gtk_ctree_set_show_stub (GtkCTree *ctree, gboolean show_stub) @@ -5718,29 +5274,6 @@ gtk_ctree_set_show_stub (GtkCTree *ctree, } } -void -gtk_ctree_set_reorderable (GtkCTree *ctree, - gboolean reorderable) -{ - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); - - ctree->reorderable = reorderable; -} - -void -gtk_ctree_set_use_drag_icons (GtkCTree *ctree, - gboolean use_icons) -{ - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); - - if (ctree->use_icons == (use_icons != 0)) - return; - - ctree->use_icons = (use_icons != 0); -} - void gtk_ctree_set_line_style (GtkCTree *ctree, GtkCTreeLineStyle line_style) @@ -6195,73 +5728,375 @@ gtk_ctree_set_drag_compare_func (GtkCTree *ctree, ctree->drag_compare = cmp_func; } +static gboolean +check_drag (GtkCTree *ctree, + GtkCTreeNode *drag_source, + GtkCTreeNode *drag_target, + GtkCListDragPos insert_pos) +{ + g_return_val_if_fail (ctree != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CTREE (ctree), FALSE); + + if (drag_source && drag_source != drag_target && + (!GTK_CTREE_ROW (drag_source)->children || + !gtk_ctree_is_ancestor (ctree, drag_source, drag_target))) + { + switch (insert_pos) + { + case GTK_CLIST_DRAG_NONE: + return FALSE; + case GTK_CLIST_DRAG_AFTER: + if (GTK_CTREE_ROW (drag_target)->sibling != drag_source) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + GTK_CTREE_ROW (drag_target)->parent, + GTK_CTREE_ROW(drag_target)->sibling)); + break; + case GTK_CLIST_DRAG_BEFORE: + if (GTK_CTREE_ROW (drag_source)->sibling != drag_target) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + GTK_CTREE_ROW (drag_target)->parent, + drag_target)); + break; + case GTK_CLIST_DRAG_INTO: + if (!GTK_CTREE_ROW (drag_target)->is_leaf && + GTK_CTREE_ROW (drag_target)->children != drag_source) + return (!ctree->drag_compare || + ctree->drag_compare (ctree, + drag_source, + drag_target, + GTK_CTREE_ROW (drag_target)->children)); + break; + } + } + return FALSE; +} + + + +/************************************/ static void -set_mouse_cursor (GtkCTree *ctree, - gboolean enable) +drag_source_info_destroy (gpointer data) { - GdkCursor *cursor; + GtkCListCellInfo *info = data; - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); + g_free (info); +} - if (enable) - cursor = gdk_cursor_new (GDK_LEFT_PTR); - else - cursor = gdk_cursor_new (GDK_CIRCLE); +static void +drag_dest_info_destroy (gpointer data) +{ + GtkCListDestInfo *info = data; - gdk_window_set_cursor (GTK_CLIST (ctree)->clist_window, cursor); - gdk_cursor_destroy (cursor); + g_free (info); } static void -check_cursor (GtkCTree *ctree) +gtk_ctree_drag_begin (GtkWidget *widget, + GdkDragContext *context) { - g_return_if_fail (ctree != NULL); - g_return_if_fail (GTK_IS_CTREE (ctree)); + GtkCList *clist; + GtkCTree *ctree; + GtkCListCellInfo *info; - if (!GTK_CTREE_ROW (ctree->drag_source)->children || - !gtk_ctree_is_ancestor (ctree, ctree->drag_source, ctree->drag_target)) + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CTREE (widget)); + g_return_if_fail (context != NULL); + + clist = GTK_CLIST (widget); + ctree = GTK_CTREE (widget); + + info = g_dataset_get_data (context, "gtk-clist-drag-source"); + + if (!info) { - if (ctree->insert_pos == GTK_CTREE_POS_AFTER) + info = g_new (GtkCListCellInfo, 1); + + if (clist->click_cell.row < 0) + clist->click_cell.row = 0; + else if (clist->click_cell.row >= clist->rows) + clist->click_cell.row = clist->rows - 1; + info->row = clist->click_cell.row; + info->column = clist->click_cell.column; + + g_dataset_set_data_full (context, "gtk-clist-drag-source", info, + drag_source_info_destroy); + } + + if (GTK_CLIST_USE_DRAG_ICONS (clist)) + { + GtkCTreeNode *node; + + node = GTK_CTREE_NODE (g_list_nth (clist->row_list, info->row)); + if (node) { - if (GTK_CTREE_ROW (ctree->drag_target)->sibling != - ctree->drag_source) - set_mouse_cursor - (ctree, - (!ctree->drag_compare || - ctree->drag_compare - (ctree, - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - GTK_CTREE_ROW (ctree->drag_target)->sibling))); + if (GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap) + { + gtk_drag_set_icon_pixmap + (context, + gtk_widget_get_colormap (widget), + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap, + GTK_CELL_PIXTEXT + (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask, + -2, -2); + return; + } } - else if (ctree->insert_pos == GTK_CTREE_POS_BEFORE) + gtk_drag_set_icon_default (context); + } +} + +static gint +gtk_ctree_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkCList *clist; + GtkCTree *ctree; + gint row, column; + GtkCListDestInfo *dest_info; + gint h = 0; + gint insert_pos = GTK_CLIST_DRAG_NONE; + gint y_delta; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CTREE (widget), FALSE); + + clist = GTK_CLIST (widget); + ctree = GTK_CTREE (widget); + + if (gtk_drag_get_source_widget (context) != widget) + { + gdk_drag_status (context, GDK_ACTION_DEFAULT, time); + return FALSE; + } + + y -= (GTK_CONTAINER (widget)->border_width + + widget->style->klass->ythickness + clist->column_title_area.height); + row = ROW_FROM_YPIXEL (clist, y); + + if (row >= clist->rows) + { + row = clist->rows - 1; + y = ROW_TOP_YPIXEL (clist, row) + clist->row_height; + } + if (row < -1) + row = -1; + + x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness; + column = COLUMN_FROM_XPIXEL (clist, x); + + if (row >= 0) + { + y_delta = y - ROW_TOP_YPIXEL (clist, row); + + if (GTK_CLIST_DRAW_DRAG_RECT(clist)) { - if (GTK_CTREE_ROW (ctree->drag_source)->sibling != - ctree->drag_target) - set_mouse_cursor - (ctree, - (!ctree->drag_compare || - ctree->drag_compare - (ctree, - ctree->drag_source, - GTK_CTREE_ROW (ctree->drag_target)->parent, - ctree->drag_target))); + insert_pos = GTK_CLIST_DRAG_INTO; + h = clist->row_height / 4; } - else if (!GTK_CTREE_ROW (ctree->drag_target)->is_leaf) + else if (GTK_CLIST_DRAW_DRAG_LINE(clist)) + { + insert_pos = GTK_CLIST_DRAG_BEFORE; + h = clist->row_height / 2; + } + + if (GTK_CLIST_DRAW_DRAG_LINE(clist)) { - if (GTK_CTREE_ROW (ctree->drag_target)->children != - ctree->drag_source) - set_mouse_cursor - (ctree, - (!ctree->drag_compare || - ctree->drag_compare - (ctree, - ctree->drag_source, - ctree->drag_target, - GTK_CTREE_ROW (ctree->drag_target)->children))); + if (y_delta < h) + insert_pos = GTK_CLIST_DRAG_BEFORE; + else if (clist->row_height - y_delta < h) + insert_pos = GTK_CLIST_DRAG_AFTER; } } - else - set_mouse_cursor(ctree, FALSE); + + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (!dest_info) + { + dest_info = g_new (GtkCListDestInfo, 1); + + dest_info->cell.row = -1; + dest_info->cell.column = -1; + dest_info->insert_pos = GTK_CLIST_DRAG_NONE; + + g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info, + drag_dest_info_destroy); + } + + if (GTK_CLIST_REORDERABLE (clist)) + { + GList *list; + GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE); + + list = context->targets; + while (list) + { + if (atom == GPOINTER_TO_INT (list->data)) + break; + list = list->next; + } + + if (list) + { + GtkCTreeNode *drag_source; + GtkCTreeNode *drag_target; + + drag_source = GTK_CTREE_NODE (g_list_nth (clist->row_list, + clist->click_cell.row)); + drag_target = GTK_CTREE_NODE (g_list_nth (clist->row_list, row)); + + if (gtk_drag_get_source_widget (context) != widget || + !check_drag (ctree, drag_source, drag_target, insert_pos)) + { + if (dest_info->cell.row < 0) + { + gdk_drag_status (context, GDK_ACTION_DEFAULT, time); + return FALSE; + } + return TRUE; + } + + if (row != dest_info->cell.row || + (row == dest_info->cell.row && + dest_info->insert_pos != insert_pos)) + { + if (dest_info->cell.row >= 0) + GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight + (clist, + g_list_nth (clist->row_list, dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + dest_info->insert_pos = insert_pos; + dest_info->cell.row = row; + dest_info->cell.column = column; + + GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight + (clist, + g_list_nth (clist->row_list, dest_info->cell.row)->data, + dest_info->cell.row, dest_info->insert_pos); + + gdk_drag_status (context, context->suggested_action, time); + } + return TRUE; + } + } + + dest_info->insert_pos = insert_pos; + dest_info->cell.row = row; + dest_info->cell.column = column; + return TRUE; +} + +static void +gtk_ctree_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint32 time) +{ + GtkCTree *ctree; + GtkCList *clist; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CTREE (widget)); + g_return_if_fail (context != NULL); + g_return_if_fail (selection_data != NULL); + + ctree = GTK_CTREE (widget); + clist = GTK_CLIST (widget); + + if (GTK_CLIST_REORDERABLE (clist) && + gtk_drag_get_source_widget (context) == widget && + selection_data->target == + gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) && + selection_data->format == GTK_TYPE_POINTER && + selection_data->length == sizeof (GtkCListCellInfo)) + { + GtkCListCellInfo *source_info; + GtkCListDestInfo *dest_info; + + source_info = (GtkCListCellInfo *)(selection_data->data); + dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest"); + + if (dest_info && source_info) + { + GtkCTreeNode *source_node; + GtkCTreeNode *dest_node; + + source_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, + source_info->row)); + dest_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, + dest_info->cell.row)); + + if (!source_info || !dest_info) + return; + + switch (dest_info->insert_pos) + { + case GTK_CLIST_DRAG_NONE: + break; + case GTK_CLIST_DRAG_INTO: + if (check_drag (ctree, source_node, dest_node, + dest_info->insert_pos)) + gtk_ctree_move (ctree, source_node, dest_node, + GTK_CTREE_ROW (dest_node)->children); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + case GTK_CLIST_DRAG_BEFORE: + if (check_drag (ctree, source_node, dest_node, + dest_info->insert_pos)) + gtk_ctree_move (ctree, source_node, + GTK_CTREE_ROW (dest_node)->parent, dest_node); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + case GTK_CLIST_DRAG_AFTER: + if (check_drag (ctree, source_node, dest_node, + dest_info->insert_pos)) + gtk_ctree_move (ctree, source_node, + GTK_CTREE_ROW (dest_node)->parent, + GTK_CTREE_ROW (dest_node)->sibling); + g_dataset_remove_data (context, "gtk-clist-drag-dest"); + break; + } + } + } +} + +/* deprecated*/ +void +gtk_ctree_set_reorderable (GtkCTree *ctree, + gboolean reorderable) +{ + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + + gtk_clist_set_reorderable (GTK_CLIST (ctree), reorderable); +} + +void +gtk_ctree_set_use_drag_icons (GtkCTree *ctree, + gboolean use_icons) +{ + g_return_if_fail (ctree != NULL); + g_return_if_fail (GTK_IS_CTREE (ctree)); + + gtk_clist_set_use_drag_icons (GTK_CLIST (ctree), use_icons); +} + +void +gtk_ctree_show_stub (GtkCTree *ctree, + gboolean show_stub) +{ + g_message ("gtk_ctree_show_stub() is deprecated"); + gtk_ctree_set_show_stub (ctree, show_stub); } diff --git a/gtk/gtkctree.h b/gtk/gtkctree.h index 141316a14..6f710911e 100644 --- a/gtk/gtkctree.h +++ b/gtk/gtkctree.h @@ -100,22 +100,11 @@ struct _GtkCTree GtkCList clist; GdkGC *lines_gc; - GdkWindow *drag_icon; - gint icon_width; - gint icon_height; gint tree_indent; gint tree_spacing; gint tree_column; - gint drag_row; - GtkCTreeNode *drag_source; - GtkCTreeNode *drag_target; - gint insert_pos; - - guint reorderable : 1; - guint use_icons : 1; - guint in_drag : 1; - guint drag_rect : 1; + guint line_style : 2; guint expander_style : 2; guint show_stub : 1; @@ -418,10 +407,6 @@ void gtk_ctree_set_spacing (GtkCTree *ctree, gint spacing); void gtk_ctree_set_show_stub (GtkCTree *ctree, gboolean show_stub); -void gtk_ctree_set_reorderable (GtkCTree *ctree, - gboolean reorderable); -void gtk_ctree_set_use_drag_icons (GtkCTree *ctree, - gboolean use_icons); void gtk_ctree_set_line_style (GtkCTree *ctree, GtkCTreeLineStyle line_style); void gtk_ctree_set_expander_style (GtkCTree *ctree, @@ -442,7 +427,10 @@ void gtk_ctree_sort_recursive (GtkCTree *ctree, /* deprecated*/ void gtk_ctree_show_stub (GtkCTree *ctree, gboolean show_stub); - +void gtk_ctree_set_reorderable (GtkCTree *ctree, + gboolean reorderable); +void gtk_ctree_set_use_drag_icons (GtkCTree *ctree, + gboolean use_icons); #ifdef __cplusplus diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 52f88989f..0cf829b36 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -3722,6 +3722,11 @@ hide_titles_clist (GtkWidget *widget, gpointer data) gtk_clist_column_titles_hide (GTK_CLIST (data)); } +void toggle_reorderable (GtkWidget *widget, GtkCList *clist) +{ + gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active); +} + void select_clist (GtkWidget *widget, gint row, @@ -3995,6 +4000,7 @@ create_clist (void) GtkWidget *button; GtkWidget *separator; GtkWidget *scrolled_win; + GtkWidget *check; GtkWidget *undo_button; GtkWidget *label; @@ -4097,6 +4103,12 @@ create_clist (void) gtk_signal_connect (GTK_OBJECT (undo_button), "clicked", (GtkSignalFunc) undo_selection, (gpointer) clist); + check = gtk_check_button_new_with_label ("Reorderable"); + gtk_signal_connect (GTK_OBJECT (check), "clicked", + GTK_SIGNAL_FUNC (toggle_reorderable), clist); + gtk_box_pack_start (GTK_BOX (box2), check, FALSE, TRUE, 0); + gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (check), TRUE); + label = gtk_label_new ("Selection Mode :"); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0); @@ -4112,18 +4124,6 @@ create_clist (void) * the rest of the clist configuration */ - /* - gtk_signal_connect (GTK_OBJECT (clist), - "select_row", - (GtkSignalFunc) select_clist, - undo_button); - - gtk_signal_connect (GTK_OBJECT (clist), - "unselect_row", - (GtkSignalFunc) unselect_clist, - undo_button); - */ - gtk_clist_set_row_height (GTK_CLIST (clist), 18); gtk_widget_set_usize (clist, -1, 300); @@ -4275,74 +4275,6 @@ void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, (parent) ? target1 : "nil", (sibling) ? target2 : "nil"); } -gint button_press (GtkCTree *ctree, GdkEventButton *event, gpointer data) -{ - gint row; - gint column; - GtkCTreeNode *work; - gint res; - - res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, - &row, &column); - if (!res && event->button != 3) - return FALSE; - - work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row)); - - switch (event->button) - { - case 1: - if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE && - event->state & GDK_SHIFT_MASK) - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),"button_press_event"); - break; - case 2: - if (GTK_CTREE_ROW (work)->children && - gtk_ctree_is_hot_spot (ctree, event->x, event->y)) - { - if (GTK_CTREE_ROW (work)->expanded) - gtk_ctree_collapse_recursive (ctree, work); - else - gtk_ctree_expand_recursive (ctree, work); - after_press (ctree, NULL); - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), - "button_press_event"); - } - break; - default: - break; - } - return FALSE; -} - -gint button_release (GtkCTree *ctree, GdkEventButton *event, gpointer data) -{ - gint row; - gint column; - GtkCTreeNode *work; - gint res; - - res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, - &row, &column); - if (!res || event->button != 1) - return FALSE; - - work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row)); - - if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE && - event->state & GDK_SHIFT_MASK) - { - if (GTK_CTREE_ROW (work)->row.state == GTK_STATE_SELECTED) - gtk_ctree_unselect_recursive (ctree, work); - else - gtk_ctree_select_recursive (ctree, work); - after_press (ctree, NULL); - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), - "button_release_event"); - } - return FALSE; -} - void count_items (GtkCTree *ctree, GtkCTreeNode *list) { if (GTK_CTREE_ROW (list)->is_leaf) @@ -4616,11 +4548,6 @@ void change_row_height (GtkWidget *widget, GtkCList *clist) gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value); } -void toggle_reorderable (GtkWidget *widget, GtkCTree *ctree) -{ - gtk_ctree_set_reorderable (ctree, GTK_TOGGLE_BUTTON (widget)->active); -} - void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { GtkStyle *style = NULL; @@ -4953,16 +4880,11 @@ void create_ctree (void) gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED); line_style = GTK_CTREE_LINES_DOTTED; - gtk_ctree_set_reorderable (ctree, TRUE); gtk_signal_connect (GTK_OBJECT (ctree), "click_column", (GtkSignalFunc) ctree_click_column, NULL); - gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event", - GTK_SIGNAL_FUNC (button_press), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "button_press_event", GTK_SIGNAL_FUNC (after_press), NULL); - gtk_signal_connect (GTK_OBJECT (ctree), "button_release_event", - GTK_SIGNAL_FUNC (button_release), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "button_release_event", GTK_SIGNAL_FUNC (after_press), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "tree_move", diff --git a/tests/testgtk.c b/tests/testgtk.c index 52f88989f..0cf829b36 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -3722,6 +3722,11 @@ hide_titles_clist (GtkWidget *widget, gpointer data) gtk_clist_column_titles_hide (GTK_CLIST (data)); } +void toggle_reorderable (GtkWidget *widget, GtkCList *clist) +{ + gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active); +} + void select_clist (GtkWidget *widget, gint row, @@ -3995,6 +4000,7 @@ create_clist (void) GtkWidget *button; GtkWidget *separator; GtkWidget *scrolled_win; + GtkWidget *check; GtkWidget *undo_button; GtkWidget *label; @@ -4097,6 +4103,12 @@ create_clist (void) gtk_signal_connect (GTK_OBJECT (undo_button), "clicked", (GtkSignalFunc) undo_selection, (gpointer) clist); + check = gtk_check_button_new_with_label ("Reorderable"); + gtk_signal_connect (GTK_OBJECT (check), "clicked", + GTK_SIGNAL_FUNC (toggle_reorderable), clist); + gtk_box_pack_start (GTK_BOX (box2), check, FALSE, TRUE, 0); + gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (check), TRUE); + label = gtk_label_new ("Selection Mode :"); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0); @@ -4112,18 +4124,6 @@ create_clist (void) * the rest of the clist configuration */ - /* - gtk_signal_connect (GTK_OBJECT (clist), - "select_row", - (GtkSignalFunc) select_clist, - undo_button); - - gtk_signal_connect (GTK_OBJECT (clist), - "unselect_row", - (GtkSignalFunc) unselect_clist, - undo_button); - */ - gtk_clist_set_row_height (GTK_CLIST (clist), 18); gtk_widget_set_usize (clist, -1, 300); @@ -4275,74 +4275,6 @@ void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, (parent) ? target1 : "nil", (sibling) ? target2 : "nil"); } -gint button_press (GtkCTree *ctree, GdkEventButton *event, gpointer data) -{ - gint row; - gint column; - GtkCTreeNode *work; - gint res; - - res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, - &row, &column); - if (!res && event->button != 3) - return FALSE; - - work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row)); - - switch (event->button) - { - case 1: - if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE && - event->state & GDK_SHIFT_MASK) - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree),"button_press_event"); - break; - case 2: - if (GTK_CTREE_ROW (work)->children && - gtk_ctree_is_hot_spot (ctree, event->x, event->y)) - { - if (GTK_CTREE_ROW (work)->expanded) - gtk_ctree_collapse_recursive (ctree, work); - else - gtk_ctree_expand_recursive (ctree, work); - after_press (ctree, NULL); - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), - "button_press_event"); - } - break; - default: - break; - } - return FALSE; -} - -gint button_release (GtkCTree *ctree, GdkEventButton *event, gpointer data) -{ - gint row; - gint column; - GtkCTreeNode *work; - gint res; - - res = gtk_clist_get_selection_info (GTK_CLIST (ctree), event->x, event->y, - &row, &column); - if (!res || event->button != 1) - return FALSE; - - work = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list, row)); - - if (GTK_CLIST (ctree)->selection_mode == GTK_SELECTION_MULTIPLE && - event->state & GDK_SHIFT_MASK) - { - if (GTK_CTREE_ROW (work)->row.state == GTK_STATE_SELECTED) - gtk_ctree_unselect_recursive (ctree, work); - else - gtk_ctree_select_recursive (ctree, work); - after_press (ctree, NULL); - gtk_signal_emit_stop_by_name (GTK_OBJECT (ctree), - "button_release_event"); - } - return FALSE; -} - void count_items (GtkCTree *ctree, GtkCTreeNode *list) { if (GTK_CTREE_ROW (list)->is_leaf) @@ -4616,11 +4548,6 @@ void change_row_height (GtkWidget *widget, GtkCList *clist) gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value); } -void toggle_reorderable (GtkWidget *widget, GtkCTree *ctree) -{ - gtk_ctree_set_reorderable (ctree, GTK_TOGGLE_BUTTON (widget)->active); -} - void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data) { GtkStyle *style = NULL; @@ -4953,16 +4880,11 @@ void create_ctree (void) gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED); line_style = GTK_CTREE_LINES_DOTTED; - gtk_ctree_set_reorderable (ctree, TRUE); gtk_signal_connect (GTK_OBJECT (ctree), "click_column", (GtkSignalFunc) ctree_click_column, NULL); - gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event", - GTK_SIGNAL_FUNC (button_press), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "button_press_event", GTK_SIGNAL_FUNC (after_press), NULL); - gtk_signal_connect (GTK_OBJECT (ctree), "button_release_event", - GTK_SIGNAL_FUNC (button_release), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "button_release_event", GTK_SIGNAL_FUNC (after_press), NULL); gtk_signal_connect_after (GTK_OBJECT (ctree), "tree_move", -- 2.43.2