yakov pushed a commit to branch master. http://git.enlightenment.org/tools/erigo.git/commit/?id=e38a80988293857a6eb40882da72bc9d749d8c71
commit e38a80988293857a6eb40882da72bc9d749d8c71 Author: Daniel Zaoui <daniel.za...@samsung.com> Date: Thu Oct 29 11:40:23 2015 +0200 Implement the memento squash If, for example, a widget A is moved inside a same box (ABC), two mementos commands will be created: - "container change from ABC to BC" - "container change from AB to BCA" In this case, we can merge the commands to "container change from ABC to BCA" --- src/lib/undoredo.c | 177 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 72 deletions(-) diff --git a/src/lib/undoredo.c b/src/lib/undoredo.c index 8858185..6d981b2 100644 --- a/src/lib/undoredo.c +++ b/src/lib/undoredo.c @@ -10,6 +10,11 @@ struct _Memento_Command { struct { + void *old_ptr; + void *new_ptr; + }; + struct + { const Gui_Widget_Property *old_property; const Gui_Widget_Property *new_property; }; @@ -178,84 +183,87 @@ memento_command_add(Eid *eid, Memento_Type type, void *old_pointer, void *new_po return EINA_TRUE; } +static void +_cmd_del(Memento_Command *cmd) +{ + switch (cmd->type) + { + case MEMENTO_PROPERTY: + { + /* old_pointer can be NULL only when property was never set. */ + if (cmd->old_property) + prop_unref((Gui_Widget_Property *) cmd->old_property); + if (cmd->new_property) + prop_unref((Gui_Widget_Property *) cmd->new_property); + break; + } + case MEMENTO_CALLBACK: + { + if (cmd->old_callback) + cb_unref((Gui_Widget_Callback *) cmd->old_callback); + if (cmd->new_callback) + cb_unref((Gui_Widget_Callback *) cmd->new_callback); + break; + } + case MEMENTO_CALLBACK_ADD_DEL: + { + if (cmd->old_cb_container) + cb_container_unref((Callback_Container *) cmd->old_cb_container); + if (cmd->new_cb_container) + cb_container_unref((Callback_Container *) cmd->new_cb_container); + break; + } + case MEMENTO_OBJ_CONTAINER_ITEM: + { + if (cmd->old_obj_container) + obj_container_unref((Object_Container *) cmd->old_obj_container); + if (cmd->new_obj_container) + obj_container_unref((Object_Container *) cmd->new_obj_container); + break; + } + case MEMENTO_ITEM_CONTAINER_ITEM: + { + if (cmd->old_item) + item_container_item_unref((Item_Container_Item *) cmd->old_item); + if (cmd->new_item) + item_container_item_unref((Item_Container_Item *) cmd->new_item); + break; + } + case MEMENTO_WIDGET: + case MEMENTO_WIDGET_PARENT: + case MEMENTO_WIDGET_PUBLIC: + { + break; + } + case MEMENTO_WIDGET_NAME: + { + if (cmd->old_name) + free(cmd->old_name); + if (cmd->new_name) + free(cmd->new_name); + break; + } + case MEMENTO_NONE: + { + break; + } + case MEMENTO_ACTION: + { + break; + } + default: + ERR("case - default"); + } + free(cmd); +} + /* Delete Memento Object */ void memento_del(Memento *memento) { EINA_SAFETY_ON_NULL_RETURN(memento); Memento_Command *cmd; - EINA_LIST_FREE(memento->cmds, cmd) - { - switch (cmd->type) - { - case MEMENTO_PROPERTY: - { - /* old_pointer can be NULL only when property was never set. */ - if (cmd->old_property) - prop_unref((Gui_Widget_Property *) cmd->old_property); - if (cmd->new_property) - prop_unref((Gui_Widget_Property *) cmd->new_property); - break; - } - case MEMENTO_CALLBACK: - { - if (cmd->old_callback) - cb_unref((Gui_Widget_Callback *) cmd->old_callback); - if (cmd->new_callback) - cb_unref((Gui_Widget_Callback *) cmd->new_callback); - break; - } - case MEMENTO_CALLBACK_ADD_DEL: - { - if (cmd->old_cb_container) - cb_container_unref((Callback_Container *) cmd->old_cb_container); - if (cmd->new_cb_container) - cb_container_unref((Callback_Container *) cmd->new_cb_container); - break; - } - case MEMENTO_OBJ_CONTAINER_ITEM: - { - if (cmd->old_obj_container) - obj_container_unref((Object_Container *) cmd->old_obj_container); - if (cmd->new_obj_container) - obj_container_unref((Object_Container *) cmd->new_obj_container); - break; - } - case MEMENTO_ITEM_CONTAINER_ITEM: - { - if (cmd->old_item) - item_container_item_unref((Item_Container_Item *) cmd->old_item); - if (cmd->new_item) - item_container_item_unref((Item_Container_Item *) cmd->new_item); - break; - } - case MEMENTO_WIDGET: - case MEMENTO_WIDGET_PARENT: - case MEMENTO_WIDGET_PUBLIC: - { - break; - } - case MEMENTO_WIDGET_NAME: - { - if (cmd->old_name) - free(cmd->old_name); - if (cmd->new_name) - free(cmd->new_name); - break; - } - case MEMENTO_NONE: - { - break; - } - case MEMENTO_ACTION: - { - break; - } - default: - ERR("case - default"); - } - free(cmd); - } + EINA_LIST_FREE(memento->cmds, cmd) _cmd_del(cmd); free(memento); } @@ -268,7 +276,32 @@ memento_is_finalized(const Memento *memento) void memento_finalize(Memento *memento) { + Eina_List *itr; + Memento_Command *cmd, *cmd_next; memento->finalized = EINA_TRUE; + Eina_Bool change = EINA_TRUE; + + while (change) + { + change = EINA_FALSE; + EINA_LIST_FOREACH(memento->cmds, itr, cmd) + { + Eina_List *next = eina_list_next(itr); + if (next) + { + cmd_next = eina_list_data_get(next); + if (cmd->type == cmd_next->type && + cmd->eid == cmd_next->eid && + cmd->new_ptr == cmd_next->old_ptr) + { + cmd->new_ptr = cmd_next->new_ptr; + memento->cmds = eina_list_remove_list(memento->cmds, next); + _cmd_del(cmd_next); + change = EINA_TRUE; + } + } + } + } } /* Get last Memento command */ --