Adding a transition layout animation for edje box.

Perform an animation when changing the layout from an edje box.

By: Otavio Pontes <otavio@profusion.mobi>

-------

Sample EDC:

{{{

collections {
   group {
      name: "main";
      min: 500 500;
      max: 500 500;
      parts {
         part {
            name: "bg";
            type: RECT;
            description {
               color: 255 255 255 255;
               rel1 { relative: 0.0 0.0; }
               rel2 { relative: 1.0 1.0; }
            }
         }
         part {
            name: "box1";
            type: BOX;
            description {
               state: "default" 0.0;
               box {
                  layout: vertical;
                  padding: 0 0;
               }
               rel1 {
                  relative: 0.0 0.0;
               }
               rel2 {
                  relative: 1.0 1.0;
               }
            }
            description {
               state: "default" 0.1;
               inherit: "default" 0.0;
               box {
                  padding: 10 10;
                  layout: horizontal;
               }
            }
            description {
               state: "default" 0.2;
               inherit: "default" 0.0;
               box {
                  layout: vertical;
               }
               rel1 {
                  relative: 0.0 0.0;
                  offset: 100 100;
               }
               rel2 {
                  relative: 1.0 1.0;
               }
            }
            box {
               items {
                  item {
                     name: "rect1";
                     type: GROUP;
                     source: "grp_rect1";
                     weight: 1.0 1.0;
                     align: -1 -1;
                  }
                  item {
                     name: "rect2";
                     type: GROUP;
                     source: "grp_rect2";
                     weight: 1.0 1.0;
                     align: -1 -1;
                  }
               }
            }
         }
      }
      programs {
         program {
            name: "change_layout";
            signal: "mouse,clicked,1";
            source: "box1";
            action: STATE_SET "default" 0.1;
            target: "box1";
            transition: LINEAR 5.0;
            after: "change_back";
         }
         program {
            name: "change_back";
            action: STATE_SET "default" 0.2;
            target: "box1";
            transition: LINEAR 5.0;
         }
     }
   }
   group {
      name: "grp_rect1";
      parts {
         part {
            name: "r1";
            type: RECT;
            description {
               state: "default" 0.0;
               color: 255 0 0 255;
               rel1 { relative: 0.0 0.0; }
               rel2 { relative: 1.0 1.0; }
            }
            description {
               state: "default" 0.1;
               inherit: "default" 0.0;
               color: 255 0 0 255;
            }
         }
      }
   }
   group {
      name: "grp_rect2";
      parts {
         part {
            name: "r2";
            type: RECT;
            description {
               state: "default" 0.0;
               color: 0 255 0 255;
               rel1 { relative: 0.0 0.0; }
               rel2 { relative: 1.0 1.0; }
            }
            description {
               state: "default" 0.1;
               color: 0 0 255 255;
            }
         }
      }
   }
}

}}}



SVN revision: 52871
This commit is contained in:
Gustavo Sverzut Barbieri 2010-09-29 00:28:54 +00:00
parent 0667809063
commit abc87fd449
6 changed files with 272 additions and 37 deletions

View File

@ -20,6 +20,7 @@ includes_HEADERS = Edje.h Edje_Edit.h
includesdir = $(includedir)/edje-@VMAJ@
base_sources = \
edje_box_layout.c \
edje_cache.c \
edje_calc.c \
edje_callbacks.c \

View File

