edje: fix double opening of edje file.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 18 May 2012 14:37:21 +0000 (14:37 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 18 May 2012 14:37:21 +0000 (14:37 +0000)
NOTE: know issue, in elementary_config the size of the icon
change after a theme reload. I don't know what information is
lost between to reload. If someone can point at them, thanks.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/edje@71235 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/edje_load.c
src/lib/edje_private.h
src/lib/edje_smart.c
src/lib/edje_util.c

index 02cfb96..421aa5c 100644 (file)
@@ -30,10 +30,9 @@ static Eina_Bool  _edje_collection_free_prog_cache_matches_free_cb(const Eina_Ha
 static void _edje_object_pack_item_hints_set(Evas_Object *obj, Edje_Pack_Element *it);
 static void _cb_signal_repeat(void *data, Evas_Object *obj, const char *signal, const char *source);
 
-static Eina_List *_edje_swallows_collect(Edje *ed);
-static Eina_List *_edje_box_items_collect(Edje *ed);
-static Eina_List *_edje_table_items_collect(Edje *ed);
-static Eina_List *_edje_drag_collect(Edje *ed);
+static Eina_List *_edje_object_collect(Edje *ed);
+
+static int _sort_defined_boxes(const void *a, const void *b);
 
 /************************** API Routines **************************/
 
@@ -307,10 +306,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
    Eina_List *textblocks = NULL;
    Eina_List *sources = NULL;
    Eina_List *externals = NULL;
-   Eina_List *old_swallows;
-   Eina_List *old_table_items;
-   Eina_List *old_box_items;
-   Eina_List *old_drag;
+   Eina_List *collect = NULL;
    unsigned int n;
    Eina_List *parts = NULL;
    int group_path_started = 0;
@@ -333,10 +329,8 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
 
    tev = evas_object_evas_get(obj);
    evas_event_freeze(tev);
-   old_swallows = _edje_swallows_collect(ed);
-   old_table_items = _edje_table_items_collect(ed);
-   old_box_items = _edje_box_items_collect(ed);
-   old_drag = _edje_drag_collect(ed);
+
+   collect = _edje_object_collect(ed);
 
    if (_edje_script_only(ed)) _edje_script_only_shutdown(ed);
    if (_edje_lua_script_only(ed)) _edje_lua_script_only_shutdown(ed);
@@ -859,86 +853,68 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
               }
 
             /* reswallow any swallows that existed before setting the file */
-            if (old_swallows)
-              {
-                 while (old_swallows)
-                   {
-                      const char *name;
-                      Evas_Object *swallow;
-
-                      name = eina_list_data_get(old_swallows);
-                      old_swallows = eina_list_remove_list(old_swallows, old_swallows);
-
-                      swallow = eina_list_data_get(old_swallows);
-                      old_swallows = eina_list_remove_list(old_swallows, old_swallows);
-
-                      edje_object_part_swallow(obj, name, swallow);
-                      eina_stringshare_del(name);
-                   }
-              }
-
-             if (old_box_items)
-               {
-                  while (old_box_items)
-                    {
-                       const char *name;
-                       Evas_Object *child;
-
-                       name = eina_list_data_get(old_box_items);
-                       old_box_items = eina_list_remove_list(old_box_items, old_box_items);
-
-                       child = eina_list_data_get(old_box_items);
-                       old_box_items = eina_list_remove_list(old_box_items, old_box_items);
-
-                       edje_object_part_box_append(obj, name, child);
-                       eina_stringshare_del(name);
-                    }
-               }
-
-             if (old_table_items)
+             if (collect)
                {
-                  Edje_Table_Items *item;
+                  Edje_User_Defined *eud;
+                  Eina_List *boxes = NULL;
 
-                  EINA_LIST_FREE(old_table_items, item)
+                  EINA_LIST_FREE(collect, eud)
                     {
-                       edje_object_part_table_pack(obj,
-                                                   item->part, item->child,
-                                                   item->col, item->row,
-                                                   item->colspan, item->rowspan);
-                       eina_stringshare_del(item->part);
-                       free(item);
+                       switch (eud->type)
+                         {
+                          case EDJE_USER_SWALLOW:
+                             edje_object_part_swallow(obj, eud->part, eud->u.swallow.child);
+                             break;
+                          case EDJE_USER_BOX_PACK:
+                             boxes = eina_list_append(boxes, eud);
+                             eud = NULL;
+                             break;
+                          case EDJE_USER_TABLE_PACK:
+                             edje_object_part_table_pack(obj, eud->part, eud->u.table.child,
+                                                         eud->u.table.col, eud->u.table.row,
+                                                         eud->u.table.colspan, eud->u.table.rowspan);
+                             break;
+                          case EDJE_USER_DRAG_STEP:
+                             edje_object_part_drag_step_set(obj, eud->part,
+                                                            eud->u.drag_position.x,
+                                                            eud->u.drag_position.y);
+                             break;
+                          case EDJE_USER_DRAG_PAGE:
+                             edje_object_part_drag_page_set(obj, eud->part,
+                                                            eud->u.drag_position.x,
+                                                            eud->u.drag_position.y);
+                             break;
+                          case EDJE_USER_DRAG_VALUE:
+                             edje_object_part_drag_value_set(obj, eud->part,
+                                                             eud->u.drag_position.x,
+                                                             eud->u.drag_position.y);
+                             break;
+                          case EDJE_USER_DRAG_SIZE:
+                             edje_object_part_drag_size_set(obj, eud->part,
+                                                            eud->u.drag_size.w,
+                                                            eud->u.drag_size.h);
+                             break;
+                          case EDJE_USER_STRING:
+                             edje_object_part_text_set(obj, eud->part, eud->u.string.text);
+                             eina_stringshare_del(eud->u.string.text);
+                             break;
+                         }
+                       _edje_user_definition_free(eud);
                     }
-               }
 
-             if (old_drag)
-               {
-                  Edje_Drag_Items *drag;
-
-                  EINA_LIST_FREE(old_drag, drag)
+                  boxes = eina_list_sort(boxes, -1, _sort_defined_boxes);
+                  EINA_LIST_FREE(boxes, eud)
                     {
-                       Edje_Real_Part *drp;
-
-                       drp = _edje_real_part_recursive_get(ed, drag->part);
-                       if (!drp || !drp->drag) goto next;
-
-                       drp->drag->val.x = drag->x;
-                       drp->drag->val.y = drag->y;
-                       drp->drag->size.x = drag->w;
-                       drp->drag->size.y = drag->h;
-                       /* drp->drag->step.x = drag->step.x; */
-                       /* drp->drag->step.y = drag->step.y; */
-                       drp->drag->page.x = drag->page.x;
-                       drp->drag->page.y = drag->page.y;
-
-                       _edje_dragable_pos_set(drp->edje, drp, drp->drag->val.x, drp->drag->val.y);
-                       _edje_emit(drp->edje, "drag,set", drp->part->name);
-
-                    next:
-                       eina_stringshare_del(drag->part);
-                       free(drag);
+                       edje_object_part_box_append(obj, eud->part, eud->u.box.child);
+                       _edje_user_definition_free(eud);
                     }
                }
 
+             if (edje_object_mirrored_get(obj))
+               edje_object_signal_emit(obj, "edje,state,rtl", "edje");
+             else
+               edje_object_signal_emit(obj, "edje,state,ltr", "edje");
+
             _edje_recalc(ed);
             _edje_thaw(ed);
             _edje_unblock(ed);
@@ -1010,135 +986,95 @@ _edje_file_add(Edje *ed)
      }
 }
 
