From 0cb44895c50d6a0895aa5519c3d819698022e913 Mon Sep 17 00:00:00 2001 From: Christopher James Lahey Date: Tue, 7 Aug 2001 05:55:36 +0000 Subject: Added scrolling to access nodes that are scrolled off screen for drops. 2001-08-07 Christopher James Lahey * e-tree.c (scroll_timeout): Added scrolling to access nodes that are scrolled off screen for drops. Fixes Ximian bug #5645. * e-table.c, e-table.h (scroll_timeout): Added scrolling to access rows that are scrolled off screen for drops. This doesn't work for some reason, but I'm checking the code in. svn path=/trunk/; revision=11724 --- widgets/table/e-table.c | 198 +++++++++++++++++++++++++++++++++++++----------- widgets/table/e-table.h | 7 ++ widgets/table/e-tree.c | 149 +++++++++++++++++++++++++++++++----- 3 files changed, 290 insertions(+), 64 deletions(-) diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 166f864348..1bbd37f772 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -124,6 +124,9 @@ static gint e_table_drag_source_event_cb (GtkWidget *widget, static gint et_focus (GtkContainer *container, GtkDirectionType direction); +static void scroll_off (ETable *et); +static void scroll_on (ETable *et, gboolean down); + static void et_disconnect_model (ETable *et) { @@ -168,6 +171,8 @@ et_destroy (GtkObject *object) g_source_remove(et->reflow_idle_id); et->reflow_idle_id = 0; + scroll_off (et); + gtk_object_unref (GTK_OBJECT (et->model)); gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); @@ -203,38 +208,39 @@ e_table_init (GtkObject *object) GTK_WIDGET_SET_FLAGS (e_table, GTK_CAN_FOCUS); - gtk_table->homogeneous = FALSE; + gtk_table->homogeneous = FALSE; - e_table->sort_info = NULL; - e_table->group_info_change_id = 0; - e_table->reflow_idle_id = 0; + e_table->sort_info = NULL; + e_table->group_info_change_id = 0; + e_table->reflow_idle_id = 0; + e_table->scroll_idle_id = 0; - e_table->alternating_row_colors = 1; - e_table->horizontal_draw_grid = 1; - e_table->vertical_draw_grid = 1; - e_table->draw_focus = 1; - e_table->cursor_mode = E_CURSOR_SIMPLE; - e_table->length_threshold = 200; + e_table->alternating_row_colors = 1; + e_table->horizontal_draw_grid = 1; + e_table->vertical_draw_grid = 1; + e_table->draw_focus = 1; + e_table->cursor_mode = E_CURSOR_SIMPLE; + e_table->length_threshold = 200; - e_table->need_rebuild = 0; - e_table->rebuild_idle_id = 0; + e_table->need_rebuild = 0; + e_table->rebuild_idle_id = 0; - e_table->horizontal_scrolling = FALSE; + e_table->horizontal_scrolling = FALSE; - e_table->click_to_add_message = NULL; + e_table->click_to_add_message = NULL; - e_table->drag_get_data_row = -1; - e_table->drag_get_data_col = -1; - e_table->drop_row = -1; - e_table->drop_col = -1; - e_table->site = NULL; - e_table->drag_source_button_press_event_id = 0; + e_table->drag_get_data_row = -1; + e_table->drag_get_data_col = -1; + e_table->drop_row = -1; + e_table->drop_col = -1; + e_table->site = NULL; + e_table->drag_source_button_press_event_id = 0; e_table->drag_source_motion_notify_event_id = 0; - e_table->sorter = NULL; - e_table->selection = e_table_selection_model_new(); - e_table->cursor_loc = E_TABLE_CURSOR_LOC_NONE; - e_table->spec = NULL; + e_table->sorter = NULL; + e_table->selection = e_table_selection_model_new(); + e_table->cursor_loc = E_TABLE_CURSOR_LOC_NONE; + e_table->spec = NULL; } /* Grab_focus handler for the ETable */ @@ -1910,32 +1916,21 @@ et_drag_data_delete(GtkWidget *widget, context); } -static void -et_drag_leave(GtkWidget *widget, - GdkDragContext *context, - guint time, - ETable *et) -{ - gtk_signal_emit (GTK_OBJECT (et), - et_signals [TABLE_DRAG_LEAVE], - et->drop_row, - et->drop_col, - context, - time); - et->drop_row = -1; - et->drop_col = -1; -} - static gboolean -et_drag_motion(GtkWidget *widget, +do_drag_motion(ETable *et, GdkDragContext *context, gint x, gint y, - guint time, - ETable *et) + guint time) { gboolean ret_val; int row, col; + GtkWidget *widget; + + widget = GTK_WIDGET (et); + + x -= widget->allocation.x; + y -= widget->allocation.y; e_table_get_cell_at (et, x, y, &row, &col); @@ -1958,6 +1953,114 @@ et_drag_motion(GtkWidget *widget, y, time, &ret_val); + + return ret_val; +} + +static gboolean +scroll_timeout (gpointer data) +{ + ETable *et = data; + int dy; + GtkAdjustment *v; + double value; + + if (et->scroll_down) + dy = 20; + else + dy = -20; + + v = GTK_LAYOUT(et->table_canvas)->vadjustment; + + value = v->value; + + gtk_adjustment_set_value(v, CLAMP(v->value + dy, v->lower, v->upper - v->page_size)); + + if (v->value != value) + do_drag_motion(et, + et->last_drop_context, + et->last_drop_x, + et->last_drop_y, + et->last_drop_time); + + + return TRUE; +} + +static void +scroll_on (ETable *et, gboolean down) +{ + if (et->scroll_idle_id == 0 || down != et->scroll_down) { + if (et->scroll_idle_id != 0) + g_source_remove (et->scroll_idle_id); + et->scroll_down = down; + et->scroll_idle_id = g_timeout_add (100, scroll_timeout, et); + } +} + +static void +scroll_off (ETable *et) +{ + if (et->scroll_idle_id) { + g_source_remove (et->scroll_idle_id); + et->scroll_idle_id = 0; + } +} + +static void +et_drag_leave(GtkWidget *widget, + GdkDragContext *context, + guint time, + ETable *et) +{ + gtk_signal_emit (GTK_OBJECT (et), + et_signals [TABLE_DRAG_LEAVE], + et->drop_row, + et->drop_col, + context, + time); + et->drop_row = -1; + et->drop_col = -1; + + scroll_off (et); +} + +static gboolean +et_drag_motion(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + ETable *et) +{ + gboolean ret_val; + + g_print ("x=%d, y=%d\n", x, y); + + et->last_drop_x = x; + et->last_drop_y = y; + et->last_drop_time = time; + et->last_drop_context = context; + + ret_val = do_drag_motion (et, + context, + x, + y, + time); + + + x -= widget->allocation.x; + y -= widget->allocation.y; + + if (y < 20 || y > widget->allocation.height - 20) { + if (y < 20) + scroll_on (et, FALSE); + else + scroll_on (et, TRUE); + } else { + scroll_off (et); + } + return ret_val; } @@ -1972,6 +2075,9 @@ et_drag_drop(GtkWidget *widget, gboolean ret_val; int row, col; + x -= widget->allocation.x; + y -= widget->allocation.y; + e_table_get_cell_at (et, x, y, &row, &col); if (row != et->drop_row && col != et->drop_row) { @@ -2004,6 +2110,9 @@ et_drag_drop(GtkWidget *widget, &ret_val); et->drop_row = -1; et->drop_col = -1; + + scroll_off (et); + return ret_val; } @@ -2019,6 +2128,9 @@ et_drag_data_received(GtkWidget *widget, { int row, col; + x -= widget->allocation.x; + y -= widget->allocation.y; + e_table_get_cell_at (et, x, y, &row, &col); gtk_signal_emit (GTK_OBJECT (et), diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index 0cd63a58ab..f0656e7790 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -58,6 +58,7 @@ typedef struct { int group_info_change_id; int reflow_idle_id; + int scroll_idle_id; GnomeCanvas *header_canvas, *table_canvas; @@ -82,6 +83,8 @@ typedef struct { guint horizontal_scrolling : 1; guint is_grouped : 1; + + guint scroll_down : 1; char *click_to_add_message; GnomeCanvasItem *click_to_add; @@ -95,6 +98,10 @@ typedef struct { int drop_row; int drop_col; GnomeCanvasItem *drop_highlight; + int last_drop_x; + int last_drop_y; + int last_drop_time; + GdkDragContext *last_drop_context; int drag_row; int drag_col; diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c index 884ac8971b..ab1d214175 100644 --- a/widgets/table/e-tree.c +++ b/widgets/table/e-tree.c @@ -90,6 +90,7 @@ struct ETreePriv { ETableSpecification *spec; int reflow_idle_id; + int scroll_idle_id; int table_model_change_id; int table_row_change_id; @@ -117,6 +118,8 @@ struct ETreePriv { guint horizontal_scrolling : 1; + guint scroll_down : 1; + ECursorMode cursor_mode; int drop_row; @@ -124,6 +127,10 @@ struct ETreePriv { int drop_col; GnomeCanvasItem *drop_highlight; + int last_drop_x; + int last_drop_y; + int last_drop_time; + GdkDragContext *last_drop_context; int drag_row; ETreePath drag_path; @@ -184,6 +191,9 @@ static gint e_tree_drag_source_event_cb (GtkWidget *widget, static gint et_focus (GtkContainer *container, GtkDirectionType direction); +static void scroll_off (ETree *et); +static void scroll_on (ETree *et, gboolean down); + static void et_disconnect_from_etta (ETree *et) { @@ -219,6 +229,8 @@ et_destroy (GtkObject *object) g_source_remove(et->priv->reflow_idle_id); et->priv->reflow_idle_id = 0; + scroll_off (et); + et_disconnect_from_etta (et); gtk_object_unref (GTK_OBJECT (et->priv->etta)); @@ -270,6 +282,7 @@ e_tree_init (GtkObject *object) e_tree->priv->sort_info = NULL; e_tree->priv->sorter = NULL; e_tree->priv->reflow_idle_id = 0; + e_tree->priv->scroll_idle_id = 0; e_tree->priv->alternating_row_colors = 1; e_tree->priv->horizontal_draw_grid = 1; @@ -1955,36 +1968,22 @@ et_drag_data_delete(GtkWidget *widget, context); } -static void -et_drag_leave(GtkWidget *widget, - GdkDragContext *context, - guint time, - ETree *et) -{ - gtk_signal_emit (GTK_OBJECT (et), - et_signals [TREE_DRAG_LEAVE], - et->priv->drop_row, - et->priv->drop_path, - et->priv->drop_col, - context, - time); - et->priv->drop_row = -1; - et->priv->drop_col = -1; -} - static gboolean -et_drag_motion(GtkWidget *widget, +do_drag_motion(ETree *et, GdkDragContext *context, gint x, gint y, - guint time, - ETree *et) + guint time) { gboolean ret_val; int row, col; ETreePath path; - y -= widget->allocation.y; + GtkWidget *widget; + + widget = GTK_WIDGET (et); + x -= widget->allocation.x; + y -= widget->allocation.y; e_tree_get_cell_at (et, x, y, @@ -2016,6 +2015,112 @@ et_drag_motion(GtkWidget *widget, y, time, &ret_val); + + return ret_val; +} + +static gboolean +scroll_timeout (gpointer data) +{ + ETree *et = data; + int dy; + GtkAdjustment *v; + double value; + + if (et->priv->scroll_down) + dy = 20; + else + dy = -20; + + v = GTK_LAYOUT(et->priv->table_canvas)->vadjustment; + + value = v->value; + + gtk_adjustment_set_value(v, CLAMP(v->value + dy, v->lower, v->upper - v->page_size)); + + if (v->value != value) + do_drag_motion(et, + et->priv->last_drop_context, + et->priv->last_drop_x, + et->priv->last_drop_y, + et->priv->last_drop_time); + + + return TRUE; +} + +static void +scroll_on (ETree *et, gboolean down) +{ + if (et->priv->scroll_idle_id == 0 || down != et->priv->scroll_down) { + if (et->priv->scroll_idle_id != 0) + g_source_remove (et->priv->scroll_idle_id); + et->priv->scroll_down = down; + et->priv->scroll_idle_id = g_timeout_add (100, scroll_timeout, et); + } +} + +static void +scroll_off (ETree *et) +{ + if (et->priv->scroll_idle_id) { + g_source_remove (et->priv->scroll_idle_id); + et->priv->scroll_idle_id = 0; + } +} + +static void +et_drag_leave(GtkWidget *widget, + GdkDragContext *context, + guint time, + ETree *et) +{ + gtk_signal_emit (GTK_OBJECT (et), + et_signals [TREE_DRAG_LEAVE], + et->priv->drop_row, + et->priv->drop_path, + et->priv->drop_col, + context, + time); + et->priv->drop_row = -1; + et->priv->drop_col = -1; + + scroll_off (et); +} + +static gboolean +et_drag_motion(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + ETree *et) +{ + int ret_val; + + et->priv->last_drop_x = x; + et->priv->last_drop_y = y; + et->priv->last_drop_time = time; + et->priv->last_drop_context = context; + + ret_val = do_drag_motion (et, + context, + x, + y, + time); + + x -= widget->allocation.x; + y -= widget->allocation.y; + + if (y < 20 || y > widget->allocation.height - 20) { + if (y < 20) + scroll_on (et, FALSE); + else + scroll_on (et, TRUE); + } else { + scroll_off (et); + } + return ret_val; } @@ -2075,6 +2180,8 @@ et_drag_drop(GtkWidget *widget, et->priv->drop_row = -1; et->priv->drop_path = NULL; et->priv->drop_col = -1; + + scroll_off (et); return ret_val; } -- cgit v1.2.3