yakov pushed a commit to branch master. http://git.enlightenment.org/tools/erigo.git/commit/?id=779f9bbba1fed11ddc7ceb39c22ba35c9b8902a3
commit 779f9bbba1fed11ddc7ceb39c22ba35c9b8902a3 Author: Yakov Goldberg <[email protected]> Date: Mon May 11 18:33:55 2015 +0300 Implement DnD from factory/canvas to objtree. Objects can be dragged from factory/canvas to objtree. --- NEWS | 1 + src/bin/gui/dnd.c | 19 +++- src/bin/gui/dnd.h | 6 ++ src/bin/gui/editor.c | 276 ++++++++++++++++++++++++++++++++++----------------- 4 files changed, 211 insertions(+), 91 deletions(-) diff --git a/NEWS b/NEWS index 833a130..0ea01df 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ Changes since 1.0.0 Features: * Add support for widgets: Hoversel * Add multicontext support: up to 15 contexts can be opened. + * Add DnD to objtree. Objects can be dragged from factory/canvas to objtree. Fixes: * Don't show empty hoversel in Property view when there is no resources. diff --git a/src/bin/gui/dnd.c b/src/bin/gui/dnd.c index cce2ad0..5ede42a 100644 --- a/src/bin/gui/dnd.c +++ b/src/bin/gui/dnd.c @@ -107,6 +107,8 @@ static void _dropenter(void *data, Evas_Object *obj) { _dnd_info.dnd_in_out++; + /* data is NULL when entering/leaving objtree. */ + if (!data) return; Target_Info *ti = data; ti->drop_target = ti->wdg; @@ -120,8 +122,10 @@ _dropenter(void *data, Evas_Object *obj) static void _dropleave(void *data, Evas_Object *obj) { - Target_Info *main_wdg_ti = data; _dnd_info.dnd_in_out--; + /* data is NULL when entering/leaving objtree. */ + if (!data) return; + Target_Info *main_wdg_ti = data; /* if ti->drop_target is not current main widget, then it means, * that prev drop target, box for example wasn't leaved properly. @@ -610,6 +614,19 @@ drop_target_main_wdg_set(Gui_Widget *wdg, Eo *obj, } void +drop_item_container_set(Eo *obj, Elm_Xy_Item_Get_Cb itemgetcb, Elm_Drop_Item_Container_Cb dropcb, void *dropdata) +{ + elm_drop_item_container_add(obj, ELM_SEL_FORMAT_TARGETS, itemgetcb, + _dropenter, NULL, _dropleave, NULL, NULL, NULL, dropcb, dropdata); +} + +void +drop_item_container_del(Eo *obj) +{ + elm_drop_item_container_del(obj); +} + +void drop_target_wdg_del(Gui_Widget *wdg, Eo *obj) { Target_Info *ti = NULL; diff --git a/src/bin/gui/dnd.h b/src/bin/gui/dnd.h index 185848c..f9e1d3c 100644 --- a/src/bin/gui/dnd.h +++ b/src/bin/gui/dnd.h @@ -28,6 +28,12 @@ drop_target_main_wdg_set(Gui_Widget *wdg, Eo *obj, void drop_target_wdg_del(Gui_Widget *wdg, Eo *obj); +void +drop_item_container_set(Eo *obj, Elm_Xy_Item_Get_Cb itemgetcb, Elm_Drop_Item_Container_Cb dropcb, void *dropdata); + +void +drop_item_container_del(Eo *obj); + const char* dnd_drag_data_get(); diff --git a/src/bin/gui/editor.c b/src/bin/gui/editor.c index 8197904..7755080 100644 --- a/src/bin/gui/editor.c +++ b/src/bin/gui/editor.c @@ -1638,15 +1638,29 @@ _drop_target_leave(void *data, Evas_Object *obj EINA_UNUSED) } } +/* In the beginning of drop handler we want to determine, + * whenever drop can be successfull. */ +enum +{ + NO_DROP, + DROP_TO_CANVAS, + DROP_TO_WIN, + DROP_TO_BOX, + DROP_TO_TABLE, + DROP_TO_MAIN +}; + static Gui_Widget* _editor_factory_wdg_create(const char *class_name, const Gui_Widget *focused_wdg, Evas_Coord main_wdg_x, Evas_Coord main_wdg_y); +/* canvas_drop_target != NULL when dropping on canvas. */ static Eina_Bool -_drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) +_drop_target_drop(Gui_Widget *wdg, Eo *canvas_drop_target, const char *drag_data, Eina_Bool dropped_to_objtree) { - Gui_Widget *wdg = data; - Eo *canvas_drop_target = obj; DnD_Info *di = NULL; + const Gui_Widget *new_wdg = NULL; + int drop_to_wdg = NO_DROP; + _wdg_border_draw(NULL, EINA_FALSE, BORDER_DROP_TARGET); if (wdg) { @@ -1661,13 +1675,39 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) ERR("Drop target is wrong. If you see this message something is terribly wrong!"); } - const char *drag_data = ev->data; - const Gui_Widget *new_wdg = NULL; + if (!wdg) + { + drop_to_wdg = DROP_TO_CANVAS; + } + else if (IS_WIN(wdg)) + { + drop_to_wdg = DROP_TO_WIN; + } + else if (!strcmp(wdg_class_name_get(wdg), DB_DEF_BOX_CLASS)) + { + drop_to_wdg = DROP_TO_BOX; + } + else if (!strcmp(wdg_class_name_get(wdg), DB_DEF_TABLE_CLASS)) + { + drop_to_wdg = DROP_TO_TABLE; + } + else if (IS_MAIN(wdg)) + { + drop_to_wdg = DROP_TO_MAIN; + } + if (drop_to_wdg == NO_DROP) goto end; + const Gui_Context *ctx = _active_context_get(); const Gui_Session *session = gui_context_editor_session_get(ctx); /* If drag_data != EDITOR_DRAG_DATA then new widget was dragged from the factory. */ Eina_Bool drag_from_factory = !!strcmp(drag_data, EDITOR_DRAG_DATA); /* Drop when dragging from factory. */ + int drop_x = di->pointer_x, drop_y = di->pointer_y; + if (dropped_to_objtree) + { + drop_x = drop_y = 0; + } + if (drag_from_factory) { /* Don't allow to drop Window from factory into Main Obj*/ @@ -1675,7 +1715,7 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) { goto end; } - new_wdg = _editor_factory_wdg_create(drag_data, wdg, di->pointer_x, di->pointer_y); + new_wdg = _editor_factory_wdg_create(drag_data, wdg, drop_x, drop_y); } else { @@ -1805,9 +1845,9 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) } val = prop_value_nth_get(prop, 0); - gui_value_int_set(val, di->pointer_x); + gui_value_int_set(val, drop_x); val = prop_value_nth_get(prop, 1); - gui_value_int_set(val, di->pointer_y); + gui_value_int_set(val, drop_y); propview_item_update(prop); Gui_Memento *memento = NULL; @@ -1831,7 +1871,6 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) } goto end; } - /* Dragging main wdg around canvas. */ else if (!wdg_parent && !wdg) { @@ -1878,7 +1917,7 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) } /* Where to drop. */ - if (!wdg) + if (drop_to_wdg == DROP_TO_CANVAS) { Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(new_wdg), MEMENTO_WIDGET_PARENT, @@ -1892,7 +1931,7 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) } } /* Dragging into win */ - else if (wdg && IS_WIN(wdg)) + else if (drop_to_wdg == DROP_TO_WIN) { Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(new_wdg), MEMENTO_WIDGET_PARENT, @@ -1916,9 +1955,9 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) } val = prop_value_nth_get(prop, 0); - gui_value_int_set(val, di->pointer_x); + gui_value_int_set(val, drop_x); val = prop_value_nth_get(prop, 1); - gui_value_int_set(val, di->pointer_y); + gui_value_int_set(val, drop_y); propview_item_update(prop); memento_next = gui_memento_new(wdg_eid_get(new_wdg), MEMENTO_PROPERTY, old_prop, prop); @@ -1931,87 +1970,93 @@ _drop_target_drop(void *data, Evas_Object *obj, Elm_Selection_Data *ev) wdg_prop_add((Gui_Widget *) new_wdg, prop); } } - else + else if (drop_to_wdg == DROP_TO_BOX) { - if (wdg && !strcmp(wdg_class_name_get(wdg), DB_DEF_BOX_CLASS)) - { - /* Append content memento to the creation memento (which was created in _editor_factory_wdg_create()) - * or to memento unpacking from previous container - * in order to correctly manage internals. */ - Object_Container *_old_container, *_new_container; - _old_container = (Object_Container *) wdg_obj_container_get(wdg); - _new_container = obj_container_copy(_old_container); - - Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(wdg), - MEMENTO_OBJ_CONTAINER_ITEM, - _old_container, _new_container); - /* Current memento is a memento created, during _factory _widget_create earlier in this func. */ - gui_memento_append((Gui_Memento *) gui_context_current_memento_get(ctx), memento_next); - wdg_obj_container_unset(wdg); - wdg_obj_container_set(wdg, _new_container); - - const Op_Desc *op_desc = db_container_desc_op_desc_get(db_container_desc_get(wdg_class_name_get(wdg)), CONTAINER_PACK); - Gui_Widget_Property *prop = prop_create_for_op(op_desc); - Gui_Value *val = prop_value_nth_get(prop, 0); - gui_value_name_id_set(val, GUI_TYPE_OBJECT, wdg_eid_get(new_wdg)); - - Object_Container_Item *ci = obj_container_item_new(prop, wdg_eid_get(new_wdg)); - wdg_obj_container_item_add(wdg, ci, di->box_pack_idx); - } - else if (wdg && !strcmp(wdg_class_name_get(wdg), DB_DEF_TABLE_CLASS)) - { - Eo *wdg_eo = session_eo_get(session, wdg); - Object_Container_Item *it; + /* Append content memento to the creation memento (which was created in _editor_factory_wdg_create()) + * or to memento unpacking from previous container + * in order to correctly manage internals. */ + Object_Container *_old_container, *_new_container; + _old_container = (Object_Container *) wdg_obj_container_get(wdg); + _new_container = obj_container_copy(_old_container); - Object_Container *_old_container, *_new_container; - _old_container = (Object_Container *) wdg_obj_container_get(wdg); - _new_container = obj_container_copy(_old_container); + Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(wdg), + MEMENTO_OBJ_CONTAINER_ITEM, + _old_container, _new_container); + /* Current memento is a memento created, during _factory _widget_create earlier in this func. */ + gui_memento_append((Gui_Memento *) gui_context_current_memento_get(ctx), memento_next); + wdg_obj_container_unset(wdg); + wdg_obj_container_set(wdg, _new_container); - Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(wdg), - MEMENTO_OBJ_CONTAINER_ITEM, - _old_container, _new_container); - /* Current memento is a memento created, during _factory _widget_create earlier in this func. */ - gui_memento_append((Gui_Memento *) gui_context_current_memento_get(ctx), memento_next); + const Op_Desc *op_desc = db_container_desc_op_desc_get(db_container_desc_get(wdg_class_name_get(wdg)), CONTAINER_PACK); + Gui_Widget_Property *prop = prop_create_for_op(op_desc); + Gui_Value *val = prop_value_nth_get(prop, 0); + gui_value_name_id_set(val, GUI_TYPE_OBJECT, wdg_eid_get(new_wdg)); - Eina_List *old_lst = wdg_obj_container_contents_list_get(wdg); - wdg_obj_container_unset(wdg); - wdg_obj_container_set(wdg, _new_container); + Object_Container_Item *ci = obj_container_item_new(prop, wdg_eid_get(new_wdg)); + wdg_obj_container_item_add(wdg, ci, di->box_pack_idx); + } + else if (drop_to_wdg == DROP_TO_TABLE) + { + Eo *wdg_eo = session_eo_get(session, wdg); + Object_Container_Item *it; - /* Delete everything in new_container */ - wdg_obj_container_item_remove_all(wdg); + Object_Container *_old_container, *_new_container; + _old_container = (Object_Container *) wdg_obj_container_get(wdg); + _new_container = obj_container_copy(_old_container); - /* Iterate over old list and create new container items and properties. - * Also get packing coordinates from Eo object and put it into property. */ - Eina_List *l; - EINA_LIST_FOREACH(old_lst, l, it) - { - Gui_Widget_Property *prop = obj_container_item_prop_get(it); - Gui_Widget_Property *new_prop = prop_copy(prop); - int ix, iy, iw, ih; - Eid *eid = obj_container_item_eid_get(it); - Eo *c = session_eo_get(session, wdg_get(eid)); - eo_do(wdg_eo, elm_obj_table_pack_get(c, &ix, &iy, &iw, &ih)); + Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(wdg), + MEMENTO_OBJ_CONTAINER_ITEM, + _old_container, _new_container); + /* Current memento is a memento created, during _factory _widget_create earlier in this func. */ + gui_memento_append((Gui_Memento *) gui_context_current_memento_get(ctx), memento_next); - gui_value_int_set(prop_value_nth_get(new_prop, 1), ix); - gui_value_int_set(prop_value_nth_get(new_prop, 2), iy); + Eina_List *old_lst = wdg_obj_container_contents_list_get(wdg); + wdg_obj_container_unset(wdg); + wdg_obj_container_set(wdg, _new_container); - Object_Container_Item *ci = obj_container_item_new(new_prop, eid); - wdg_obj_container_item_add((Gui_Widget *) wdg, ci, -1); - } + /* Delete everything in new_container */ + wdg_obj_container_item_remove_all(wdg); - /* Add new element into the container */ - const Op_Desc *op_desc = db_container_desc_op_desc_get(db_container_desc_get(wdg_class_name_get(wdg)), CONTAINER_PACK); - Gui_Widget_Property *prop = prop_create_for_op(op_desc); + /* Iterate over old list and create new container items and properties. + * Also get packing coordinates from Eo object and put it into property. */ + Eina_List *l; + EINA_LIST_FOREACH(old_lst, l, it) + { + Gui_Widget_Property *prop = obj_container_item_prop_get(it); + Gui_Widget_Property *new_prop = prop_copy(prop); + int ix, iy, iw, ih; + Eid *eid = obj_container_item_eid_get(it); + Eo *c = session_eo_get(session, wdg_get(eid)); + eo_do(wdg_eo, elm_obj_table_pack_get(c, &ix, &iy, &iw, &ih)); - gui_value_name_id_set(prop_value_nth_get(prop, 0), GUI_TYPE_OBJECT, wdg_eid_get(new_wdg)); - gui_value_int_set(prop_value_nth_get(prop, 1), di->table_pack_x); - gui_value_int_set(prop_value_nth_get(prop, 2), di->table_pack_y); - gui_value_int_set(prop_value_nth_get(prop, 3), 1); - gui_value_int_set(prop_value_nth_get(prop, 4), 1); + gui_value_int_set(prop_value_nth_get(new_prop, 1), ix); + gui_value_int_set(prop_value_nth_get(new_prop, 2), iy); - Object_Container_Item *ci = obj_container_item_new(prop, wdg_eid_get(new_wdg)); - wdg_obj_container_item_add(wdg, ci, -1); + Object_Container_Item *ci = obj_container_item_new(new_prop, eid); + wdg_obj_container_item_add((Gui_Widget *) wdg, ci, -1); } + + /* Add new element into the container */ + const Op_Desc *op_desc = db_container_desc_op_desc_get(db_container_desc_get(wdg_class_name_get(wdg)), CONTAINER_PACK); + Gui_Widget_Property *prop = prop_create_for_op(op_desc); + + gui_value_name_id_set(prop_value_nth_get(prop, 0), GUI_TYPE_OBJECT, wdg_eid_get(new_wdg)); + gui_value_int_set(prop_value_nth_get(prop, 1), di->table_pack_x); + gui_value_int_set(prop_value_nth_get(prop, 2), di->table_pack_y); + gui_value_int_set(prop_value_nth_get(prop, 3), 1); + gui_value_int_set(prop_value_nth_get(prop, 4), 1); + + Object_Container_Item *ci = obj_container_item_new(prop, wdg_eid_get(new_wdg)); + wdg_obj_container_item_add(wdg, ci, -1); + } + /* When drop into main object which is not window, only update parent. */ + else if (drop_to_wdg == DROP_TO_MAIN) + { + Gui_Memento *memento_next = gui_memento_new(wdg_eid_get(new_wdg), + MEMENTO_WIDGET_PARENT, + wdg_parent_id_get(new_wdg), wdg_eid_get(wdg)); + gui_memento_append((Gui_Memento *) gui_context_current_memento_get(ctx), memento_next); + wdg_parent_set((Gui_Widget *) new_wdg, wdg_name_get(wdg)); } end: @@ -2025,11 +2070,60 @@ end: } } - _wdg_parent_win_reload(new_wdg); - _editor_wdg_selected_set(new_wdg); - objtree_build(wdg_context_get(new_wdg)); - objtree_item_selected_set(new_wdg); + if (new_wdg) + { + _wdg_parent_win_reload(new_wdg); + _editor_wdg_selected_set(new_wdg); + objtree_build(wdg_context_get(new_wdg)); + objtree_item_selected_set(new_wdg); + } + + return EINA_TRUE; +} + +static Eina_Bool +_drop_target_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *ev) +{ + const char *drag_data = ev->data; + return _drop_target_drop(data, obj, drag_data, EINA_FALSE); +} + +static Elm_Object_Item * +_objtree_it_get_cb(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret EINA_UNUSED, int *yposret) +{ + Elm_Object_Item *it; + eo_do(obj, it = elm_obj_genlist_at_xy_item_get(x, y, yposret)); + return it; +} + +static Eina_Bool +_objtree_drop_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, Elm_Object_Item *it, Elm_Selection_Data *ev, int xposret EINA_UNUSED, int yposret EINA_UNUSED) +{ + /* This function is called when data is dropped on the genlist */ + Eo *canvas = NULL; + Gui_Widget *wdg = NULL; + if (it) + { + wdg = elm_object_item_data_get(it); + /* if widget is a box or table, drop into it, + * othervise drop into parent. */ + if (!strcmp(wdg_class_name_get(wdg), DB_DEF_BOX_CLASS) || + !strcmp(wdg_class_name_get(wdg), DB_DEF_TABLE_CLASS)) + { + } + else + { + /* If dropping to main obj, return main object itself.*/ + wdg = wdg_parent_get(wdg) ? (Gui_Widget *) wdg_parent_get(wdg) : wdg; + } + } + else + { + canvas = g->main_win->canvas_bg; + } + const char *drag_data = ev->data; + _drop_target_drop(wdg, canvas, drag_data, EINA_TRUE); return EINA_TRUE; } @@ -2381,7 +2475,7 @@ _widget_add(Gui_Session *session, const Gui_Widget *wdg, void *data) _drop_target_enter, (void *) wdg, _drop_target_leave, (void *) wdg, _drop_target_pos, (void *) wdg, - _drop_target_drop, (void *) wdg); + _drop_target_drop_cb, (void *) wdg); } else if (!strcmp(wdg_class_name_get(wdg), DB_DEF_TABLE_CLASS)) { @@ -2389,7 +2483,7 @@ _widget_add(Gui_Session *session, const Gui_Widget *wdg, void *data) _drop_target_enter, (void *) wdg, _drop_target_leave, (void *) wdg, _drop_target_pos, (void *) wdg, - _drop_target_drop, (void *) wdg); + _drop_target_drop_cb, (void *) wdg); } } else @@ -2490,7 +2584,7 @@ _widget_add(Gui_Session *session, const Gui_Widget *wdg, void *data) _drop_target_main_wdg_enter, (void *) wdg, _drop_target_main_wdg_leave, (void *) wdg, _drop_target_pos, (void *) wdg, - _drop_target_drop, (void *) wdg); + _drop_target_drop_cb, (void *) wdg); eo_do(fr, efl_gfx_visible_set(EINA_TRUE)); eo_do(win, eo_key_data_set("__editor_frame", fr, NULL)); @@ -4581,9 +4675,11 @@ editor_init(GuiLogicCbs *_guilogic_cbs) _drop_target_main_wdg_enter, NULL, _drop_target_main_wdg_leave, NULL, _drop_target_pos, NULL, - _drop_target_drop, NULL + _drop_target_drop_cb, NULL ); + drop_item_container_set(g->main_win->objtree_list, _objtree_it_get_cb, _objtree_drop_cb, NULL); + key_binding_new(_key_binding_undo_cb, NULL, "ctrl", "z", NULL); key_binding_new(_key_binding_redo_cb, NULL, "ctrl", "shift", "z", NULL); key_binding_new(_key_binding_wdg_del_cb, NULL, "delete", NULL); --