-static Eina_List *
-_edje_swallows_collect(Edje *ed)
+static int
+_sort_defined_boxes(const void *a, const void *b)
 {
-   Eina_List *swallows = NULL;
-   unsigned int i;
-
-   if (!ed->file || !ed->table_parts) return NULL;
-   for (i = 0; i < ed->table_parts_size; i++)
-     {
-       Edje_Real_Part *rp;
+   const Edje_User_Defined *euda = a;
+   const Edje_User_Defined *eudb = b;
 
-       rp = ed->table_parts[i];
-       if (rp->part->type != EDJE_PART_TYPE_SWALLOW || !rp->swallowed_object) continue;
-       swallows = eina_list_append(swallows, eina_stringshare_add(rp->part->name));
-       swallows = eina_list_append(swallows, rp->swallowed_object);
-     }
-   return swallows;
+   if (euda->part - eudb->part != 0)
+     return euda->part - eudb->part;
+   return euda->u.box.index - eudb->u.box.index;
 }
 
 static Eina_List *
-_edje_table_items_collect(Edje *ed)
+_edje_object_collect(Edje *ed)
 {
-   Eina_List *items = NULL;
-   unsigned int i;
-
-   if (!ed->file || !ed->table_parts) return NULL;
-   for (i = 0; i < ed->table_parts_size; i++)
-     {
-        Edje_Real_Part *rp;
-        Eina_List *children;
-        Evas_Object *child;
+   Edje_User_Defined *eud;
+   Eina_List *collect;
+   Eina_List *l;
 
-        rp = ed->table_parts[i];
-        if (rp->part->type != EDJE_PART_TYPE_TABLE) continue ;
+   collect = ed->user_defined;
+   ed->user_defined = NULL;
 
-        children = evas_object_table_children_get(rp->object);
-        EINA_LIST_FREE(children, child)
-          if (!evas_object_data_get(child, "\377 edje.table_item"))
-            {
-               Edje_Table_Items *n;
-
-               n = malloc(sizeof (Edje_Table_Items));
-               if (!n) continue ;
-
-               evas_object_table_pack_get(rp->object, child,
-                                          &n->col, &n->row,
-                                          &n->colspan, &n->rowspan);
-               n->child = child;
-               n->part = eina_stringshare_add(rp->part->name);
-
-               _edje_real_part_table_unpack(rp, child);
-
-               items = eina_list_append(items, n);
-            }
-     }
-
-   return items;
-}
-
-static Eina_List *
-_edje_box_items_collect(Edje *ed)
-{
-   Eina_List *items = NULL;
-   unsigned int i;
-
-   if (!ed->file || !ed->table_parts) return NULL;
-   for (i = 0; i < ed->table_parts_size; i++)
+   EINA_LIST_FOREACH(collect, l, eud)
      {
-        Edje_Real_Part *rp;
-        Eina_List *children;
-        Evas_Object *child;
-
-        rp = ed->table_parts[i];
-        if (rp->part->type != EDJE_PART_TYPE_BOX) continue ;
-
-        children = evas_object_box_children_get(rp->object);
-        EINA_LIST_FREE(children, child)
-          if (!evas_object_data_get(child, "\377 edje.box_item"))
-            {
-               items = eina_list_append(items,
-                                        eina_stringshare_add(rp->part->name));
-               items = eina_list_append(items,
-                                        child);
-               _edje_real_part_box_remove(rp, child);
-            }
-     }
-
-   return items;
-}
-
-static Eina_List *
-_edje_drag_collect(Edje *ed)
-{
-   Eina_List *items = NULL;
-   unsigned int i;
-
-   if (!ed->file || !ed->table_parts) return NULL;
-   for (i = 0; i < ed->table_parts_size; i++)
-     {
-        Edje_Real_Part *rp;
-        Edje_Drag_Items *drag;
-
-        rp = ed->table_parts[i];        
-        if (!rp->drag) continue ;
-
-        drag = calloc(1, sizeof (Edje_Drag_Items));
-        if (!drag) continue;
-
-        drag->part = eina_stringshare_add(rp->part->name);
-        drag->x = rp->drag->val.x;
-        drag->y = rp->drag->val.y;
-        drag->w = rp->drag->size.x;
-        drag->h = rp->drag->size.y;
-        drag->step.x = rp->drag->step.x;
-        drag->step.y = rp->drag->step.y;
-        drag->page.x = rp->drag->page.x;
-        drag->page.y = rp->drag->page.y;
-
-        items = eina_list_append(items, drag);
+        switch (eud->type)
+          {
+           case EDJE_USER_STRING:
+              eud->u.string.text = eina_stringshare_ref(eud->u.string.text);
+              break;
+           case EDJE_USER_BOX_PACK:
+              if (eud->u.box.index == -1)
+                {
+                   Edje_User_Defined *search;
+                   Edje_Real_Part *rp;
+                   Eina_List *children;
+                   Eina_List *ls;
+                   Evas_Object *child;
+                   int idx = 0;
+
+                   rp = _edje_real_part_recursive_get(ed, eud->part);
+                   if (rp->part->type != EDJE_PART_TYPE_BOX) continue ;
+
+                   children = evas_object_box_children_get(rp->object);
+                   EINA_LIST_FREE(children, child)
+                     if (!evas_object_data_get(child, "\377 edje.box_item"))
+                       {
+                          EINA_LIST_FOREACH(l, ls, search)
+                            {
+                               if (search->type == EDJE_USER_BOX_PACK &&
+                                   search->u.box.child == child &&
+                                   search->part == eud->part /* beauty of stringshare ! */)
+                                 {
+                                    search->u.box.index = idx++;
+                                    break;
+                                 }
+                            }
+                          _edje_real_part_box_remove(rp, child);
+                       }
+                }
+              break;
+           case EDJE_USER_TABLE_PACK:
+             {
+                Edje_Real_Part *rp;
+
+                rp = _edje_real_part_recursive_get(ed, eud->part);
+                if (rp->part->type != EDJE_PART_TYPE_TABLE) continue ;
+
+                _edje_real_part_table_unpack(rp, eud->u.table.child);
+                break;
+             }
+           case EDJE_USER_SWALLOW:
+              edje_object_part_unswallow(NULL, eud->u.swallow.child);
+              break;
+           case EDJE_USER_DRAG_STEP:
+           case EDJE_USER_DRAG_PAGE:
+           case EDJE_USER_DRAG_VALUE:
+           case EDJE_USER_DRAG_SIZE:
+              break;
+          }
      }
 
-   return items;
+   return collect;
 }
 
 void
 _edje_file_del(Edje *ed)
 {
+   Edje_User_Defined *eud;
    Evas *tev = evas_object_evas_get(ed->obj);
-   
+
    evas_event_freeze(tev);
    if (ed->freeze_calc)
      {
@@ -1283,6 +1219,13 @@ _edje_file_del(Edje *ed)
             free(pp);
          }
      }
