ClutterDragAction: allow constraining the movement of the dragged actor

Allow setting a ClutterRect on the drag action and force the
dragged actor's position to be always within that rectangle (relative
to the actor's parent).

https://bugzilla.gnome.org/show_bug.cgi?id=681168
This commit is contained in:
Giovanni Campagna 2012-08-04 00:13:04 +02:00
parent b62797d23a
commit f99d48a0c6
4 changed files with 130 additions and 1 deletions

View File

@ -91,6 +91,7 @@ struct _ClutterDragActionPrivate
gint y_drag_threshold; gint y_drag_threshold;
ClutterActor *drag_handle; ClutterActor *drag_handle;
ClutterDragAxis drag_axis; ClutterDragAxis drag_axis;
ClutterRect drag_area;
ClutterInputDevice *device; ClutterInputDevice *device;
ClutterEventSequence *sequence; ClutterEventSequence *sequence;
@ -113,6 +114,7 @@ struct _ClutterDragActionPrivate
guint emit_delayed_press : 1; guint emit_delayed_press : 1;
guint in_drag : 1; guint in_drag : 1;
guint motion_events_enabled : 1; guint motion_events_enabled : 1;
guint drag_area_set : 1;
}; };
enum enum
@ -123,6 +125,8 @@ enum
PROP_Y_DRAG_THRESHOLD, PROP_Y_DRAG_THRESHOLD,
PROP_DRAG_HANDLE, PROP_DRAG_HANDLE,
PROP_DRAG_AXIS, PROP_DRAG_AXIS,
PROP_DRAG_AREA,
PROP_DRAG_AREA_SET,
PROP_LAST PROP_LAST
}; };
@ -520,13 +524,27 @@ clutter_drag_action_real_drag_motion (ClutterDragAction *action,
gfloat delta_y) gfloat delta_y)
{ {
ClutterActor *drag_handle; ClutterActor *drag_handle;
gfloat x, y;
if (action->priv->drag_handle != NULL) if (action->priv->drag_handle != NULL)
drag_handle = action->priv->drag_handle; drag_handle = action->priv->drag_handle;
else else
drag_handle = actor; drag_handle = actor;
clutter_actor_move_by (drag_handle, delta_x, delta_y); clutter_actor_get_position (drag_handle, &x, &y);
x += delta_x;
y += delta_y;
if (action->priv->drag_area_set)
{
ClutterRect *drag_area = &action->priv->drag_area;
x = CLAMP (x, drag_area->origin.x, drag_area->origin.x + drag_area->size.width);
y = CLAMP (y, drag_area->origin.y, drag_area->origin.y + drag_area->size.height);
}
clutter_actor_set_position (drag_handle, x, y);
} }
static void static void
@ -560,6 +578,10 @@ clutter_drag_action_set_property (GObject *gobject,
clutter_drag_action_set_drag_axis (action, g_value_get_enum (value)); clutter_drag_action_set_drag_axis (action, g_value_get_enum (value));
break; break;
case PROP_DRAG_AREA:
clutter_drag_action_set_drag_area (action, g_value_get_boxed (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
} }
@ -601,6 +623,14 @@ clutter_drag_action_get_property (GObject *gobject,
g_value_set_enum (value, priv->drag_axis); g_value_set_enum (value, priv->drag_axis);
break; break;
case PROP_DRAG_AREA:
g_value_set_boxed (value, &priv->drag_area);
break;
case PROP_DRAG_AREA_SET:
g_value_set_boolean (value, priv->drag_area_set);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
} }
@ -636,6 +666,7 @@ clutter_drag_action_dispose (GObject *gobject)
} }
clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL); clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL);
clutter_drag_action_set_drag_area (CLUTTER_DRAG_ACTION (gobject), NULL);
G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject); G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject);
} }
@ -745,6 +776,37 @@ clutter_drag_action_class_init (ClutterDragActionClass *klass)
CLUTTER_DRAG_AXIS_NONE, CLUTTER_DRAG_AXIS_NONE,
CLUTTER_PARAM_READWRITE); CLUTTER_PARAM_READWRITE);
/**
* ClutterDragAction:drag-area:
*
* Constains the dragging action (or in particular, the resulting
* actor position) to the specified #ClutterRect, in parent's
* coordinates.
*
* Since: 1.12
*/
drag_props[PROP_DRAG_AREA] =
g_param_spec_boxed ("drag-area",
P_("Drag Area"),
P_("Constrains the dragging to a rectangle"),
CLUTTER_TYPE_RECT,
CLUTTER_PARAM_READWRITE);
/**
* ClutterDragAction:drag-area-set:
*
* Whether the #ClutterDragAction:drag-area property has been set.
*
* Since: 1.12
*/
drag_props[PROP_DRAG_AREA_SET] =
g_param_spec_boolean ("drag-area-set",
P_("Drag Area Set"),
P_("Whether the drag area is set"),
FALSE,
CLUTTER_PARAM_READABLE);
gobject_class->set_property = clutter_drag_action_set_property; gobject_class->set_property = clutter_drag_action_set_property;
gobject_class->get_property = clutter_drag_action_get_property; gobject_class->get_property = clutter_drag_action_get_property;
gobject_class->dispose = clutter_drag_action_dispose; gobject_class->dispose = clutter_drag_action_dispose;
@ -1168,3 +1230,58 @@ clutter_drag_action_get_motion_coords (ClutterDragAction *action,
if (motion_y) if (motion_y)
*motion_y = action->priv->last_motion_y; *motion_y = action->priv->last_motion_y;
} }
/**
* clutter_drag_action_get_drag_area:
* @action: a #ClutterDragAction
* @drag_area: (out caller-allocates): a #ClutterRect to be filled
*
* Retrieves the "drag area" associated with @action, that
* is a #ClutterRect that constrains the actor movements,
* in parents coordinates.
*
* Returns: %TRUE if the actor is actually constrained (and thus
* @drag_area is valid), %FALSE otherwise
*/
gboolean
clutter_drag_action_get_drag_area (ClutterDragAction *action,
ClutterRect *drag_area)
{
g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), FALSE);
if (drag_area != NULL)
*drag_area = action->priv->drag_area;
return action->priv->drag_area_set;
}
/**
* clutter_drag_action_set_drag_area:
* @action: a #ClutterDragAction
* @drag_area: (allow-none): a #ClutterRect
*
* Sets @drag_area to constrain the dragging of the actor associated
* with @action, so that it position is always within @drag_area, expressed
* in parent's coordinates.
* If @drag_area is %NULL, the actor is not constrained.
*/
void
clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area)
{
ClutterDragActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action));
priv = action->priv;
if (drag_area != NULL)
{
priv->drag_area = *drag_area;
priv->drag_area_set = TRUE;
}
else
priv->drag_area_set = FALSE;
g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_AREA_SET]);
g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_AREA]);
}

