Flip: Fix confusion with hitsize and direction

Elm Flip has some confusing API (and documentation as well) regarding
flip directions and hitsize. Basically, it works just as expected
when everything is set to 1 (all hitsizes are 100% and all directions
are enabled), like in the elm example file :)

BUT, it's not actually possible to restrict the hitsize for one
direction.

Example: You want to flip to left only.
Set direction enabled LEFT.
Then, you must set the hitsize for... RIGHT because that's where the
finger interaction will start from (right to left!). BUT since
RIGHT interaction is not enabled, the histize parameter on RIGHT
will have NO effect on the flip.

Here's what this commit fixes:
- Clear up a bit of the confusion between direction and hit area,
through documentation
- Separate hit area position and direction (bugfix)
- Allow for negative hitsize values to DISABLE a specific area
(define previously undefined behaviour)

So, it will be possible for example:
- Enable left/right interactions
- Only on the top 10% of the widget

NOTE: This breaks behaviour! API/ABI are not quite broken but
undefined behaviour just got defined and fixed.
This commit is contained in:
Jean-Philippe Andre 2013-12-11 11:37:04 +09:00
parent 4c9dcb75e5
commit 4cf069ede9
2 changed files with 61 additions and 51 deletions

View File

@ -1689,7 +1689,6 @@ _move_cb(void *data,
if (((dx * dx) + (dy * dy)) >
(_elm_config->finger_size * _elm_config->finger_size / 4))
{
sd->dir = ELM_FLIP_DIRECTION_LEFT;
if ((sd->x > (w / 2)) &&
(dx < 0) && (abs(dx) > abs(dy)))
{
@ -1712,6 +1711,7 @@ _move_cb(void *data,
sd->dir = ELM_FLIP_DIRECTION_DOWN;
if (!sd->dir_enabled[ELM_FLIP_DIRECTION_DOWN]) return;
}
else return;
sd->started = EINA_TRUE;
if (sd->intmode == ELM_FLIP_INTERACTION_PAGE)
@ -2034,6 +2034,31 @@ elm_flip_interaction_set(Evas_Object *obj,
eo_do(obj, elm_obj_flip_interaction_set(mode));
}
static void
_event_rect_create(Eo *obj, Elm_Flip_Smart_Data *sd, int i)
{
Evas_Object *clip;
Evas *e;
if (sd->event[i]) return;
e = evas_object_evas_get(obj);
sd->event[i] = evas_object_rectangle_add(e);
clip = evas_object_clip_get(obj);
evas_object_data_set(sd->event[i], "_elm_leaveme", obj);
evas_object_clip_set(sd->event[i], clip);
evas_object_color_set(sd->event[i], 0, 0, 0, 0);
evas_object_show(sd->event[i]);
evas_object_smart_member_add(sd->event[i], obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_DOWN, _down_cb, obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_UP, _up_cb, obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_MOVE, _move_cb, obj);
}
static void
_interaction_set(Eo *obj, void *_pd, va_list *list)
{
@ -2045,37 +2070,15 @@ _interaction_set(Eo *obj, void *_pd, va_list *list)
if (sd->intmode == mode) return;
sd->intmode = mode;
Evas *e = evas_object_evas_get(obj);
Evas_Object *clip = evas_object_clip_get(obj);
for (i = 0; i < 4; i++)
{
if (sd->intmode == ELM_FLIP_INTERACTION_NONE)
ELM_SAFE_FREE(sd->event[i], evas_object_del);
else if (sd->dir_enabled[i])
{
if (sd->event[i])
{
evas_object_del(sd->event[i]);
sd->event[i] = NULL;
}
}
else
{
if ((sd->dir_enabled[i]) && (!sd->event[i]))
{
sd->event[i] = evas_object_rectangle_add(e);
evas_object_data_set(sd->event[i], "_elm_leaveme", obj);
evas_object_clip_set(sd->event[i], clip);
evas_object_color_set(sd->event[i], 0, 0, 0, 0);
evas_object_show(sd->event[i]);
evas_object_smart_member_add(sd->event[i], obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_DOWN, _down_cb, obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_UP, _up_cb, obj);
evas_object_event_callback_add
(sd->event[i], EVAS_CALLBACK_MOUSE_MOVE, _move_cb, obj);
}
int area = (i & 0x2) | (i ^ 0x1);
if (sd->dir_hitsize[area] >= 0.0)
_event_rect_create(obj, sd, area);
}
}
@ -2115,6 +2118,7 @@ _interaction_direction_enabled_set(Eo *obj, void *_pd, va_list *list)
Elm_Flip_Direction dir = va_arg(*list, Elm_Flip_Direction);
Eina_Bool enabled = va_arg(*list, int);
int i = (int) dir;
int area;
Elm_Flip_Smart_Data *sd = _pd;
@ -2122,27 +2126,14 @@ _interaction_direction_enabled_set(Eo *obj, void *_pd, va_list *list)
if (sd->dir_enabled[i] == enabled) return;
sd->dir_enabled[i] = enabled;
if (sd->intmode == ELM_FLIP_INTERACTION_NONE) return;
if ((sd->dir_enabled[i]) && (!sd->event[i]))
{
sd->event[i] = evas_object_rectangle_add(evas_object_evas_get(obj));
evas_object_data_set(sd->event[i], "_elm_leaveme", obj);
evas_object_clip_set(sd->event[i], evas_object_clip_get(obj));
evas_object_color_set(sd->event[i], 0, 0, 0, 0);
evas_object_show(sd->event[i]);
evas_object_smart_member_add(sd->event[i], obj);
evas_object_event_callback_add(sd->event[i], EVAS_CALLBACK_MOUSE_DOWN,
_down_cb, obj);
evas_object_event_callback_add(sd->event[i], EVAS_CALLBACK_MOUSE_UP,
_up_cb, obj);
evas_object_event_callback_add(sd->event[i], EVAS_CALLBACK_MOUSE_MOVE,
_move_cb, obj);
}
else if (!(sd->dir_enabled[i]) && (sd->event[i]))
{
evas_object_del(sd->event[i]);
sd->event[i] = NULL;
}
area = (i & 0x2) | (i ^ 0x1); // up <-> down, left <-> right
if (enabled && (sd->dir_hitsize[area] >= 0.0))
_event_rect_create(obj, sd, area);
else if (!enabled && (sd->dir_hitsize[area] <= 0.0))
// Delete this hit area as it has the default hitsize (0)
ELM_SAFE_FREE(sd->event[area], evas_object_del);
_sizing_eval(obj);
_configure(obj);
}
@ -2186,12 +2177,19 @@ _interaction_direction_hitsize_set(Eo *obj, void *_pd, va_list *list)
Elm_Flip_Smart_Data *sd = _pd;
if (hitsize < 0.0) hitsize = 0.0;
if (hitsize < 0.0)
hitsize = -1.0;
else if (hitsize > 1.0)
hitsize = 1.0;
if (sd->dir_hitsize[i] == hitsize) return;
sd->dir_hitsize[i] = hitsize;
if (hitsize >= 0.0)
_event_rect_create(obj, sd, i);
else
ELM_SAFE_FREE(sd->event[i], evas_object_del);
_sizing_eval(obj);
_configure(obj);
}

View File

@ -188,6 +188,10 @@ EAPI Elm_Flip_Interaction elm_flip_interaction_get(const Evas_Object *obj);
* desired directions for flipping if you need interactive flipping. You must
* call this function once for each direction that should be enabled.
*
* You can also set the appropriate hit area size by calling
* @c elm_flip_interaction_direction_hitsize_set(). By default, a minimum
* hit area will be created on the opposite edge of the flip.
*
* @see elm_flip_interaction_set()
*
* @ingroup Flip
@ -213,13 +217,21 @@ EAPI Eina_Bool elm_flip_interaction_direction_enabled_get(Evas_Object
* @brief Set the amount of the flip that is sensitive to interactive flip
*
* @param obj The flip object
* @param dir The direction to modify
* @param dir The hit area to set
* @param hitsize The amount of that dimension (0.0 to 1.0) to use
*
* Set the amount of the flip that is sensitive to interactive flip, with 0
* representing no area in the flip and 1 representing the entire flip. There
* is however a consideration to be made in that the area will never be
* smaller than the finger size set(as set in your Elementary configuration).
* smaller than the finger size set (as set in your Elementary configuration),
* and dragging must always start from the opposite half of the flip (eg. right
* half of the flip when dragging to the left).
*
* Note that the @c dir parameter is not actually related to the direction of
* the drag, it only refers to the area in the flip where interaction can
* occur (top, bottom, left, right).
*
* Negative values of @c hitsize will disable this hit area.
*
* @see elm_flip_interaction_set()
*