+
+   while (ed->user_defined)
+     {
+        eud = eina_list_data_get(ed->user_defined);
+        _edje_user_definition_free(eud);
+     }
+
    if (ed->L) _edje_lua2_script_shutdown(ed);
    while (ed->subobjs) evas_object_del(ed->subobjs->data);
    if (ed->table_parts) free(ed->table_parts);
index b39e93f..48b4827 100644 (file)
@@ -1159,6 +1159,8 @@ struct _Edje
       void                  *data;
    } item_provider;
 
+   Eina_List            *user_defined;
+
    int                   walking_callbacks;
 
    unsigned int          dirty : 1;
@@ -1547,6 +1549,52 @@ struct _Edje_Patterns
    size_t          finals[];
 };
 
+typedef enum _Edje_User_Defined_Type 
+{
+   EDJE_USER_SWALLOW,
+   EDJE_USER_BOX_PACK,
+   EDJE_USER_TABLE_PACK,
+   EDJE_USER_STRING,
+   EDJE_USER_DRAG_STEP,
+   EDJE_USER_DRAG_PAGE,
+   EDJE_USER_DRAG_VALUE,
+   EDJE_USER_DRAG_SIZE
+} Edje_User_Defined_Type;
+
+typedef struct _Edje_User_Defined Edje_User_Defined;
+struct _Edje_User_Defined
+{
+   Edje_User_Defined_Type type;
+   const char *part;
+   Edje *ed;
+
+   union {
+      struct {
+         const char *text;
+      } string;
+      struct {
+         Evas_Object *child;
+      } swallow;
+      struct {
+         Evas_Object *child;
+         int index;
+      } box;
+      struct {
+         Evas_Object *child;
+         unsigned short col;
+         unsigned short row;
+         unsigned short colspan;
+         unsigned short rowspan;
+      } table;
+      struct {
+         double x, y;
+      } drag_position;
+      struct {
+         double w, h;
+      } drag_size;
+   } u;
+};
+
 Edje_Patterns   *edje_match_collection_dir_init(const Eina_List *lst);
 Edje_Patterns   *edje_match_programs_signal_init(Edje_Program * const *array,
                                                 unsigned int count);
