Add calculate callback to Evas_Smart_Class.

Some people is using it for some time now without problems, so I'm
adding it to SVN to get some broader use. Remember to recompile ALL
libraries that depend on Evas as it will change the
EVAS_SMART_CLASS_VERSION and old classes will fail to load.

This will also change Edje so it will postpone _edje_recalc() to
render time, calculate() callback, however some methods will force
early recalculation.



SVN revision: 35860
This commit is contained in:
Gustavo Sverzut Barbieri 2008-09-07 01:25:49 +00:00
parent 3deae56fa1
commit 58a49c2f69
10 changed files with 248 additions and 6 deletions

View File

@ -135,6 +135,14 @@ _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, doubl
void
_edje_recalc(Edje *ed)
{
if (ed->postponed) return ;
evas_object_smart_changed(ed->obj);
ed->postponed = 1;
}
void
_edje_recalc_do(Edje *ed)
{
int i;
@ -142,7 +150,8 @@ _edje_recalc(Edje *ed)
if (ed->freeze)
{
ed->recalc = 1;
if (!ed->calc_only) return;
if (!ed->calc_only &&
!ed->postponed) return;
}
for (i = 0; i < ed->table_parts_size; i++)
{
@ -161,6 +170,7 @@ _edje_recalc(Edje *ed)
_edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY);
}
ed->dirty = 0;
ed->postponed = 0;
if (!ed->calc_only) ed->recalc = 0;
}

View File

@ -681,6 +681,7 @@ struct _Edje
unsigned short walking_actions : 1;
unsigned short block_break : 1;
unsigned short delete_me : 1;
unsigned short postponed : 1;
};
struct _Edje_Real_Part
@ -1007,6 +1008,7 @@ void _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, double pos);
Edje_Part_Description *_edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name, double val);
void _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, double v1, const char *d2, double v2);
void _edje_recalc(Edje *ed);
void _edje_recalc_do(Edje *ed);
int _edje_part_dragable_calc(Edje *ed, Edje_Real_Part *ep, double *x, double *y);
void _edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, double x, double y);

View File

@ -13,6 +13,7 @@ static void _edje_smart_hide(Evas_Object * obj);
static void _edje_smart_color_set(Evas_Object * obj, int r, int g, int b, int a);
static void _edje_smart_clip_set(Evas_Object * obj, Evas_Object * clip);
static void _edje_smart_clip_unset(Evas_Object * obj);
static void _edje_smart_calculate(Evas_Object * obj);
static Evas_Smart *_edje_smart = NULL;
@ -45,6 +46,7 @@ edje_object_add(Evas *evas)
_edje_smart_color_set,
_edje_smart_clip_set,
_edje_smart_clip_unset,
_edje_smart_calculate,
NULL
};
_edje_smart = evas_smart_class_new(&sc);
@ -237,3 +239,13 @@ _edje_smart_clip_unset(Evas_Object * obj)
evas_object_clip_unset(ed->clipper);
// _edje_emit(ed, "clip_unset", NULL);
}
static void
_edje_smart_calculate(Evas_Object *obj)
{
Edje *ed;
ed = evas_object_smart_data_get(obj);
if (!ed) return;
_edje_recalc_do(ed);
}

View File

