diff options
-rw-r--r-- | shell/ChangeLog | 32 | ||||
-rw-r--r-- | shell/Evolution-ShellComponentDnd.idl | 3 | ||||
-rw-r--r-- | shell/e-storage-set-view.c | 148 |
3 files changed, 165 insertions, 18 deletions
diff --git a/shell/ChangeLog b/shell/ChangeLog index d27f938e69..a0c2bbd4bf 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,25 @@ +2001-03-21 Ettore Perazzoli <ettore@ximian.com> + + * e-storage-set-view.c (tree_drag_data_get): Get the target type + from the atom, and pass it through the `SourceFolder::getData' + invocation. Also, signal an error by passing `-1' as the length + value to `gtk_selection_data_set()'. + (find_matching_target_for_drag_context): New helper function. + (tree_drag_motion): Use it to figure out a suitable type for the + drop action, and pass it to the `DestinationFolder::handleMotion' + method. + + * e-storage-set-view.c (get_component_at_node): New helper + function. + (table_drag_begin): Use it. + (convert_corba_drag_action_to_gdk): New helper function. + (table_drag_motion): Use the `DestinationFolder::handleMotion' + method to handle the "drag_motion" signal. + + * Evolution-ShellComponentDnd.idl: Change the signature for the + `handleMotion' method so that it only has @suggested_action + parameter. + 2001-03-20 JP Rosevear <jpr@ximian.com> * importer/Makefile.am: make sure intelligent.h gets disted @@ -6,29 +28,27 @@ * Merged e-tree-rework-branch: -2001-03-19 Christopher James Lahey <clahey@ximian.com> + 2001-03-19 Christopher James Lahey <clahey@ximian.com> * e-storage-set-view.c (etree_get_save_id): Made "root" detection deal properly with removed nodes. -2001-03-18 Christopher James Lahey <clahey@ximian.com> + 2001-03-18 Christopher James Lahey <clahey@ximian.com> * e-shell-view.c (e_shell_view_save_settings): Added some unused code to implement saving of the expanded state. * e-storage-set-view.c: Added has_save_id and get_save_id methods. -2001-03-13 Christopher James Lahey <clahey@ximian.com> + 2001-03-13 Christopher James Lahey <clahey@ximian.com> * e-storage-set-view.c (ETREE_SPEC): Set draw-grid here to false. -2001-03-09 Christopher James Lahey <clahey@ximian.com> + 2001-03-09 Christopher James Lahey <clahey@ximian.com> * e-storage-set-view.c, e-storage-set-view.h: Chaned this to use ETree instead of ETable. -End of branch - 2001-03-19 Ettore Perazzoli <ettore@ximian.com> * evolution-shell-component-client.c: New members diff --git a/shell/Evolution-ShellComponentDnd.idl b/shell/Evolution-ShellComponentDnd.idl index f5fa3d0c0e..7eaea434fc 100644 --- a/shell/Evolution-ShellComponentDnd.idl +++ b/shell/Evolution-ShellComponentDnd.idl @@ -79,8 +79,7 @@ module ShellComponentDnd { @default_action and @non_default_action we want to be performed when the drop happens. */ boolean handleMotion (in Context destination_context, - out Action default_action, - out Action non_default_action); + out Action suggested_action); /* Data is dropped. We are given the data for the dropped object, and we are supposed to perform the operation diff --git a/shell/e-storage-set-view.c b/shell/e-storage-set-view.c index 038e75c73a..f99c27647b 100644 --- a/shell/e-storage-set-view.c +++ b/shell/e-storage-set-view.c @@ -241,7 +241,7 @@ get_pixbuf_for_folder (EStorageSetView *storage_set_view, GDK_INTERP_HYPER); } - g_hash_table_insert (priv->type_name_to_pixbuf, g_strdup(type_name), scaled_pixbuf); + g_hash_table_insert (priv->type_name_to_pixbuf, g_strdup (type_name), scaled_pixbuf); } return scaled_pixbuf; @@ -269,7 +269,31 @@ get_folder_at_node (EStorageSetView *storage_set_view, return folder; } -static GNOME_Evolution_ShellComponentDnd_Action +static EvolutionShellComponentClient * +get_component_at_node (EStorageSetView *storage_set_view, + ETreePath path) +{ + EStorageSetViewPrivate *priv; + EvolutionShellComponentClient *component_client; + EFolderTypeRegistry *folder_type_registry; + EFolder *folder; + + priv = storage_set_view->priv; + + folder = get_folder_at_node (storage_set_view, path); + if (folder == NULL) + return NULL; + + folder_type_registry = e_storage_set_get_folder_type_registry (priv->storage_set); + g_assert (folder_type_registry != NULL); + + component_client = e_folder_type_registry_get_handler_for_type (folder_type_registry, + e_folder_get_type_string (folder)); + + return component_client; +} + +static GNOME_Evolution_ShellComponentDnd_ActionSet convert_gdk_drag_action_to_corba (GdkDragAction action) { GNOME_Evolution_ShellComponentDnd_Action retval; @@ -288,6 +312,72 @@ convert_gdk_drag_action_to_corba (GdkDragAction action) return retval; } +static GdkDragAction +convert_corba_drag_action_to_gdk (GNOME_Evolution_ShellComponentDnd_ActionSet action) +{ + GdkDragAction retval; + + retval = GDK_ACTION_DEFAULT; + + if (action & GNOME_Evolution_ShellComponentDnd_ACTION_COPY) + retval |= GDK_ACTION_COPY; + if (action & GNOME_Evolution_ShellComponentDnd_ACTION_MOVE) + retval |= GDK_ACTION_MOVE; + if (action & GNOME_Evolution_ShellComponentDnd_ACTION_LINK) + retval |= GDK_ACTION_LINK; + if (action & GNOME_Evolution_ShellComponentDnd_ACTION_ASK) + retval |= GDK_ACTION_ASK; + + return retval; +} + +static const char * +find_matching_target_for_drag_context (EStorageSetView *storage_set_view, + ETreePath path, + GdkDragContext *drag_context) +{ + EStorageSetViewPrivate *priv; + EFolderTypeRegistry *folder_type_registry; + EFolder *folder; + GList *accepted_types; + GList *p, *q; + + priv = storage_set_view->priv; + folder_type_registry = e_storage_set_get_folder_type_registry (priv->storage_set); + + folder = get_folder_at_node (storage_set_view, path); + if (folder == NULL) + return NULL; + + accepted_types = e_folder_type_registry_get_accepted_dnd_types_for_type (folder_type_registry, + e_folder_get_type_string (folder)); + + /* FIXME? We might make this more efficient. Currently it takes `n * + m' string compares, where `n' is the number of targets in the + @drag_context, and `m' is the number of supported types in + @folder. */ + + for (p = drag_context->targets; p != NULL; p = p->next) { + char *possible_type; + + possible_type = gdk_atom_name ((GdkAtom) p->data); + + for (q = accepted_types; q != NULL; q = q->next) { + const char *accepted_type; + + accepted_type = (const char *) q->data; + if (strcmp (possible_type, accepted_type) == 0) { + g_free (possible_type); + return accepted_type; + } + } + + g_free (possible_type); + } + + return NULL; +} + /* Custom marshalling function. */ @@ -709,7 +799,6 @@ tree_drag_begin (ETree *etree, EStorageSetView *storage_set_view; EStorageSetViewPrivate *priv; EFolder *folder; - EFolderTypeRegistry *folder_type_registry; EvolutionShellComponentClient *component_client; GNOME_Evolution_ShellComponent corba_component; GNOME_Evolution_ShellComponentDnd_ActionSet possible_actions; @@ -724,9 +813,7 @@ tree_drag_begin (ETree *etree, g_assert (priv->drag_corba_source_interface == CORBA_OBJECT_NIL); folder = get_folder_at_node (storage_set_view, path); - folder_type_registry = e_storage_set_get_folder_type_registry (priv->storage_set); - component_client = e_folder_type_registry_get_handler_for_type (folder_type_registry, - e_folder_get_type_string (folder)); + component_client = get_component_at_node (storage_set_view, path); g_assert (component_client != NULL); @@ -824,6 +911,7 @@ tree_drag_data_get (ETree *etree, EStorageSetView *storage_set_view; EStorageSetViewPrivate *priv; CORBA_Environment ev; + char *target_type; storage_set_view = E_STORAGE_SET_VIEW (etree); priv = storage_set_view->priv; @@ -838,17 +926,19 @@ tree_drag_data_get (ETree *etree, if (priv->drag_corba_source_interface == CORBA_OBJECT_NIL) return; + target_type = gdk_atom_name ((GdkAtom) context->targets->data); + CORBA_exception_init (&ev); GNOME_Evolution_ShellComponentDnd_SourceFolder_getData (priv->drag_corba_source_interface, priv->drag_corba_source_context, convert_gdk_drag_action_to_corba (context->action), - "", /* FIXME type! */ + target_type, & priv->drag_corba_data, &ev); if (ev._major != CORBA_NO_EXCEPTION) - gtk_selection_data_set (selection_data, selection_data->target, 8, "", 1); + gtk_selection_data_set (selection_data, selection_data->target, 8, "", -1); else gtk_selection_data_set (selection_data, priv->drag_corba_data->target, @@ -856,6 +946,8 @@ tree_drag_data_get (ETree *etree, priv->drag_corba_data->bytes._buffer, priv->drag_corba_data->bytes._length); + g_free (target_type); + CORBA_exception_free (&ev); } @@ -899,11 +991,47 @@ tree_drag_motion (ETree *tree, { EStorageSetView *storage_set_view; EStorageSetViewPrivate *priv; + EvolutionShellComponentClient *component_client; + GNOME_Evolution_ShellComponentDnd_DestinationFolder destination_folder_interface; + GNOME_Evolution_ShellComponentDnd_Action suggested_action; + GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context corba_context; + CORBA_boolean can_handle; + CORBA_Environment ev; + const char *dnd_type; storage_set_view = E_STORAGE_SET_VIEW (tree); priv = storage_set_view->priv; - gdk_drag_status (context, GDK_ACTION_MOVE, time); + component_client = get_component_at_node (storage_set_view, path); + if (component_client == NULL) + return FALSE; + + destination_folder_interface = evolution_shell_component_client_get_dnd_source_interface (component_client); + if (destination_folder_interface == NULL) + return FALSE; + + dnd_type = find_matching_target_for_drag_context (storage_set_view, path, context); + if (dnd_type == NULL) + return FALSE; + + CORBA_exception_init (&ev); + + corba_context.dnd_type = (char *) dnd_type; /* (Safe cast, as we don't actually free the corba_context.) */ + corba_context.possible_actions = convert_gdk_drag_action_to_corba (context->actions); + corba_context.suggested_action = convert_gdk_drag_action_to_corba (context->suggested_action); + + can_handle = GNOME_Evolution_ShellComponentDnd_DestinationFolder_handleMotion (destination_folder_interface, + &corba_context, + &suggested_action, + &ev); + if (ev._major != CORBA_NO_EXCEPTION || ! can_handle) { + CORBA_exception_free (&ev); + return FALSE; + } + + CORBA_exception_free (&ev); + + gdk_drag_status (context, convert_corba_drag_action_to_gdk (suggested_action), time); return TRUE; } @@ -980,7 +1108,7 @@ cursor_activated (ETree *tree, priv = storage_set_view->priv; - priv->selected_row_path = e_tree_memory_node_get_data (E_TREE_MEMORY(priv->etree_model), path); + priv->selected_row_path = e_tree_memory_node_get_data (E_TREE_MEMORY (priv->etree_model), path); if (e_tree_model_node_depth (priv->etree_model, path) >= 2) { /* it was a folder */ |