@@ -2073,6 +2121,8 @@ Eina_Bool _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_n
 
 void _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *state);
 
+void _edje_user_definition_free(Edje_User_Defined *eud);
+
 #ifdef HAVE_LIBREMIX
 #include <remix/remix.h>
 #endif
index 59ccc46..2c74c50 100644 (file)
@@ -112,6 +112,7 @@ _edje_smart_add(Evas_Object *obj)
    ed->is_rtl = EINA_FALSE;
    ed->have_objects = 1;
    ed->references = 1;
+   ed->user_defined = NULL;
 
    evas_object_geometry_get(obj, &(ed->x), &(ed->y), &(ed->w), &(ed->h));
    ed->obj = obj;
index 9c217c8..796445f 100644 (file)
@@ -46,9 +46,55 @@ static Eina_Bool _edje_color_class_list_foreach(const Eina_Hash *hash, const voi
 static Eina_Bool _edje_text_class_list_foreach(const Eina_Hash *hash, const void *key, void *data, void *fdata);
 static void _edje_object_image_preload_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
 static void _edje_object_signal_preload_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _edje_user_def_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__);
 
 Edje_Real_Part *_edje_real_part_recursive_get_helper(const Edje *ed, char **path);
 
+static Edje_User_Defined *
+_edje_user_definition_new(Edje_User_Defined_Type type, const char *part, Edje *ed)
+{
+   Edje_User_Defined *eud;
+
+   eud = malloc(sizeof (Edje_User_Defined));
+   if (!eud) return NULL;
+
+   eud->type = type;
+   eud->part = eina_stringshare_add(part);
+   eud->ed = ed;
+   ed->user_defined = eina_list_append(ed->user_defined, eud);
+
+   return eud;
+}
+
+void
+_edje_user_definition_free(Edje_User_Defined *eud)
+{
+   Evas_Object *child = NULL;
+   switch (eud->type)
+     {
+      case EDJE_USER_SWALLOW: child = eud->u.swallow.child; break;
+      case EDJE_USER_BOX_PACK: child = eud->u.box.child; break;
+      case EDJE_USER_TABLE_PACK: child = eud->u.table.child; break;
+      case EDJE_USER_STRING:
+      case EDJE_USER_DRAG_STEP:
+      case EDJE_USER_DRAG_PAGE:
+      case EDJE_USER_DRAG_VALUE:
+      case EDJE_USER_DRAG_SIZE:
+         break;
+     }
+   if (child) evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+   eud->ed->user_defined = eina_list_remove(eud->ed->user_defined, eud);
+   eina_stringshare_del(eud->part);
+   free(eud);
+}
+
+static void
+_edje_user_def_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
+{
+   Edje_User_Defined *eud = data;
+
+   _edje_user_definition_free(eud);
+}
 
 static void
 _edje_class_member_direct_del(const char *class, Edje_List_Refcount *lookup, Eina_Hash *hash)