@ -715,6 +715,10 @@ edje_object_part_object_get(const Evas_Object *obj, const char *part)
ed = _edje_fetch(obj);
if ((!ed) || (!part)) return NULL;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp) return NULL;
return rp->object;
@ -748,6 +752,10 @@ edje_object_part_geometry_get(const Evas_Object *obj, const char *part, Evas_Coo
if (h) *h = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -828,6 +836,10 @@ edje_object_part_text_get(const Evas_Object *obj, const char *part)
ed = _edje_fetch(obj);
if ((!ed) || (!part)) return NULL;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp) return NULL;
if (rp->part->type == EDJE_PART_TYPE_TEXT)
@ -855,6 +867,10 @@ edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_sw
ed = _edje_fetch(obj);
if ((!ed) || (!part)) return;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp) return;
if (rp->part->type != EDJE_PART_TYPE_SWALLOW) return;
@ -1021,7 +1037,7 @@ edje_object_part_unswallow(Evas_Object *obj, Evas_Object *obj_swallow)
rp->swallow_params.max.w = 0;
rp->swallow_params.max.h = 0;
rp->edje->dirty = 1;
_edje_recalc(rp->edje);
_edje_recalc_do(rp->edje);
return;
}
}
@ -1039,6 +1055,10 @@ edje_object_part_swallow_get(const Evas_Object *obj, const char *part)
ed = _edje_fetch(obj);
if ((!ed) || (!part)) return NULL;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp) return NULL;
return rp->swallowed_object;
@ -1088,6 +1108,10 @@ edje_object_size_max_get(const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *m
if (maxh) *maxh = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
if (ed->collection->prop.max.w == 0)
{
/* XXX TODO: convert maxw to 0, fix things that break. */
@ -1125,7 +1149,7 @@ edje_object_calc_force(Evas_Object *obj)
ed->dirty = 1;
pf = ed->freeze;
ed->freeze = 0;
_edje_recalc(ed);
_edje_recalc_do(ed);
ed->freeze = pf;
}
@ -1187,7 +1211,7 @@ edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Co
ok = 0;
ed->dirty = 1;
_edje_recalc(ed);
_edje_recalc_do(ed);
if (reset_maxwh)
{
maxw = 0;
@ -1291,6 +1315,10 @@ edje_object_part_state_get(const Evas_Object *obj, const char *part, double *val
if (val_ret) *val_ret = 0;
return "";
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -1335,6 +1363,10 @@ edje_object_part_drag_dir_get(const Evas_Object *obj, const char *part)
ed = _edje_fetch(obj);
if ((!ed) || (!part)) return EDJE_DRAG_DIR_NONE;
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp) return EDJE_DRAG_DIR_NONE;
if ((rp->part->dragable.x) && (rp->part->dragable.y)) return EDJE_DRAG_DIR_XY;
@ -1399,6 +1431,10 @@ edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double
if (dy) *dy = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -1464,6 +1500,10 @@ edje_object_part_drag_size_get(const Evas_Object *obj, const char *part, double
if (dh) *dh = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -1522,6 +1562,10 @@ edje_object_part_drag_step_get(const Evas_Object *obj, const char *part, double
if (dy) *dy = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -1580,6 +1624,10 @@ edje_object_part_drag_page_get(const Evas_Object *obj, const char *part, double
if (dy) *dy = 0;
return;
}
/* Need to recalc before providing the object. */
_edje_recalc_do(ed);
rp = _edje_real_part_recursive_get(ed, (char *)part);
if (!rp)
{
@ -2097,5 +2145,5 @@ _edje_real_part_swallow(Edje_Real_Part *rp, Evas_Object *obj_swallow)
evas_object_precise_is_inside_set(obj_swallow, 1);
rp->edje->dirty = 1;
_edje_recalc(rp->edje);
_edje_recalc_do(rp->edje);
}

View File

@ -1164,6 +1164,7 @@ _smart_init(void)
_smart_color_set,
_smart_clip_set,
_smart_clip_unset,
NULL,
NULL
};
smart = evas_smart_class_new(&sc);

View File

@ -137,7 +137,7 @@ typedef enum _Evas_Aspect_Control
} Evas_Aspect_Control;
#define EVAS_SMART_CLASS_VERSION 1 /** the version you have to put into the version field in the smart class struct */
#define EVAS_SMART_CLASS_VERSION 2 /** the version you have to put into the version field in the smart class struct */
struct _Evas_Smart_Class /** a smart object class */
{
const char *name; /** the string name of the class */
@ -153,6 +153,7 @@ struct _Evas_Smart_Class /** a smart object class */
void (*color_set) (Evas_Object *o, int r, int g, int b, int a); // FIXME: DELETE ME
void (*clip_set) (Evas_Object *o, Evas_Object *clip); // FIXME: DELETE ME
void (*clip_unset) (Evas_Object *o); // FIXME: DELETE ME
void (*calculate) (Evas_Object *o);
const void *data;
};
@ -767,6 +768,11 @@ extern "C" {
EAPI void evas_object_smart_callback_add (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data);
EAPI void *evas_object_smart_callback_del (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info));
EAPI void evas_object_smart_callback_call (Evas_Object *obj, const char *event, void *event_info);
EAPI void evas_object_smart_changed (Evas_Object *obj);
EAPI void evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value);
EAPI Evas_Bool evas_object_smart_need_recalculate_get(Evas_Object *obj);
EAPI void evas_object_smart_calculate (Evas_Object *obj);
/* events */
EAPI void evas_event_freeze (Evas *e);

View File

@ -70,6 +70,7 @@ evas_new(void)
evas_array_setup(&e->pending_objects, 16);
evas_array_setup(&e->obscuring_objects, 16);
evas_array_setup(&e->temporary_objects, 16);
evas_array_setup(&e->calculate_objects, 16);
return e;
}

View File