@ -0,0 +1,231 @@
#include "edje_private.h"
typedef struct _Edje_Transition_Animation_Data Edje_Transition_Animation_Data;
struct _Edje_Transition_Animation_Data
{
Evas_Object *obj;
struct
{
Evas_Coord x, y, w, h;
} start, end;
};
struct _Edje_Part_Box_Animation
{
struct
{
Evas_Object_Box_Layout layout;
void *data;
void(*free_data)(void *data);
Edje_Alignment align;
Evas_Point padding;
} start, end;
Eina_List *objs;
Eina_Bool recalculate:1;
Evas_Object *box;
double progress;
double start_progress;
int box_start_w, box_start_h;
};
static void
_edje_box_layout_find_all(const char *name, const char *name_alt, Evas_Object_Box_Layout *cb, void **data, void (**free_data)(void *data))
{
if (!_edje_box_layout_find(name, cb, data, free_data))
{
if ((!name_alt) ||
(!_edje_box_layout_find(name_alt, cb, data, free_data)))
{
ERR("box layout '%s' (fallback '%s') not available, using horizontal.",
name, name_alt);
*cb = evas_object_box_layout_horizontal;
*free_data = NULL;
*data = NULL;
}
}
}
static void
_edje_box_layout_calculate_coords(Evas_Object *obj, Evas_Object_Box_Data *priv, Edje_Part_Box_Animation *anim)
{
Eina_List *l;
Edje_Transition_Animation_Data *tad;
Evas_Coord x, y;
evas_object_geometry_get(obj, &x, &y, &anim->box_start_w, &anim->box_start_h);
EINA_LIST_FOREACH(anim->objs, l, tad)
{
evas_object_geometry_get(tad->obj, &tad->start.x, &tad->start.y,
&tad->start.w, &tad->start.h);
tad->start.x = tad->start.x - x;
tad->start.y = tad->start.y - y;
}
evas_object_box_padding_set(obj, anim->end.padding.x, anim->end.padding.y);
evas_object_box_align_set(obj, TO_DOUBLE(anim->end.align.x), TO_DOUBLE(anim->end.align.y));
anim->end.layout(obj, priv, anim->end.data);
EINA_LIST_FOREACH(anim->objs, l, tad)
{
evas_object_geometry_get(tad->obj, &tad->end.x, &tad->end.y,
&tad->end.w, &tad->end.h);
tad->end.x = tad->end.x - x;
tad->end.y = tad->end.y - y;
}
}
static void
_edje_box_layout_exec(Evas_Object *obj, Edje_Part_Box_Animation *anim)
{
Eina_List *l;
Edje_Transition_Animation_Data *tad;
Evas_Coord x, y, w, h;
Evas_Coord cur_x, cur_y, cur_w, cur_h;
evas_object_geometry_get(obj, &x, &y, &w, &h);
double progress = (anim->progress - anim->start_progress) / (1 - anim->start_progress);
EINA_LIST_FOREACH(anim->objs, l, tad)
{
cur_x = x + (tad->start.x + ((tad->end.x - tad->start.x) * progress)) * (w / (double)anim->box_start_w);
cur_y = y + (tad->start.y + ((tad->end.y - tad->start.y) * progress)) * (h / (double)anim->box_start_h);
cur_w = (w / (double)anim->box_start_w) * (tad->start.w + ((tad->end.w - tad->start.w) * progress));
cur_h = (h / (double)anim->box_start_h) * (tad->start.h + ((tad->end.h - tad->start.h) * progress));
evas_object_move(tad->obj, cur_x, cur_y);
evas_object_resize(tad->obj, cur_w, cur_h);
}
}
static void
_edje_box_layout(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data)
{
Edje_Part_Box_Animation *anim = data;
if (anim->progress < 0.01)
{
evas_object_box_padding_set(obj, anim->start.padding.x, anim->start.padding.y);
evas_object_box_align_set(obj, TO_DOUBLE(anim->start.align.x), TO_DOUBLE(anim->start.align.y));
anim->start.layout(obj, priv, anim->start.data);
return;
}
if (anim->recalculate)
{
_edje_box_layout_calculate_coords(obj, priv, anim);
anim->start_progress = anim->progress;
anim->recalculate = EINA_FALSE;
}
if ((anim->progress > 0) && (anim->start_progress < 1))
_edje_box_layout_exec(obj, anim);
}
void
_edje_box_layout_free_data(void *data)
{
Edje_Transition_Animation_Data *tad;
Edje_Part_Box_Animation *anim = data;
if (anim->start.free_data && anim->start.data)
anim->start.free_data(anim->start.data);
if (anim->end.free_data && anim->end.data)
anim->end.free_data(anim->end.data);
EINA_LIST_FREE(anim->objs, tad)
free(tad);
free(data);
}
Edje_Part_Box_Animation *
_edje_box_layout_anim_new(Evas_Object *box)
{
Edje_Part_Box_Animation *anim = calloc(1, sizeof(Edje_Part_Box_Animation));
if (!anim)
return NULL;
anim->box = box;
evas_object_box_layout_set(box, _edje_box_layout, anim, NULL);
return anim;
}
void
_edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc)
{
Evas_Object_Box_Data *priv;
int min_w, min_h;
if ((ep->param2) && (ep->description_pos != ZERO))
{
Edje_Part_Description_Box *param2_desc = (Edje_Part_Description_Box *)ep->param2->description;
if (ep->anim->end.layout == NULL)
{
_edje_box_layout_find_all(param2_desc->box.layout, param2_desc->box.alt_layout, &ep->anim->end.layout, &ep->anim->end.data, &ep->anim->end.free_data);
ep->anim->end.padding.x = param2_desc->box.padding.x;
ep->anim->end.padding.y = param2_desc->box.padding.y;
ep->anim->end.align.x = param2_desc->box.align.x;
ep->anim->end.align.y = param2_desc->box.align.y;
priv = evas_object_smart_data_get(ep->object);
if (priv == NULL)
return;
evas_object_box_padding_set(ep->object, ep->anim->start.padding.x, ep->anim->start.padding.y);
evas_object_box_align_set(ep->object, TO_DOUBLE(ep->anim->start.align.x), TO_DOUBLE(ep->anim->start.align.y));
ep->anim->start.layout(ep->object, priv, ep->anim->start.data);
_edje_box_layout_calculate_coords(ep->object, priv, ep->anim);
ep->anim->start_progress = 0.0;
}
evas_object_smart_changed(ep->object);
}
else {
ep->anim->end.layout = NULL;
}
if (ep->description_pos < 0.01 || !ep->anim->start.layout)
{
_edje_box_layout_find_all(chosen_desc->box.layout, chosen_desc->box.alt_layout, &ep->anim->start.layout, &ep->anim->start.data, &ep->anim->start.free_data);
ep->anim->start.padding.x = chosen_desc->box.padding.x;
ep->anim->start.padding.y = chosen_desc->box.padding.y;
ep->anim->start.align.x = chosen_desc->box.align.x;
ep->anim->start.align.y = chosen_desc->box.align.y;
evas_object_smart_changed(ep->object);
}
ep->anim->progress = ep->description_pos;
if (evas_object_smart_need_recalculate_get(ep->object))
{
evas_object_smart_need_recalculate_set(ep->object, 0);
evas_object_smart_calculate(ep->object);
}
evas_object_size_hint_min_get(ep->object, &min_w, &min_h);
if (chosen_desc->box.min.h && (p3->w < min_w))
p3->w = min_w;
if (chosen_desc->box.min.v && (p3->h < min_h))
p3->h = min_h;
}
Eina_Bool
_edje_box_layout_add_child(Edje_Real_Part *rp, Evas_Object *child_obj)
{
Edje_Transition_Animation_Data *tad;
tad = calloc(1, sizeof(Edje_Transition_Animation_Data));
if (!tad)
return EINA_FALSE;
tad->obj = child_obj;
rp->anim->objs = eina_list_append(rp->anim->objs, tad);
rp->anim->recalculate = EINA_TRUE;
return EINA_TRUE;
}
void
_edje_box_layout_remove_child(Edje_Real_Part *rp, Evas_Object *child_obj)
{
Eina_List *l;
Edje_Transition_Animation_Data *tad;
EINA_LIST_FOREACH(rp->anim->objs, l, tad)
{
if (tad->obj == child_obj)
{
free(eina_list_data_get(l));
rp->anim->objs = eina_list_remove_list(rp->anim->objs, l);
rp->anim->recalculate = EINA_TRUE;
}
}
rp->anim->recalculate = EINA_TRUE;
}