@@ -1117,11 +1163,38 @@ edje_object_part_text_style_user_peek(const Evas_Object *obj, const char *part)
       return NULL;
 }
 
+static void
+_edje_user_define_string(Edje *ed, const char *part, const char *raw_text)
+{
+   /* NOTE: This one is tricky, text is referenced in rp->text.text for the life of the
+    rp. So on edje_object_file_set, we should first ref it, before destroying the old
+    layout. */
+   Edje_User_Defined *eud;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_STRING && !strcmp(eud->part, part))
+       {
+          if (!raw_text)
+            {
+               _edje_user_definition_free(eud);
+               return ;
+            }
+          eud->u.string.text = raw_text;
+          return ;
+       }
+
+   eud = _edje_user_definition_new(EDJE_USER_STRING, part, ed);
+   if (!eud) return ;
+   eud->u.string.text = raw_text;
+}
+
 EAPI Eina_Bool
 edje_object_part_text_set(Evas_Object *obj, const char *part, const char *text)
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -1129,7 +1202,9 @@ edje_object_part_text_set(Evas_Object *obj, const char *part, const char *text)
    if (!rp) return EINA_FALSE;
    if ((rp->part->type != EDJE_PART_TYPE_TEXT) &&
        (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK)) return EINA_FALSE;
-   return _edje_object_part_text_raw_set(obj, rp, part, text);
+   r = _edje_object_part_text_raw_set(obj, rp, part, text);
+   _edje_user_define_string(ed, part, rp->text.text);
+   return r;
 }
 
 EAPI const char *
@@ -1162,6 +1237,7 @@ edje_object_part_text_escaped_set(Evas_Object *obj, const char *part, const char
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool ret;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -1172,7 +1248,6 @@ edje_object_part_text_escaped_set(Evas_Object *obj, const char *part, const char
         Eina_Strbuf *sbuf;
         char *esc_start = NULL, *esc_end = NULL;
         char *s, *p;
-        Eina_Bool ret;
         
         sbuf = eina_strbuf_new();
         p = (char *)text;
@@ -1220,11 +1295,14 @@ edje_object_part_text_escaped_set(Evas_Object *obj, const char *part, const char
           }
         ret = _edje_object_part_text_raw_set
           (obj, rp, part, eina_strbuf_string_get(sbuf));
+        _edje_user_define_string(ed, part, rp->text.text);
         eina_strbuf_free(sbuf);
         return ret;
      }
    if (rp->part->type != EDJE_PART_TYPE_TEXTBLOCK) return EINA_FALSE;
-   return _edje_object_part_text_raw_set(obj, rp, part, text);
+   ret = _edje_object_part_text_raw_set(obj, rp, part, text);
+   _edje_user_define_string(ed, part, rp->text.text);
+   return ret;
 }
 
 
@@ -1356,6 +1434,7 @@ edje_object_part_text_unescaped_set(Evas_Object *obj, const char *part, const ch
        ret = _edje_object_part_text_raw_set(obj, rp, part, text);
        free(text);
      }
+   _edje_user_define_string(ed, part, rp->text.text);
    return ret;
 }
 
@@ -2343,6 +2422,8 @@ edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_sw
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud = NULL;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -2357,6 +2438,20 @@ edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_sw
    // XXX: by Sachiel, January 21th 2009, 19:30 UTC
    _edje_recalc_do(ed);
 
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_SWALLOW && !strcmp(part, eud->part))
+       {
+          ed->user_defined = eina_list_remove_list(ed->user_defined, l);
+          if (!obj_swallow)
+            {
+               _edje_user_definition_free(eud);
+               l = NULL;
+               eud = NULL;
+               break;
+            }
+          break;
+       }
+
    rp = evas_object_data_get(obj_swallow, "\377 edje.swallowing_part");
    if (rp)
      {
@@ -2376,6 +2471,22 @@ edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_sw
        return EINA_FALSE;
      }
    _edje_real_part_swallow(rp, obj_swallow, EINA_TRUE);
