From d554c5bbab77882ed04cade3a1aa2f1191832c6d Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Sun, 14 Jan 2001 02:05:21 +0000 Subject: Initial steps to support Drag 'n Drop in the tree view. svn path=/trunk/; revision=7484 --- shell/ChangeLog | 27 ++++ shell/e-storage-set-view.c | 329 +++++++++++++++++++++++++------------- shell/e-storage-set-view.h | 10 +- shell/evolution-shell-component.c | 2 +- shell/evolution-shell-component.h | 2 +- 5 files changed, 255 insertions(+), 115 deletions(-) diff --git a/shell/ChangeLog b/shell/ChangeLog index db830dbd71..e14b426b19 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,30 @@ +2001-01-13 Ettore Perazzoli + + * e-storage-set-view.h: New signal `dnd_action'. + + * e-storage-set-view.c: Renamed `drag_types' to + `source_drag_types' and `num_drag_types' to + `num_source_drag_types'. New variables `destination_drag_types' + and `num_destination_drag_types'. + (e_storage_set_view_construct): Set the ETree as a drag + destination. Allow both GDK_ACTION_MOVE and GDK_ACTION_COPY. + + * e-storage-set-view.c (table_drag_begin): Renamed from + `etable_drag_begin'. + (table_drag_data_get): Renamed from `etable_drag_data_get'. + Changed to be a method override instead of a signal handler. + (table_drag_motion): New; implementation for the + `ETable::table_drag_motion' method. Changed to be a method + override instead of a signal handler. + (table_drag_drop): New, implementation for `::table_drag_drop'. + (cursor_change): Renamed from `on_cursor_change'. + (e_storage_set_view_construct): Don't connect the signals here. + (class_init): Instead, override the methods here. Also, install + our override for `::table_drag_motion' and for + `::table_drag_drop'. + (right_click): Changed to be a method instead of a signal handler. + (cursor_change): Likewise. + 2001-01-13 Miguel de Icaza * e-shell.c (e_shell_construct): Unref our copy, and then destroy. diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c index 896c7715d1..9d703216ca 100644 --- a/shell/e-storage-set-view.c +++ b/shell/e-storage-set-view.c @@ -77,6 +77,7 @@ struct _EStorageSetViewPrivate { enum { FOLDER_SELECTED, STORAGE_SELECTED, + DND_ACTION, LAST_SIGNAL }; @@ -94,11 +95,17 @@ typedef enum _DndTargetType DndTargetType; #define URI_LIST_TYPE "text/uri-list" #define E_SHORTCUT_TYPE "E-SHORTCUT" -static GtkTargetEntry drag_types [] = { +static GtkTargetEntry source_drag_types [] = { { URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST }, { E_SHORTCUT_TYPE, 0, DND_TARGET_TYPE_E_SHORTCUT } }; -static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); +static const int num_source_drag_types = sizeof (source_drag_types) / sizeof (source_drag_types[0]); + +static GtkTargetEntry destination_drag_types [] = { + { URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST }, + { E_SHORTCUT_TYPE, 0, DND_TARGET_TYPE_E_SHORTCUT } +}; +static const int num_destination_drag_types = sizeof (destination_drag_types) / sizeof (destination_drag_types[0]); static GtkTargetList *target_list; @@ -212,9 +219,96 @@ get_pixbuf_for_folder (EStorageSetView *storage_set_view, return scaled_pixbuf; } + +/* Custom marshalling function. */ + +typedef void (* GtkSignal_NONE__ENUM_STRING_STRING_STRING) (GtkObject *object, + int, const char *, const char *, const char *); + +static void +marshal_NONE__ENUM_STRING_STRING_STRING (GtkObject *object, + GtkSignalFunc func, + void *func_data, + GtkArg *args) +{ + GtkSignal_NONE__ENUM_STRING_STRING_STRING rfunc; + + rfunc = (GtkSignal_NONE__ENUM_STRING_STRING_STRING) func; + (* rfunc) (object, + GTK_VALUE_ENUM (args[0]), + GTK_VALUE_STRING (args[1]), + GTK_VALUE_STRING (args[2]), + GTK_VALUE_STRING (args[3])); +} + + +/* DnD selection setup stuff. */ + +static void +set_uri_list_selection (EStorageSetView *storage_set_view, + GtkSelectionData *selection_data) +{ + EStorageSetViewPrivate *priv; + char *uri_list; + + priv = storage_set_view->priv; + + /* FIXME: Get `evolution:' from somewhere instead of hardcoding it here. */ + uri_list = g_strconcat ("evolution:", priv->selected_row_path, "\n", NULL); + gtk_selection_data_set (selection_data, selection_data->target, + 8, (guchar *) uri_list, strlen (uri_list)); + g_free (uri_list); +} + +static void +set_e_shortcut_selection (EStorageSetView *storage_set_view, + GtkSelectionData *selection_data) +{ + EStorageSetViewPrivate *priv; + int shortcut_len; + char *shortcut; + const char *trailing_slash; + const char *name; + + g_return_if_fail(storage_set_view != NULL); + + priv = storage_set_view->priv; + + trailing_slash = strrchr (priv->selected_row_path, '/'); + if (trailing_slash == NULL) + name = NULL; + else + name = trailing_slash + 1; + + /* FIXME: Get `evolution:' from somewhere instead of hardcoding it here. */ + + if (name != NULL) + shortcut_len = strlen (name); + else + shortcut_len = 0; + + shortcut_len ++; /* Separating zero. */ + + shortcut_len += strlen ("evolution:"); + shortcut_len += strlen (priv->selected_row_path); + shortcut_len ++; /* Trailing zero. */ + + shortcut = g_malloc (shortcut_len); + + if (name == NULL) + sprintf (shortcut, "%cevolution:%s", '\0', priv->selected_row_path); + else + sprintf (shortcut, "%s%cevolution:%s", name, '\0', priv->selected_row_path); + + gtk_selection_data_set (selection_data, selection_data->target, + 8, (guchar *) shortcut, shortcut_len); + + g_free (shortcut); +} + /* Folder context menu. */ -/* FIXME: This should be moved somewhere else, so that also the sortcut code +/* FIXME: This should be moved somewhere else, so that also the shortcut code can share it. */ #if 0 @@ -338,13 +432,15 @@ destroy (GtkObject *object) /* ETable methods */ static void -etable_drag_begin (EStorageSetView *storage_set_view, - int row, int col, - GdkDragContext *context) +table_drag_begin (ETable *etable, + int row, int col, + GdkDragContext *context) { + EStorageSetView *storage_set_view; EStorageSetViewPrivate *priv; ETreePath *node; + storage_set_view = E_STORAGE_SET_VIEW (etable); priv = storage_set_view->priv; node = e_tree_model_node_at_row (priv->etree_model, row); @@ -353,85 +449,111 @@ etable_drag_begin (EStorageSetView *storage_set_view, } static void -set_uri_list_selection (EStorageSetView *storage_set_view, - GtkSelectionData *selection_data) +table_drag_data_get (ETable *etable, + int drag_row, + int drag_col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint32 time) { - EStorageSetViewPrivate *priv; - char *uri_list; + EStorageSetView *storage_set_view; - priv = storage_set_view->priv; + storage_set_view = E_STORAGE_SET_VIEW (etable); - /* FIXME: Get `evolution:' from somewhere instead of hardcoding it here. */ - uri_list = g_strconcat ("evolution:", priv->selected_row_path, "\n", NULL); - gtk_selection_data_set (selection_data, selection_data->target, - 8, (guchar *) uri_list, strlen (uri_list)); - g_free (uri_list); + switch (info) { + case DND_TARGET_TYPE_URI_LIST: + set_uri_list_selection (storage_set_view, selection_data); + break; + case DND_TARGET_TYPE_E_SHORTCUT: + set_e_shortcut_selection (storage_set_view, selection_data); + break; + default: + g_assert_not_reached (); + } } -static void -set_e_shortcut_selection (EStorageSetView *storage_set_view, - GtkSelectionData *selection_data) +static gboolean +table_drag_motion (ETable *table, + int row, + int col, + GdkDragContext *context, + gint x, + gint y, + guint time) { - EStorageSetViewPrivate *priv; - int shortcut_len; - char *shortcut; - const char *trailing_slash; - const char *name; + gdk_drag_status (context, GDK_ACTION_MOVE, time); - g_return_if_fail(storage_set_view != NULL); + return TRUE; +} + +static gboolean +table_drag_drop (ETable *etable, + int row, + int col, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + EStorageSetView *storage_set_view; + EStorageSetViewPrivate *priv; + ETreePath *target_tree_path; + const char *target_path; + storage_set_view = E_STORAGE_SET_VIEW (etable); priv = storage_set_view->priv; - trailing_slash = strrchr (priv->selected_row_path, '/'); - if (trailing_slash == NULL) - name = NULL; - else - name = trailing_slash + 1; + target_tree_path = e_tree_model_node_at_row (priv->etree_model, row); + target_path = e_tree_model_node_get_data (priv->etree_model, target_tree_path); - /* FIXME: Get `evolution:' from somewhere instead of hardcoding it here. */ + gtk_signal_emit (GTK_OBJECT (etable), signals[DND_ACTION], + context->action, NULL, NULL, NULL); - if (name != NULL) - shortcut_len = strlen (name); - else - shortcut_len = 0; - - shortcut_len ++; /* Separating zero. */ - - shortcut_len += strlen ("evolution:"); - shortcut_len += strlen (priv->selected_row_path); - shortcut_len ++; /* Trailing zero. */ + return TRUE; +} - shortcut = g_malloc (shortcut_len); +static gboolean +right_click (ETable *etable, + int row, + int col, + GdkEvent *event) +{ + EStorageSetView *storage_set_view; + EStorageSetViewPrivate *priv; - if (name == NULL) - sprintf (shortcut, "%cevolution:%s", '\0', priv->selected_row_path); - else - sprintf (shortcut, "%s%cevolution:%s", name, '\0', priv->selected_row_path); + storage_set_view = E_STORAGE_SET_VIEW (etable); + priv = storage_set_view->priv; - gtk_selection_data_set (selection_data, selection_data->target, - 8, (guchar *) shortcut, shortcut_len); + popup_folder_menu (storage_set_view, (GdkEventButton *) event); - g_free (shortcut); + return TRUE; } static void -etable_drag_data_get (EStorageSetView *storage_set_view, - int drag_row, - int drag_col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint32 time) +cursor_change (ETable *table, + int row) { - switch (info) { - case DND_TARGET_TYPE_URI_LIST: - set_uri_list_selection (storage_set_view, selection_data); - break; - case DND_TARGET_TYPE_E_SHORTCUT: - set_e_shortcut_selection (storage_set_view, selection_data); - break; - default: - g_assert_not_reached (); + EStorageSetView *storage_set_view; + ETreePath *node; + EStorageSetViewPrivate *priv; + + storage_set_view = E_STORAGE_SET_VIEW (table); + + priv = storage_set_view->priv; + + node = e_tree_model_node_at_row (priv->etree_model, row); + + priv->selected_row_path = e_tree_model_node_get_data (priv->etree_model, node); + + if (e_tree_model_node_depth (priv->etree_model, node) >= 2) { + /* it was a folder */ + gtk_signal_emit (GTK_OBJECT (storage_set_view), signals[FOLDER_SELECTED], + priv->selected_row_path); + } else { + /* it was a storage */ + gtk_signal_emit (GTK_OBJECT (storage_set_view), signals[STORAGE_SELECTED], + priv->selected_row_path + 1); } } @@ -496,7 +618,9 @@ etree_value_to_string (ETableModel *etc, int col, const void *value, void *data) /* ETreeModel Methods */ static GdkPixbuf* -etree_icon_at (ETreeModel *etree, ETreePath *tree_path, void *model_data) +etree_icon_at (ETreeModel *etree, + ETreePath *tree_path, + void *model_data) { EStorageSetView *storage_set_view; EStorageSet *storage_set; @@ -720,12 +844,21 @@ static void class_init (EStorageSetViewClass *klass) { GtkObjectClass *object_class; + ETableClass *etable_class; parent_class = gtk_type_class (e_table_get_type ()); object_class = GTK_OBJECT_CLASS (klass); object_class->destroy = destroy; + etable_class = E_TABLE_CLASS (klass); + etable_class->right_click = right_click; + etable_class->cursor_change = cursor_change; + etable_class->table_drag_begin = table_drag_begin; + etable_class->table_drag_data_get = table_drag_data_get; + etable_class->table_drag_motion = table_drag_motion; + etable_class->table_drag_drop = table_drag_drop; + signals[FOLDER_SELECTED] = gtk_signal_new ("folder_selected", GTK_RUN_FIRST, @@ -744,11 +877,23 @@ class_init (EStorageSetViewClass *klass) GTK_TYPE_NONE, 1, GTK_TYPE_STRING); + signals[DND_ACTION] + = gtk_signal_new ("dnd_action", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EStorageSetViewClass, dnd_action), + marshal_NONE__ENUM_STRING_STRING_STRING, + GTK_TYPE_NONE, 4, + GTK_TYPE_ENUM, + GTK_TYPE_STRING, + GTK_TYPE_STRING, + GTK_TYPE_STRING); + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); /* Set up DND. */ - target_list = gtk_target_list_new (drag_types, num_drag_types); + target_list = gtk_target_list_new (source_drag_types, num_source_drag_types); g_assert (target_list != NULL); } @@ -905,40 +1050,6 @@ insert_storages (EStorageSetView *storage_set_view) e_free_object_list (storage_list); } -static void -right_click (EStorageSetView *storage_set_view, int row, int col, - GdkEventButton *event, gboolean *ret) -{ - EStorageSetViewPrivate *priv; - - priv = storage_set_view->priv; - - popup_folder_menu (storage_set_view, event); -} - -static void -on_cursor_change (EStorageSetView *storage_set_view, int row, gpointer user_data) -{ - ETreePath *node; - EStorageSetViewPrivate *priv; - - priv = storage_set_view->priv; - - node = e_tree_model_node_at_row (priv->etree_model, row); - - priv->selected_row_path = e_tree_model_node_get_data (priv->etree_model, node); - - if (e_tree_model_node_depth (priv->etree_model, node) >= 2) { - /* it was a folder */ - gtk_signal_emit (GTK_OBJECT (storage_set_view), signals[FOLDER_SELECTED], - priv->selected_row_path); - } else { - /* it was a storage */ - gtk_signal_emit (GTK_OBJECT (storage_set_view), signals[STORAGE_SELECTED], - priv->selected_row_path + 1); - } -} - void e_storage_set_view_construct (EStorageSetView *storage_set_view, EStorageSet *storage_set) @@ -980,7 +1091,12 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view, gtk_object_unref (GTK_OBJECT (extras)); e_table_drag_source_set (E_TABLE (storage_set_view), GDK_BUTTON1_MASK, - drag_types, num_drag_types, GDK_ACTION_MOVE); + source_drag_types, num_source_drag_types, + GDK_ACTION_MOVE | GDK_ACTION_COPY); + + e_table_drag_dest_set (E_TABLE (storage_set_view), GTK_DEST_DEFAULT_ALL, + source_drag_types, num_source_drag_types, + GDK_ACTION_MOVE | GDK_ACTION_COPY); gtk_object_ref (GTK_OBJECT (storage_set)); priv->storage_set = storage_set; @@ -1001,15 +1117,6 @@ e_storage_set_view_construct (EStorageSetView *storage_set_view, GTK_SIGNAL_FUNC (removed_folder_cb), storage_set_view, GTK_OBJECT (storage_set_view)); - gtk_signal_connect (GTK_OBJECT (storage_set_view), "right_click", - GTK_SIGNAL_FUNC (right_click), GTK_OBJECT(storage_set_view)); - gtk_signal_connect (GTK_OBJECT (storage_set_view), "cursor_change", - GTK_SIGNAL_FUNC (on_cursor_change), GTK_OBJECT(storage_set_view)); - gtk_signal_connect (GTK_OBJECT (storage_set_view), "table_drag_begin", - GTK_SIGNAL_FUNC (etable_drag_begin), GTK_OBJECT(storage_set_view)); - gtk_signal_connect (GTK_OBJECT (storage_set_view), "table_drag_data_get", - GTK_SIGNAL_FUNC (etable_drag_data_get), GTK_OBJECT(storage_set_view)); - insert_storages (storage_set_view); } diff --git a/shell/e-storage-set-view.h b/shell/e-storage-set-view.h index 2121e5ce96..92c9c84167 100644 --- a/shell/e-storage-set-view.h +++ b/shell/e-storage-set-view.h @@ -60,8 +60,14 @@ struct _EStorageSetViewClass { void (* folder_selected) (EStorageSetView *storage_set_view, const char *path); - void (* storage_selected) (EStorageSetView *storage_set_view, - const char *name); + void (* storage_selected) (EStorageSetView *storage_set_view, + const char *name); + + void (* dnd_action) (EStorageSetView *storage_set_view, + GdkDragAction action, + const char *source_data, + const char *source_data_type, + const char *target_path); }; diff --git a/shell/evolution-shell-component.c b/shell/evolution-shell-component.c index a426c60375..b35e85c7c7 100644 --- a/shell/evolution-shell-component.c +++ b/shell/evolution-shell-component.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* evolution-shell-component.c * - * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000, 2001 Ximian, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff --git a/shell/evolution-shell-component.h b/shell/evolution-shell-component.h index ffa3b44ff1..15dfff4fb0 100644 --- a/shell/evolution-shell-component.h +++ b/shell/evolution-shell-component.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* evolution-shell-component.h * - * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000, 2001 Ximian, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as -- cgit v1.2.3