View File

@ -1419,43 +1419,6 @@ _edje_part_recalc_single(Edje *ed,
}
}
static void
_edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc)
{
Evas_Object_Box_Layout layout;
void (*free_data)(void *data);
void *data;
int min_w, min_h;
if (!_edje_box_layout_find(chosen_desc->box.layout, &layout, &data, &free_data))
{
if ((!chosen_desc->box.alt_layout) ||
(!_edje_box_layout_find(chosen_desc->box.alt_layout, &layout, &data, &free_data)))
{
ERR("box layout '%s' (fallback '%s') not available, using horizontal.",
chosen_desc->box.layout, chosen_desc->box.alt_layout);
layout = evas_object_box_layout_horizontal;
free_data = NULL;
data = NULL;
}
}
evas_object_box_layout_set(ep->object, layout, data, free_data);
evas_object_box_align_set(ep->object, TO_DOUBLE(chosen_desc->box.align.x), TO_DOUBLE(chosen_desc->box.align.y));
evas_object_box_padding_set(ep->object, chosen_desc->box.padding.x, chosen_desc->box.padding.y);
if (evas_object_smart_need_recalculate_get(ep->object))
{
evas_object_smart_need_recalculate_set(ep->object, 0);
evas_object_smart_calculate(ep->object);
}
evas_object_size_hint_min_get(ep->object, &min_w, &min_h);
if (chosen_desc->box.min.h && (p3->w < min_w))
p3->w = min_w;
if (chosen_desc->box.min.v && (p3->h < min_h))
p3->h = min_h;
}
static void
_edje_table_recalc_apply(Edje *ed __UNUSED__,
Edje_Real_Part *ep,

View File

@ -455,6 +455,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
break;
case EDJE_PART_TYPE_BOX:
rp->object = evas_object_box_add(ed->evas);
rp->anim = _edje_box_layout_anim_new(rp->object);
break;
case EDJE_PART_TYPE_TABLE:
rp->object = evas_object_table_add(ed->evas);
@ -971,6 +972,11 @@ _edje_file_del(Edje *ed)
/* evas_box/table handles deletion of objects */
rp->items = eina_list_free(rp->items);
}
if (rp->anim)
{
_edje_box_layout_free_data(rp->anim);
rp->anim = NULL;
}
if (rp->text.text) eina_stringshare_del(rp->text.text);
if (rp->text.font) eina_stringshare_del(rp->text.font);
if (rp->text.cache.in_str) eina_stringshare_del(rp->text.cache.in_str);