+
+   if (rp->swallowed_object)
+     {
+        if (!eud)
+          {
+             eud = _edje_user_definition_new(EDJE_USER_SWALLOW, part, ed);
+             evas_object_event_callback_add(obj_swallow, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+          }
+        else ed->user_defined = eina_list_append(ed->user_defined, eud);
+          
+        if (eud)
+          {
+             eud->u.swallow.child = obj_swallow;
+          }
+     }
+
    return EINA_TRUE;
 }
 
@@ -2643,7 +2754,7 @@ edje_box_layout_register(const char *name, Evas_Object_Box_Layout func, void *(*
 }
 
 EAPI void
-edje_object_part_unswallow(Evas_Object *obj __UNUSED__, Evas_Object *obj_swallow)
+edje_object_part_unswallow(Evas_Object *obj, Evas_Object *obj_swallow)
 {
    Edje_Real_Part *rp;
 
@@ -2657,8 +2768,33 @@ edje_object_part_unswallow(Evas_Object *obj __UNUSED__, Evas_Object *obj_swallow
        ERR("cannot unswallow part %s: not swallow type!", rp->part->name);
        return;
      }
+
    if (rp->swallowed_object == obj_swallow)
      {
+        Edje_User_Defined *eud;
+        Eina_List *l;
+
+        if (obj)
+          {
+             Edje *ed;
+
+             ed = _edje_fetch(obj);
+             if (!ed && obj)
+               {
+                  ERR("edje_object_part_unswallow called on a non Edje object ('%s').",
+                      evas_object_type_get(obj));
+               }
+             else
+               {
+                  EINA_LIST_FOREACH(ed->user_defined, l, eud)
+                    if (eud->type == EDJE_USER_SWALLOW && eud->u.swallow.child == obj_swallow)
+                      {
+                         _edje_user_definition_free(eud);
+                         break;
+                      }
+               }
+          }
+
        evas_object_smart_member_del(rp->swallowed_object);
        evas_object_event_callback_del_full(rp->swallowed_object,
                                             EVAS_CALLBACK_FREE,
@@ -3064,6 +3200,8 @@ edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, d
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3071,6 +3209,24 @@ edje_object_part_drag_value_set(Evas_Object *obj, const char *part, double dx, d
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
    if (rp->drag->down.count > 0) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_VALUE && !strcmp(part, eud->part))
+       {
+          eud->u.drag_position.x = dx;
+          eud->u.drag_position.y = dy;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_VALUE, part, ed);
+        if (eud)
+          {
+             eud->u.drag_position.x = dx;
+             eud->u.drag_position.y = dy;
+          } 
+     }
+
    if (rp->part->dragable.confine_id != -1)
      {
        dx = CLAMP(dx, 0.0, 1.0);
@@ -3129,12 +3285,32 @@ edje_object_part_drag_size_set(Evas_Object *obj, const char *part, double dw, do
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
    rp = _edje_real_part_recursive_get(ed, part);
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_SIZE && !strcmp(part, eud->part))
+       {
+          eud->u.drag_size.w = dw;
+          eud->u.drag_size.h = dh;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_SIZE, part, ed);
+        if (eud)
+          {
+             eud->u.drag_size.w = dw;
+             eud->u.drag_size.h = dh;
+          } 
+     }
+
    if (dw < 0.0) dw = 0.0;
    else if (dw > 1.0) dw = 1.0;
    if (dh < 0.0) dh = 0.0;
@@ -3185,12 +3361,32 @@ edje_object_part_drag_step_set(Evas_Object *obj, const char *part, double dx, do
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
    rp = _edje_real_part_recursive_get(ed, part);
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_STEP && !strcmp(part, eud->part))
+       {
+          eud->u.drag_position.x = dx;
+          eud->u.drag_position.y = dy;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
+        if (eud)
+          {
+             eud->u.drag_position.x = dx;
+             eud->u.drag_position.y = dy;
+          } 
+     }
+
    if (dx < 0.0) dx = 0.0;
    else if (dx > 1.0) dx = 1.0;
    if (dy < 0.0) dy = 0.0;
@@ -3237,12 +3433,32 @@ edje_object_part_drag_page_set(Evas_Object *obj, const char *part, double dx, do
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
    rp = _edje_real_part_recursive_get(ed, part);
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_PAGE && !strcmp(part, eud->part))
+       {
+          eud->u.drag_position.x = dx;
+          eud->u.drag_position.y = dy;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
+        if (eud)
+          {
+             eud->u.drag_position.x = dx;
+             eud->u.drag_position.y = dy;
+          } 
+     }
+
    if (dx < 0.0) dx = 0.0;
    else if (dx > 1.0) dx = 1.0;
    if (dy < 0.0) dy = 0.0;
@@ -3290,6 +3506,8 @@ edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double
    Edje *ed;
    Edje_Real_Part *rp;
    FLOAT_T px, py;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3297,6 +3515,24 @@ edje_object_part_drag_step(Evas_Object *obj, const char *part, double dx, double
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
    if (rp->drag->down.count > 0) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_STEP && !strcmp(part, eud->part))
+       {
+          eud->u.drag_position.x = dx;
+          eud->u.drag_position.y = dy;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_STEP, part, ed);
+        if (eud)
+          {
+             eud->u.drag_position.x = dx;
+             eud->u.drag_position.y = dy;
+          } 
+     }
+
    px = rp->drag->val.x;
    py = rp->drag->val.y;
    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx),
@@ -3320,6 +3556,8 @@ edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double
    Edje *ed;
    Edje_Real_Part *rp;
    FLOAT_T px, py;
+   Edje_User_Defined *eud;
+   Eina_List *l;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3327,6 +3565,24 @@ edje_object_part_drag_page(Evas_Object *obj, const char *part, double dx, double
    if (!rp) return EINA_FALSE;
    if (!rp->drag) return EINA_FALSE;
    if (rp->drag->down.count > 0) return EINA_FALSE;
+
+   EINA_LIST_FOREACH(ed->user_defined, l, eud)
+     if (eud->type == EDJE_USER_DRAG_PAGE && !strcmp(part, eud->part))
+       {
+          eud->u.drag_position.x = dx;
+          eud->u.drag_position.y = dy;
+          break;
+       }
+   if (!eud)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_DRAG_PAGE, part, ed);
+        if (eud)
+          {
+             eud->u.drag_position.x = dx;
+             eud->u.drag_position.y = dy;
+          } 
+     }
+
    px = rp->drag->val.x;
    py = rp->drag->val.y;
    rp->drag->val.x = ADD(px, MUL(FROM_DOUBLE(dx), MUL(rp->drag->page.x, rp->part->dragable.x)));
