From 4cf069ede935dd8c93f6e814a08fb84ad4230538 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Wed, 11 Dec 2013 11:37:04 +0900 Subject: [PATCH] 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. --- legacy/elementary/src/lib/elm_flip.c | 96 ++++++++++----------- legacy/elementary/src/lib/elm_flip_legacy.h | 16 +++- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/legacy/elementary/src/lib/elm_flip.c b/legacy/elementary/src/lib/elm_flip.c index c24e25da9f..36f2fdd323 100644 --- a/legacy/elementary/src/lib/elm_flip.c +++ b/legacy/elementary/src/lib/elm_flip.c @@ -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); } diff --git a/legacy/elementary/src/lib/elm_flip_legacy.h b/legacy/elementary/src/lib/elm_flip_legacy.h index 3e463dcd68..6fcf15e1cf 100644 --- a/legacy/elementary/src/lib/elm_flip_legacy.h +++ b/legacy/elementary/src/lib/elm_flip_legacy.h @@ -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() *