View File

@ -289,6 +289,7 @@ typedef struct _Edje_Part_Description_Spec_Text Edje_Part_Description_Spec_
typedef struct _Edje_Part_Description_Spec_Box Edje_Part_Description_Spec_Box;
typedef struct _Edje_Part_Description_Spec_Table Edje_Part_Description_Spec_Table;
typedef struct _Edje_Patterns Edje_Patterns;
typedef struct _Edje_Part_Box_Animation Edje_Part_Box_Animation;
#define EDJE_INF_MAX_W 100000
#define EDJE_INF_MAX_H 100000
@ -1108,6 +1109,7 @@ struct _Edje_Real_Part
Edje_Rectangle req; // 16
Eina_List *items; // 4 //FIXME: only if table/box
Edje_Part_Box_Animation *anim; // 4 //FIXME: Used only if box
void *entry_data; // 4 // FIXME: move to entry section
Evas_Object *cursorbg_object; // 4 // FIXME: move to entry section
Evas_Object *cursorfg_object; // 4 // FIXME: move to entry section
@ -1519,6 +1521,11 @@ void _edje_real_part_swallow_clear(Edje_Real_Part *rp);
void _edje_box_init(void);
void _edje_box_shutdown(void);
Eina_Bool _edje_box_layout_find(const char *name, Evas_Object_Box_Layout *cb, void **data, void (**free_data)(void *data));
void _edje_box_recalc_apply(Edje *ed __UNUSED__, Edje_Real_Part *ep, Edje_Calc_Params *p3, Edje_Part_Description_Box *chosen_desc);
Eina_Bool _edje_box_layout_add_child(Edje_Real_Part *rp, Evas_Object *child_obj);
void _edje_box_layout_remove_child(Edje_Real_Part *rp, Evas_Object *child_obj);
Edje_Part_Box_Animation * _edje_box_layout_anim_new(Evas_Object *box);
void _edje_box_layout_free_data(void *data);
Eina_Bool _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj);
Eina_Bool _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj);