@@ -3364,6 +3620,7 @@ edje_object_part_box_append(Evas_Object *obj, const char *part, Evas_Object *chi
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part) || (!child)) return EINA_FALSE;
@@ -3372,7 +3629,20 @@ edje_object_part_box_append(Evas_Object *obj, const char *part, Evas_Object *chi
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
 
-   return _edje_real_part_box_append(rp, child);
+   r = _edje_real_part_box_append(rp, child);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+
+        eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
+        if (!eud) return r;
+        eud->u.box.child = child;
+        eud->u.box.index = -1;
+
+        evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+     }
+   return r;
 }
 
 EAPI Eina_Bool
@@ -3380,6 +3650,7 @@ edje_object_part_box_prepend(Evas_Object *obj, const char *part, Evas_Object *ch
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3388,7 +3659,19 @@ edje_object_part_box_prepend(Evas_Object *obj, const char *part, Evas_Object *ch
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
 
-   return _edje_real_part_box_prepend(rp, child);
+   r = _edje_real_part_box_prepend(rp, child);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+
+        eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
+        if (!eud) return r;
+        eud->u.box.child = child;
+
+        evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+     }
+   return r;
 }
 
 EAPI Eina_Bool
@@ -3396,6 +3679,7 @@ edje_object_part_box_insert_before(Evas_Object *obj, const char *part, Evas_Obje
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3404,7 +3688,19 @@ edje_object_part_box_insert_before(Evas_Object *obj, const char *part, Evas_Obje
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
 
-   return _edje_real_part_box_insert_before(rp, child, reference);
+   r = _edje_real_part_box_insert_before(rp, child, reference);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+
+        eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
+        if (!eud) return r;
+        eud->u.box.child = child;
+
+        evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+     }
+   return r;
 }
 
 EAPI Eina_Bool
@@ -3412,6 +3708,7 @@ edje_object_part_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3420,7 +3717,19 @@ edje_object_part_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
 
-   return _edje_real_part_box_insert_at(rp, child, pos);
+   r = _edje_real_part_box_insert_at(rp, child, pos);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+
+        eud = _edje_user_definition_new(EDJE_USER_BOX_PACK, part, ed);
+        if (!eud) return r;
+        eud->u.box.child = child;
+
+        evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+     }
+   return r;
 }
 
 EAPI Evas_Object *