@ -13,6 +13,7 @@ struct _Evas_Object_Smart
Evas_Object_List *contained;
int walking_list;
Evas_Bool deletions_waiting : 1;
Evas_Bool need_recalculate : 1;
};
struct _Evas_Smart_Callback
@ -436,6 +437,163 @@ evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event
evas_object_smart_callbacks_clear(obj);
}
/**
* Set the need_recalculate flag of given smart object.
*
* If this flag is set then calculate() callback (method) of the given
* smart object will be called, if one is provided, during render phase
* usually evas_render(). After this step, this flag will be automatically
* unset.
*
* If no calculate() is provided, this flag will be left unchanged.
*
* @note just setting this flag will not make scene dirty and evas_render()
* will have no effect. To do that, use evas_object_smart_changed(),
* that will automatically call this function with 1 as parameter.
*
* @param obj the smart object
* @param value if one want to set or unset the need_recalculate flag.
*
* @ingroup Evas_Smart_Object_Group
*/
EAPI void
evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value)
{
Evas_Object_Smart *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
return;
MAGIC_CHECK_END();
value = !!value;
if (o->need_recalculate == value)
return;
o->need_recalculate = value;
if (!obj->smart.smart->smart_class->calculate)
return;
/* XXX: objects can be present multiple times in calculate_objects()
* XXX: after a set-unset-set cycle, but it's not a problem since
* XXX: on _evas_render_call_smart_calculate() will check for the flag
* XXX: and it will be unset after the first.
*/
if (o->need_recalculate)
{
Evas *e;
e = obj->layer->evas;
_evas_array_append(&e->calculate_objects, obj);
}
/* TODO: else, remove from array */
}
/**
* Get the current value of need_recalculate flag.
*
* @note this flag will be unset during the render phase, after calculate()
* is called if one is provided. If no calculate() is provided, then
* the flag will be left unchanged after render phase.
*
* @param obj the smart object
* @return if flag is set or not.
*
* @ingroup Evas_Smart_Object_Group
*/
EAPI Evas_Bool
evas_object_smart_need_recalculate_get(Evas_Object *obj)
{
Evas_Object_Smart *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
return;
MAGIC_CHECK_END();
return o->need_recalculate;
}
/**
* Call user provided calculate() and unset need_calculate.
*
* @param obj the smart object
* @return if flag is set or not.
*
* @ingroup Evas_Smart_Object_Group
*/
EAPI void
evas_object_smart_calculate(Evas_Object *obj)
{
Evas_Object_Smart *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
o = obj->object_data;
MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
return;
MAGIC_CHECK_END();
if (obj->smart.smart->smart_class->calculate)
obj->smart.smart->smart_class->calculate(obj);
o->need_recalculate = 0;
}
/**
* Call calculate() on all smart objects that need_recalculate.
*
* @internal
*/
void
evas_call_smarts_calculate(Evas *e)
{
Evas_Array *calculate;
unsigned int i;
calculate = &e->calculate_objects;
for (i = 0; i < calculate->count; ++i)
{
Evas_Object *obj;
Evas_Object_Smart *o;
obj = _evas_array_get(calculate, i);
if (obj->delete_me)
continue;
o = obj->object_data;
if (o->need_recalculate)
{
obj->smart.smart->smart_class->calculate(obj);
o->need_recalculate = 0;
}
}
evas_array_flush(calculate);
}
/**
* Mark smart object as changed, dirty.
*
* This will inform the scene that it changed and needs to be redraw, also
* setting need_recalculate on the given object.
*
* @see evas_object_smart_need_recalculate_set().
*
* @ingroup Evas_Smart_Object_Group
*/
EAPI void
evas_object_smart_changed(Evas_Object *obj)
{
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
evas_object_change(obj);
evas_object_smart_need_recalculate_set(obj, 1);
}
/* internal calls */
static void
evas_object_smart_callbacks_clear(Evas_Object *obj)

View File

@ -341,6 +341,8 @@ evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char
MAGIC_CHECK_END();
if (!e->changed) return NULL;
evas_call_smarts_calculate(e);
/* Check if the modified object mean recalculating every thing */
if (!e->invalidate)
_evas_render_check_pending_objects(&e->pending_objects, e);

View File

@ -288,6 +288,7 @@ struct _Evas
Evas_Array pending_objects;
Evas_Array obscuring_objects;
Evas_Array temporary_objects;
Evas_Array calculate_objects;
int delete_grabs;
int walking_grabs;
@ -713,6 +714,7 @@ void evas_object_smart_member_lower(Evas_Object *member);
void evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other);
void evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other);
const Evas_Object_List *evas_object_smart_members_get_direct(const Evas_Object *obj);
void evas_call_smarts_calculate(Evas *e);
void *evas_mem_calloc(int size);
void evas_object_event_callback_all_del(Evas_Object *obj);
void evas_object_event_callback_cleanup(Evas_Object *obj);