View File

@ -129,6 +129,14 @@ void clutter_drag_action_get_motion_coords (ClutterDragAction *actio
gfloat *motion_x, gfloat *motion_x,
gfloat *motion_y); gfloat *motion_y);
CLUTTER_AVAILABLE_IN_1_12
gboolean clutter_drag_action_get_drag_area (ClutterDragAction *action,
ClutterRect *drag_area);
CLUTTER_AVAILABLE_IN_1_12
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_DRAG_ACTION_H__ */ #endif /* __CLUTTER_DRAG_ACTION_H__ */

View File

@ -625,6 +625,7 @@ clutter_device_manager_get_type
clutter_device_manager_list_devices clutter_device_manager_list_devices
clutter_device_manager_peek_devices clutter_device_manager_peek_devices
clutter_do_event clutter_do_event
clutter_drag_action_get_drag_area
clutter_drag_action_get_drag_axis clutter_drag_action_get_drag_axis
clutter_drag_action_get_drag_handle clutter_drag_action_get_drag_handle
clutter_drag_action_get_drag_threshold clutter_drag_action_get_drag_threshold
@ -632,6 +633,7 @@ clutter_drag_action_get_motion_coords
clutter_drag_action_get_press_coords clutter_drag_action_get_press_coords
clutter_drag_action_get_type clutter_drag_action_get_type
clutter_drag_action_new clutter_drag_action_new
clutter_drag_action_set_drag_area
clutter_drag_action_set_drag_axis clutter_drag_action_set_drag_axis
clutter_drag_action_set_drag_handle clutter_drag_action_set_drag_handle
clutter_drag_action_set_drag_threshold clutter_drag_action_set_drag_threshold

View File

@ -2570,6 +2570,8 @@ clutter_drag_action_get_drag_handle
ClutterDragAxis ClutterDragAxis
clutter_drag_action_set_drag_axis clutter_drag_action_set_drag_axis
clutter_drag_action_get_drag_axis clutter_drag_action_get_drag_axis
clutter_drag_action_set_drag_area
clutter_drag_action_get_drag_area
<SUBSECTION> <SUBSECTION>
clutter_drag_action_get_press_coords clutter_drag_action_get_press_coords