/* Drag handle has changed so unset styles on old handle and set style on new one */ static void _xfdashboard_drag_action_on_drag_handle_changed(XfdashboardDragAction *self, GParamSpec *inSpec, gpointer inUserData) { XfdashboardDragActionPrivate *priv; gchar *styleClass; g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(self)); priv=self->priv; /* Unset styles on current drag handle */ if(priv->dragHandle && XFDASHBOARD_IS_ACTOR(priv->dragHandle)) { /* Unset style */ if(priv->source) { styleClass=g_strdup_printf("drag-source-%s", G_OBJECT_TYPE_NAME(priv->source)); xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); } styleClass=g_strdup_printf("drag-actor-%s", G_OBJECT_TYPE_NAME(priv->actor)); xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->dragHandle), "drag-handle"); /* Forget drag handle */ priv->dragHandle=NULL; } /* Remember new drag handle and set styles */ priv->dragHandle=clutter_drag_action_get_drag_handle(CLUTTER_DRAG_ACTION(self)); if(priv->dragHandle && XFDASHBOARD_IS_ACTOR(priv->dragHandle)) { /* Set style */ if(priv->source) { styleClass=g_strdup_printf("drag-source-%s", G_OBJECT_TYPE_NAME(priv->source)); xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); } styleClass=g_strdup_printf("drag-actor-%s", G_OBJECT_TYPE_NAME(priv->actor)); xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->dragHandle), "drag-handle"); } }
static void on_drag_end (ClutterDragAction *action, ClutterActor *actor, gfloat event_x, gfloat event_y, ClutterModifierType modifiers) { ClutterActor *handle = clutter_drag_action_get_drag_handle (action); g_print ("Drag ended at: %.0f, %.0f\n", event_x, event_y); clutter_actor_save_easing_state (actor); clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); clutter_actor_set_opacity (actor, 255); clutter_actor_restore_easing_state (actor); clutter_actor_save_easing_state (handle); if (!drop_successful) { ClutterActor *parent = clutter_actor_get_parent (actor); gfloat x_pos, y_pos; clutter_actor_save_easing_state (parent); clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR); clutter_actor_set_opacity (parent, 255); clutter_actor_restore_easing_state (parent); clutter_actor_get_transformed_position (actor, &x_pos, &y_pos); clutter_actor_set_easing_mode (handle, CLUTTER_EASE_OUT_BOUNCE); clutter_actor_set_position (handle, x_pos, y_pos); clutter_actor_set_opacity (handle, 0); clutter_actor_restore_easing_state (handle); } else { clutter_actor_set_easing_mode (handle, CLUTTER_LINEAR); clutter_actor_set_opacity (handle, 0); } clutter_actor_restore_easing_state (handle); g_signal_connect (handle, "transitions-completed", G_CALLBACK (clutter_actor_destroy), NULL); }
static void on_drag_end (ClutterDragAction *action, ClutterActor *actor, gfloat event_x, gfloat event_y, ClutterModifierType modifiers) { ClutterActor *drag_handle; drag_handle = clutter_drag_action_get_drag_handle (action); if (actor != drag_handle) { gfloat real_x, real_y; ClutterActor *parent; /* if we are dragging a copy we can destroy the copy now * and animate the real actor to the drop coordinates, * transformed in the parent's coordinate space */ clutter_actor_animate (drag_handle, CLUTTER_LINEAR, 150, "opacity", 0, "signal-swapped-after::completed", G_CALLBACK (clutter_actor_destroy), drag_handle, NULL); parent = clutter_actor_get_parent (actor); clutter_actor_transform_stage_point (parent, event_x, event_y, &real_x, &real_y); clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 150, "@effects.disable.factor", 0.0, "x", real_x, "y", real_y, NULL); } else clutter_actor_animate (actor, CLUTTER_LINEAR, 150, "@effects.disable.factor", 0.0, NULL); }
/* Dragging of actor begins */ static void _xfdashboard_drag_action_drag_begin(ClutterDragAction *inAction, ClutterActor *inActor, gfloat inStageX, gfloat inStageY, ClutterModifierType inModifiers) { XfdashboardDragAction *self; XfdashboardDragActionPrivate *priv; ClutterDragActionClass *dragActionClass; GSList *list; g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inAction)); self=XFDASHBOARD_DRAG_ACTION(inAction); priv=self->priv; dragActionClass=CLUTTER_DRAG_ACTION_CLASS(xfdashboard_drag_action_parent_class); /* Call parent's class method */ if(dragActionClass->drag_begin) dragActionClass->drag_begin(inAction, inActor, inStageX, inStageY, inModifiers); /* Remember dragged actor while dragging and listen to possible 'destroy' signal emissions */ priv->actor=inActor; priv->actorDestroySignalID=g_signal_connect_swapped(priv->actor, "destroy", G_CALLBACK(_xfdashboard_drag_action_on_dragged_actor_destroyed), self); /* Get list of drop targets. It is a new list with all current * drop targets already reffed. So the drop targets will be valid * while dragging */ priv->targets=xfdashboard_drop_action_get_targets(); /* Emit "begin" signal on all drop targets to determine if they * can handle dragged actor and to prepare them for dragging. * All targets returning TRUE (and therefore telling us they * can handle dragged actor and are prepared for drag'n'drop) * will be sorted. */ list=priv->targets; while(list) { XfdashboardDropAction *dropTarget=XFDASHBOARD_DROP_ACTION(list->data); gboolean canHandle=FALSE; g_signal_emit_by_name(dropTarget, "begin", self, &canHandle); if(!canHandle) { GSList *next; /* Drop target cannot handle dragged actor so unref it and * remove it from list of drop targets */ next=g_slist_next(list); priv->targets=g_slist_remove_link(priv->targets, list); g_object_unref(list->data); g_slist_free_1(list); list=next; } else list=g_slist_next(list); } _xfdashboard_drag_action_sort_targets(self); /* We should listen to allocation changes for each actor which * is an active drop target. */ for(list=priv->targets; list; list=g_slist_next(list)) { XfdashboardDropAction *dropTarget=XFDASHBOARD_DROP_ACTION(list->data); ClutterActorMeta *actorMeta=CLUTTER_ACTOR_META(dropTarget); ClutterActor *actor=clutter_actor_meta_get_actor(actorMeta); g_signal_connect_swapped(actor, "allocation-changed", G_CALLBACK(_xfdashboard_drag_on_drop_target_allocation_changed), self); } /* Setup for dragging */ priv->dragCancelled=FALSE; priv->lastDropTarget=NULL; priv->lastMotionActors=NULL; /* Set styles */ if(priv->source && XFDASHBOARD_IS_ACTOR(priv->source)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->source), "drag-source"); } if(XFDASHBOARD_IS_ACTOR(priv->actor)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "dragged"); } priv->dragHandle=clutter_drag_action_get_drag_handle(CLUTTER_DRAG_ACTION(self)); if(priv->dragHandle && XFDASHBOARD_IS_ACTOR(priv->dragHandle)) { gchar *styleClass; if(priv->source) { styleClass=g_strdup_printf("drag-source-%s", G_OBJECT_TYPE_NAME(priv->source)); xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); } styleClass=g_strdup_printf("drag-actor-%s", G_OBJECT_TYPE_NAME(priv->actor)); xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass); g_free(styleClass); xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->dragHandle), "drag-handle"); /* Get notified if drag handle changes */ priv->dragHandleChangedID=g_signal_connect(self, "notify::drag-handle", G_CALLBACK(_xfdashboard_drag_action_on_drag_handle_changed), NULL); } }