@@ -3428,6 +3737,7 @@ edje_object_part_box_remove(Evas_Object *obj, const char *part, Evas_Object *chi
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Evas_Object *r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return NULL;
@@ -3436,7 +3746,21 @@ edje_object_part_box_remove(Evas_Object *obj, const char *part, Evas_Object *chi
    if (!rp) return NULL;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
 
-   return _edje_real_part_box_remove(rp, child);
+   r = _edje_real_part_box_remove(rp, child);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+        Eina_List *l;
+
+        EINA_LIST_FOREACH(ed->user_defined, l, eud)
+          if (eud->type == EDJE_USER_BOX_PACK && eud->u.box.child == child && !strcmp(eud->part, part))
+            {
+               _edje_user_definition_free(eud);
+               return r;
+            }
+     }
+   return r;
 }
 
 EAPI Evas_Object *
@@ -3444,6 +3768,7 @@ edje_object_part_box_remove_at(Evas_Object *obj, const char *part, unsigned int
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Evas_Object *r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return NULL;
@@ -3452,7 +3777,21 @@ edje_object_part_box_remove_at(Evas_Object *obj, const char *part, unsigned int
    if (!rp) return NULL;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return NULL;
 
-   return _edje_real_part_box_remove_at(rp, pos);
+   r = _edje_real_part_box_remove_at(rp, pos);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+        Eina_List *l;
+
+        EINA_LIST_FOREACH(ed->user_defined, l, eud)
+          if (eud->type == EDJE_USER_BOX_PACK && eud->u.box.child == r && !strcmp(eud->part, part))
+            {
+               _edje_user_definition_free(eud);
+               return r;
+            }
+     }
+   return r;
 }
 
 EAPI Eina_Bool
@@ -3460,6 +3799,7 @@ edje_object_part_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool cl
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3468,8 +3808,20 @@ edje_object_part_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool cl
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_BOX) return EINA_FALSE;
 
-   return _edje_real_part_box_remove_all(rp, clear);
+   r = _edje_real_part_box_remove_all(rp, clear);
+   if (r)
+     {
+        Edje_User_Defined *eud;
+        Eina_List *ll, *l;
 
+        EINA_LIST_FOREACH_SAFE(ed->user_defined, l, ll, eud)
+          if (eud->type == EDJE_USER_BOX_PACK && !strcmp(eud->part, part))
+            {
+               _edje_user_definition_free(eud);
+               return r;
+            }
+     }
+   return r;
 }
 
 static void
@@ -3705,6 +4057,8 @@ edje_object_part_table_pack(Evas_Object *obj, const char *part, Evas_Object *chi
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Edje_User_Defined *eud;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3713,7 +4067,22 @@ edje_object_part_table_pack(Evas_Object *obj, const char *part, Evas_Object *chi
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
 
-   return _edje_real_part_table_pack(rp, child_obj, col, row, colspan, rowspan);
+   r = _edje_real_part_table_pack(rp, child_obj, col, row, colspan, rowspan);
+
+   if (r)
+     {
+        eud = _edje_user_definition_new(EDJE_USER_TABLE_PACK, part, ed);
+        if (!eud) return r;
+
+        eud->u.table.child = child_obj;
+        eud->u.table.col = col;
+        eud->u.table.row = row;
+        eud->u.table.colspan = colspan;
+        eud->u.table.rowspan = rowspan;
+
+        evas_object_event_callback_add(child_obj, EVAS_CALLBACK_DEL, _edje_user_def_del_cb, eud);
+     }
+   return r;                                   
 }
 
 EAPI Eina_Bool
@@ -3721,6 +4090,7 @@ edje_object_part_table_unpack(Evas_Object *obj, const char *part, Evas_Object *c
 {
    Edje *ed;
    Edje_Real_Part *rp;
+   Eina_Bool r;
 
    ed = _edje_fetch(obj);
    if ((!ed) || (!part)) return EINA_FALSE;
@@ -3729,7 +4099,24 @@ edje_object_part_table_unpack(Evas_Object *obj, const char *part, Evas_Object *c
    if (!rp) return EINA_FALSE;
    if (rp->part->type != EDJE_PART_TYPE_TABLE) return EINA_FALSE;
 
-   return _edje_real_part_table_unpack(rp, child_obj);
+   r = _edje_real_part_table_unpack(rp, child_obj);
+
+   if (r)
+     {
+        Edje_User_Defined *eud;
+        Eina_List *l;
+        
+        EINA_LIST_FOREACH(ed->user_defined, l, eud)
+          if (eud->type == EDJE_USER_TABLE_PACK &&
+              eud->u.table.child == child_obj &&
+              !strcmp(part, eud->part))
+            {
+               _edje_user_definition_free(eud);
+               break;
+            }
+     }
+
+   return r;
 }
 
 EAPI Eina_Bool