aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/table/e-table.c198
-rw-r--r--widgets/table/e-table.h7
-rw-r--r--widgets/table/e-tree.c149
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;
}