forked from enlightenment/efl
genlist: added reorder feature on key events
Summary: This feature allows user to reorder items using up/down keys. Test Plan: elementary_test -to "Genlist Reorder Mode" Reviewers: singh.amitesh, raster, seoz, SanghyeonLee Differential Revision: https://phab.enlightenment.org/D1262 Conflicts: src/bin/test_genlist.c src/lib/elm_genlist_legacy.h
This commit is contained in:
parent
be15a0dc33
commit
17419ec81c
|
@ -5,6 +5,8 @@
|
|||
#endif
|
||||
#include <Elementary.h>
|
||||
|
||||
static int tween_mode_val;
|
||||
|
||||
Evas_Object * _elm_min_set(Evas_Object *obj, Evas_Object *parent,
|
||||
Evas_Coord w, Evas_Coord h);
|
||||
|
||||
|
@ -2087,6 +2089,44 @@ _reorder_tg_changed_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSE
|
|||
elm_genlist_reorder_mode_set(data, elm_check_state_get(obj));
|
||||
}
|
||||
|
||||
static void
|
||||
_focus_highlight_ck_changed_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
|
||||
{
|
||||
elm_win_focus_highlight_enabled_set(data, elm_check_state_get(obj));
|
||||
}
|
||||
|
||||
static void
|
||||
_tween_mode_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
switch (tween_mode_val)
|
||||
{
|
||||
case 1:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_LINEAR);
|
||||
break;
|
||||
case 2:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_ACCELERATE);
|
||||
break;
|
||||
case 3:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_DECELERATE);
|
||||
break;
|
||||
case 4:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_SINUSOIDAL);
|
||||
break;
|
||||
case 5:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_DIVISOR_INTERP);
|
||||
break;
|
||||
case 6:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_BOUNCE);
|
||||
break;
|
||||
case 7:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_SPRING);
|
||||
break;
|
||||
default:
|
||||
elm_genlist_reorder_mode_start(data, ECORE_POS_MAP_LINEAR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gl_moved is called after an item was reordered.
|
||||
* This is only called when reorder mode is enabled.
|
||||
|
@ -2144,11 +2184,12 @@ static void gl_moved_before(Evas_Object *data EINA_UNUSED, Evas_Object *obj EINA
|
|||
void
|
||||
test_genlist11(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
Evas_Object *win, *fr, *lb, *bx, *tg, *gl;
|
||||
Evas_Object *win, *fr, *lb, *bx, *tg, *gl, *hbx, *ck, *grp, *rd;
|
||||
int i;
|
||||
|
||||
api_data *api = calloc(1, sizeof(api_data));
|
||||
win = elm_win_util_standard_add("genlist-reorder-mode", "Genlist Reorder Mode");
|
||||
elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
|
||||
elm_win_autodel_set(win, EINA_TRUE);
|
||||
evas_object_event_callback_add(win, EVAS_CALLBACK_FREE, _cleanup_cb, api);
|
||||
|
||||
|
@ -2176,20 +2217,116 @@ test_genlist11(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event
|
|||
api->gl = gl;
|
||||
evas_object_show(gl);
|
||||
|
||||
hbx = elm_box_add(win);
|
||||
elm_box_horizontal_set(hbx, EINA_TRUE);
|
||||
evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, 0);
|
||||
elm_box_padding_set(hbx, 20, 0);
|
||||
elm_box_pack_end(bx, hbx);
|
||||
evas_object_show(hbx);
|
||||
|
||||
tg = elm_check_add(win);
|
||||
elm_object_style_set(tg, "toggle");
|
||||
elm_object_text_set(tg, "Reorder Mode:");
|
||||
elm_check_state_set(tg, elm_config_mirrored_get());
|
||||
evas_object_smart_callback_add(tg, "changed", _reorder_tg_changed_cb, gl);
|
||||
elm_box_pack_end(bx, tg);
|
||||
elm_box_pack_end(hbx, tg);
|
||||
evas_object_show(tg);
|
||||
|
||||
ck = elm_check_add(win);
|
||||
elm_object_text_set(ck, "Focus Highlight");
|
||||
elm_check_state_set(ck, elm_win_focus_highlight_enabled_get(win));
|
||||
evas_object_smart_callback_add(ck, "changed", _focus_highlight_ck_changed_cb, win);
|
||||
elm_box_pack_end(hbx, ck);
|
||||
evas_object_show(ck);
|
||||
|
||||
lb = elm_label_add(win);
|
||||
elm_object_text_set(lb, "Select reorder tween mode:");
|
||||
elm_box_pack_end(bx, lb);
|
||||
evas_object_show(lb);
|
||||
|
||||
hbx = elm_box_add(win);
|
||||
elm_box_horizontal_set(hbx, EINA_TRUE);
|
||||
evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, 0);
|
||||
elm_box_pack_end(bx, hbx);
|
||||
evas_object_show(hbx);
|
||||
|
||||
grp = rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Linear");
|
||||
elm_radio_state_value_set(rd, 1);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Accelerate");
|
||||
elm_radio_state_value_set(rd, 2);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Decelerate");
|
||||
elm_radio_state_value_set(rd, 3);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Sinusoidal");
|
||||
elm_radio_state_value_set(rd, 4);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
hbx = elm_box_add(win);
|
||||
elm_box_horizontal_set(hbx, EINA_TRUE);
|
||||
evas_object_size_hint_weight_set(hbx, EVAS_HINT_EXPAND, 0);
|
||||
elm_box_pack_end(bx, hbx);
|
||||
evas_object_show(hbx);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Divisor Interpolation");
|
||||
elm_radio_state_value_set(rd, 5);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Bounce");
|
||||
elm_radio_state_value_set(rd, 6);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
rd = elm_radio_add(win);
|
||||
elm_object_text_set(rd, "Spring");
|
||||
elm_radio_state_value_set(rd, 7);
|
||||
elm_radio_value_pointer_set(rd, &tween_mode_val);
|
||||
elm_radio_group_add(rd, grp);
|
||||
evas_object_smart_callback_add(rd, "changed", _tween_mode_changed_cb, gl);
|
||||
elm_box_pack_end(hbx, rd);
|
||||
evas_object_show(rd);
|
||||
|
||||
elm_radio_value_set(grp, 1);
|
||||
|
||||
api->itc1 = elm_genlist_item_class_new();
|
||||
api->itc1->item_style = "default";
|
||||
api->itc1->func.text_get = gl_text_get;
|
||||
api->itc1->func.content_get = gl_content_get;
|
||||
api->itc1->func.state_get = gl_state_get;
|
||||
api->itc1->func.del = NULL;
|
||||
|
||||
evas_object_smart_callback_add(gl, "moved", (Evas_Smart_Cb)gl_moved, gl);
|
||||
evas_object_smart_callback_add(gl, "moved,after", (Evas_Smart_Cb)gl_moved_after, gl);
|
||||
evas_object_smart_callback_add(gl, "moved,before", (Evas_Smart_Cb)gl_moved_before, gl);
|
||||
|
|
|
@ -89,7 +89,9 @@
|
|||
cmd(SIG_ITEM_FOCUSED, "item,focused", "") \
|
||||
cmd(SIG_ITEM_UNFOCUSED, "item,unfocused", "") \
|
||||
cmd(SIG_PRESSED, "pressed", "") \
|
||||
cmd(SIG_RELEASED, "released", "")
|
||||
cmd(SIG_RELEASED, "released", "") \
|
||||
cmd(SIG_ITEM_REORDER_START, "item,reorder,anim,start", "") \
|
||||
cmd(SIG_ITEM_REORDER_STOP, "item,reorder,anim,stop", "")
|
||||
|
||||
ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
|
||||
|
||||
|
@ -109,7 +111,11 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
|
|||
static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
|
||||
static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
|
||||
static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params);
|
||||
|
||||
static void _item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after);
|
||||
static void _item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before);
|
||||
EOLIAN static void _elm_genlist_reorder_mode_set(Eo *obj EINA_UNUSED,
|
||||
Elm_Genlist_Data *sd,
|
||||
Eina_Bool reorder_mode);
|
||||
|
||||
static const Elm_Action key_actions[] = {
|
||||
{"move", _key_action_move},
|
||||
|
@ -2716,6 +2722,98 @@ _key_action_move_dir(Evas_Object *obj, Elm_Focus_Direction dir, Eina_Bool multi)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_anim_end(Elm_Genlist_Data *sd)
|
||||
{
|
||||
if (sd->reorder.dir == ELM_FOCUS_UP)
|
||||
_item_move_after(sd->reorder.it2, sd->reorder.it1);
|
||||
else if (sd->reorder.dir == ELM_FOCUS_DOWN)
|
||||
_item_move_after(sd->reorder.it1, sd->reorder.it2);
|
||||
|
||||
ecore_job_del(sd->calc_job);
|
||||
sd->calc_job = ecore_job_add(_calc_job, sd->obj);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_item_swap_cb(void *data, double pos)
|
||||
{
|
||||
Elm_Genlist_Data *sd = data;
|
||||
double frame = pos;
|
||||
Evas_Coord xx1, yy1, xx2, yy2;
|
||||
double dx, dy;
|
||||
|
||||
switch (sd->reorder.tween_mode)
|
||||
{
|
||||
case ECORE_POS_MAP_LINEAR:
|
||||
frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 0, 0);
|
||||
break;
|
||||
case ECORE_POS_MAP_ACCELERATE:
|
||||
case ECORE_POS_MAP_DECELERATE:
|
||||
case ECORE_POS_MAP_SINUSOIDAL:
|
||||
frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 1.0, 0);
|
||||
break;
|
||||
case ECORE_POS_MAP_DIVISOR_INTERP:
|
||||
case ECORE_POS_MAP_BOUNCE:
|
||||
case ECORE_POS_MAP_SPRING:
|
||||
frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 1.0, 1.0);
|
||||
break;
|
||||
default:
|
||||
// use ECORE_POS_MAP_LINEAR as default tween mode
|
||||
frame = ecore_animator_pos_map(frame, sd->reorder.tween_mode, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
dx = sd->reorder.x2 - sd->reorder.x1;
|
||||
dy = sd->reorder.y2 - sd->reorder.y1;
|
||||
|
||||
xx1 = sd->reorder.x1 + (dx * frame);
|
||||
yy1 = sd->reorder.y1 + (dy * frame);
|
||||
xx2 = sd->reorder.x2 - (dx * frame);
|
||||
yy2 = sd->reorder.y2 - (dy * frame);
|
||||
|
||||
evas_object_move(VIEW(sd->reorder.it2), xx2, yy2);
|
||||
evas_object_move(VIEW(sd->reorder.it1), xx1, yy1);
|
||||
|
||||
if (pos == 1.0)
|
||||
{
|
||||
elm_genlist_item_bring_in((Elm_Object_Item *)sd->reorder.it2, ELM_GENLIST_ITEM_SCROLLTO_IN);
|
||||
_anim_end(sd);
|
||||
evas_object_smart_callback_call(sd->obj, SIG_ITEM_REORDER_STOP, sd->reorder.it1);
|
||||
sd->reorder.running = EINA_FALSE;
|
||||
}
|
||||
|
||||
_elm_widget_focus_highlight_start(sd->obj);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_swap_items(Elm_Gen_Item *it1, Elm_Gen_Item *it2, Elm_Focus_Direction dir)
|
||||
{
|
||||
ELM_GENLIST_DATA_GET_FROM_ITEM(it1, sd);
|
||||
Evas_Coord xx1, yy1, xx2, yy2;
|
||||
|
||||
if (!it1 || !it2) return;
|
||||
|
||||
sd->reorder.running = EINA_TRUE;
|
||||
sd->reorder.dir = dir;
|
||||
sd->reorder.it1 = it1;
|
||||
sd->reorder.it2 = it2;
|
||||
|
||||
evas_object_geometry_get(VIEW(it1), &xx1, &yy1, NULL, NULL);
|
||||
evas_object_geometry_get(VIEW(it2), &xx2, &yy2, NULL, NULL);
|
||||
sd->reorder.x1 = xx1;
|
||||
sd->reorder.y1 = yy1;
|
||||
sd->reorder.x2 = xx2;
|
||||
sd->reorder.y2 = yy2;
|
||||
|
||||
evas_object_raise(VIEW(it1));
|
||||
evas_object_smart_callback_call(sd->obj, SIG_ITEM_REORDER_START, sd->reorder.it1);
|
||||
//TODO: Add elm config for time
|
||||
ecore_animator_timeline_add(0.3, _item_swap_cb, sd);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_key_action_move(Evas_Object *obj, const char *params)
|
||||
{
|
||||
|
@ -2762,6 +2860,18 @@ _key_action_move(Evas_Object *obj, const char *params)
|
|||
}
|
||||
else if (!strcmp(dir, "up"))
|
||||
{
|
||||
if (sd->reorder.running) return EINA_TRUE;
|
||||
if (sd->reorder_mode)
|
||||
{
|
||||
Elm_Gen_Item *up = (Elm_Gen_Item *)elm_genlist_item_prev_get(sd->focused_item);
|
||||
ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focused_it);
|
||||
ELM_GENLIST_ITEM_DATA_GET(up, up2);
|
||||
|
||||
_swap_items(focused_it, up2, ELM_FOCUS_UP);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (_key_action_move_dir(obj, ELM_FOCUS_UP, EINA_FALSE)) return EINA_TRUE;
|
||||
else return EINA_FALSE;
|
||||
}
|
||||
|
@ -2773,6 +2883,18 @@ _key_action_move(Evas_Object *obj, const char *params)
|
|||
}
|
||||
else if (!strcmp(dir, "down"))
|
||||
{
|
||||
if (sd->reorder.running) return EINA_TRUE;
|
||||
if (sd->reorder_mode)
|
||||
{
|
||||
Elm_Gen_Item *down = (Elm_Gen_Item *)elm_genlist_item_next_get(sd->focused_item);
|
||||
ELM_GENLIST_ITEM_DATA_GET(sd->focused_item, focused_it);
|
||||
ELM_GENLIST_ITEM_DATA_GET(down, down2);
|
||||
|
||||
_swap_items(focused_it, down2, ELM_FOCUS_DOWN);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (_key_action_move_dir(obj, ELM_FOCUS_DOWN, EINA_FALSE)) return EINA_TRUE;
|
||||
else return EINA_FALSE;
|
||||
}
|
||||
|
@ -7342,6 +7464,25 @@ _elm_genlist_decorate_mode_set(Eo *obj, Elm_Genlist_Data *sd, Eina_Bool decorate
|
|||
sd->calc_job = ecore_job_add(_calc_job, sd->obj);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_genlist_reorder_mode_start(Evas_Object *obj, Ecore_Pos_Map tween_mode)
|
||||
{
|
||||
ELM_GENLIST_CHECK(obj);
|
||||
ELM_GENLIST_DATA_GET(obj, sd);
|
||||
|
||||
sd->reorder.tween_mode = tween_mode;
|
||||
_elm_genlist_reorder_mode_set(obj, sd, EINA_TRUE);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_genlist_reorder_mode_stop(Evas_Object *obj)
|
||||
{
|
||||
ELM_GENLIST_CHECK(obj);
|
||||
ELM_GENLIST_DATA_GET(obj, sd);
|
||||
|
||||
_elm_genlist_reorder_mode_set(obj, sd, EINA_FALSE);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_elm_genlist_reorder_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bool reorder_mode)
|
||||
{
|
||||
|
|
|
@ -379,7 +379,12 @@
|
|||
* - @c "unfocused" - When the genlist has lost focus. (since 1.8)
|
||||
* - @c "item,focused" - When the genlist item has recieved focus. (since 1.10)
|
||||
* - @c "item,unfocused" - When the genlist item has lost focus. (since 1.10)
|
||||
*
|
||||
* - @c "item,reorder,anim,start" - This is called when a genglist item's movement
|
||||
has just started by keys in reorder mode. The %c event_info parameter
|
||||
* is the item that is going to move. (since 1.13)
|
||||
* - @c "item,reorder,anim,stop" - This is called when a genlist item's movement just
|
||||
stopped in reorder mode. The %c event_info parameter is the item
|
||||
that was moved. (since 1.13)
|
||||
*
|
||||
* Supported elm_object_item common APIs
|
||||
* @li @ref elm_object_item_part_content_get
|
||||
|
|
|
@ -31,5 +31,33 @@ EAPI Evas_Object *elm_genlist_add(Evas_Object *parent);
|
|||
EAPI Elm_Object_Item *
|
||||
elm_genlist_nth_item_get(const Evas_Object *obj, unsigned int nth);
|
||||
|
||||
#include "elm_genlist_item.eo.legacy.h"
|
||||
/**
|
||||
* Enable item reorder mode with keys for genlist widget
|
||||
*
|
||||
* @param obj The genlist object
|
||||
* @param tween_mode Position mappings for animation
|
||||
* @see _Ecore_Pos_Map
|
||||
*
|
||||
* @see elm_genlist_reorder_mode_stop()
|
||||
* @since 1.13
|
||||
*
|
||||
* @ingroup Genlist
|
||||
*/
|
||||
EAPI void
|
||||
elm_genlist_reorder_mode_start(Evas_Object *obj, Ecore_Pos_Map tween_mode);
|
||||
|
||||
/**
|
||||
* Stop item reorder mode with keys for genlist widget
|
||||
*
|
||||
* @param obj The genlist object
|
||||
*
|
||||
* @see elm_genlist_reorder_mode_start()
|
||||
* @since 1.13
|
||||
*
|
||||
* @ingroup Genlist
|
||||
*/
|
||||
EAPI void
|
||||
elm_genlist_reorder_mode_stop(Evas_Object *obj);
|
||||
|
||||
#include "elm_genlist.eo.legacy.h"
|
||||
#include "elm_genlist_item.eo.legacy.h"
|
||||
|
|
|
@ -140,6 +140,15 @@ struct _Elm_Genlist_Data
|
|||
Elm_Genlist_Item_Move_Effect_Mode move_effect_mode;
|
||||
int reorder_fast;
|
||||
|
||||
struct
|
||||
{
|
||||
Elm_Gen_Item *it1, *it2; /**< The items which are getting swapped */
|
||||
Elm_Focus_Direction dir; /**< focus key direction */
|
||||
Ecore_Pos_Map tween_mode; /**< Position mappings for animation */
|
||||
Evas_Coord x1, y1, x2, y2; /**< Coordinates of it1 and it2 */
|
||||
Eina_Bool running : 1; /**< animation is happening */
|
||||
} reorder;
|
||||
|
||||
Eina_Bool focus_on_selection_enabled : 1;
|
||||
Eina_Bool tree_effect_enabled : 1;
|
||||
Eina_Bool auto_scroll_enabled : 1;
|
||||
|
|
Loading…
Reference in New Issue