View File

@ -3678,6 +3678,12 @@ _edje_real_part_box_append(Edje_Real_Part *rp, Evas_Object *child_obj)
opt = evas_object_box_append(rp->object, child_obj);
if (!opt) return EINA_FALSE;
if (!_edje_box_layout_add_child(rp, child_obj))
{
evas_object_box_remove(rp->object, child_obj);
return EINA_FALSE;
}
_edje_box_child_add(rp, child_obj);
return EINA_TRUE;
@ -3691,6 +3697,12 @@ _edje_real_part_box_prepend(Edje_Real_Part *rp, Evas_Object *child_obj)
opt = evas_object_box_prepend(rp->object, child_obj);
if (!opt) return EINA_FALSE;
if (!_edje_box_layout_add_child(rp, child_obj))
{
evas_object_box_remove(rp->object, child_obj);
return EINA_FALSE;
}
_edje_box_child_add(rp, child_obj);
return EINA_TRUE;
@ -3704,6 +3716,12 @@ _edje_real_part_box_insert_before(Edje_Real_Part *rp, Evas_Object *child_obj, co
opt = evas_object_box_insert_before(rp->object, child_obj, ref);
if (!opt) return EINA_FALSE;
if (!_edje_box_layout_add_child(rp, child_obj))
{
evas_object_box_remove(rp->object, child_obj);
return EINA_FALSE;
}
_edje_box_child_add(rp, child_obj);
return EINA_TRUE;
@ -3717,6 +3735,12 @@ _edje_real_part_box_insert_at(Edje_Real_Part *rp, Evas_Object *child_obj, unsign
opt = evas_object_box_insert_at(rp->object, child_obj, pos);
if (!opt) return EINA_FALSE;
if (!_edje_box_layout_add_child(rp, child_obj))
{
evas_object_box_remove(rp->object, child_obj);
return EINA_FALSE;
}
_edje_box_child_add(rp, child_obj);
return EINA_TRUE;
@ -3727,6 +3751,7 @@ _edje_real_part_box_remove(Edje_Real_Part *rp, Evas_Object *child_obj)
{
if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
if (!evas_object_box_remove(rp->object, child_obj)) return NULL;
_edje_box_layout_remove_child(rp, child_obj);
_edje_box_child_remove(rp, child_obj);
return child_obj;
}
@ -3744,6 +3769,7 @@ _edje_real_part_box_remove_at(Edje_Real_Part *rp, unsigned int pos)
child_obj = opt->obj;
if (evas_object_data_get(child_obj, "\377 edje.box_item")) return NULL;
if (!evas_object_box_remove_at(rp->object, pos)) return NULL;
_edje_box_layout_remove_child(rp, child_obj);
_edje_box_child_remove(rp, child_obj);
return child_obj;
}
@ -3762,6 +3788,7 @@ _edje_real_part_box_remove_all(Edje_Real_Part *rp, Eina_Bool clear)
i++;
else
{
_edje_box_layout_remove_child(rp, child_obj);
_edje_box_child_remove(rp, child_obj);
if (!evas_object_box_remove_at(rp->object, i))
return EINA_FALSE;