efl/legacy/edje/src/lib/edje_program.c

591 lines
13 KiB
C
Raw Normal View History

#include "Edje.h"
#include "edje_private.h"
static double _edje_frametime = 1.0 / 60.0;
int _edje_anim_count = 0;
Ecore_Timer *_edje_timer = NULL;
Evas_List *_edje_animators = NULL;
/* API Routines */
void
edje_frametime_set(double t)
{
if (t == _edje_frametime) return;
_edje_frametime = t;
if (_edje_timer)
{
ecore_timer_del(_edje_timer);
_edje_timer = ecore_timer_add(_edje_frametime, _edje_timer_cb, NULL);
}
}
double
edje_frametime_get(void)
{
return _edje_frametime;
}
void
edje_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
{
Edje *ed;
Edje_Signal_Callback *escb;
if ((!emission) || (!source) || (!func)) return;
ed = _edje_fetch(obj);
if (!ed) return;
escb = calloc(1, sizeof(Edje_Signal_Callback));
escb->signal = strdup(emission);
escb->source = strdup(source);
escb->func = func;
escb->data = data;
ed->callbacks = evas_list_append(ed->callbacks, escb);
if (ed->walking_callbacks)
{
escb->just_added = 1;
ed->just_added_callbacks = 1;
}
}
void *
edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source))
{
Edje *ed;
Evas_List *l;
if ((!emission) || (!source) || (!func)) return NULL;
ed = _edje_fetch(obj);
if (!ed) return;
for (l = ed->callbacks; l; l = l->next)
{
Edje_Signal_Callback *escb;
escb = l->data;
if ((escb->func == func) &&
(!strcmp(escb->signal, emission)) &&
(!strcmp(escb->source, source)))
{
void *data;
data = escb->data;
if (ed->walking_callbacks)
{
escb->delete_me = 1;
ed->delete_callbacks = 1;
}
else
{
ed->callbacks = evas_list_remove_list(ed->callbacks, l);
free(escb->signal);
free(escb->source);
free(escb);
}
return data;
}
}
return NULL;
}
void
edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
{
Edje *ed;
if ((!emission) || (!source)) return;
ed = _edje_fetch(obj);
if (!ed) return;
_edje_emit(ed, (char *)emission, (char *)source);
}
void
edje_object_play_set(Evas_Object *obj, int play)
{
Edje *ed;
double t;
Evas_List *l;
ed = _edje_fetch(obj);
if (!ed) return;
if (play)
{
if (!ed->paused) return;
ed->paused = 0;
t = ecore_time_get() - ed->paused_at;
for (l = ed->actions; l; l = l->next)
{
Edje_Running_Program *runp;
runp = l->data;
runp->start_time += t;
}
}
else
{
if (ed->paused) return;
ed->paused = 1;
ed->paused_at = ecore_time_get();
}
}
int
edje_object_play_get(Evas_Object *obj)
{
Edje *ed;
ed = _edje_fetch(obj);
if (!ed) return 0;
if (ed->paused) return 0;
return 1;
}
void
edje_object_animation_set(Evas_Object *obj, int on)
{
Edje *ed;
Evas_List *l;
ed = _edje_fetch(obj);
if (!ed) return;
ed->no_anim = !on;
_edje_freeze(ed);
if (!on)
{
Evas_List *newl = NULL;
for (l = ed->actions; l; l = l->next)
newl = evas_list_append(newl, l->data);
while (newl)
{
Edje_Running_Program *runp;
runp = newl->data;
newl = evas_list_remove(newl, newl->data);
_edje_program_run_iterate(runp, runp->start_time + runp->program->tween.time);
}
}
else
{
_edje_emit(ed, "load", "");
if (evas_object_visible_get(obj))
{
evas_object_hide(obj);
evas_object_show(obj);
}
}
_edje_thaw(ed);
}
int
edje_object_animation_get(Evas_Object *obj)
{
Edje *ed;
ed = _edje_fetch(obj);
if (!ed) return 0;
if (ed->no_anim) return 0;
return 1;
}
/* Private Routines */
int
_edje_program_run_iterate(Edje_Running_Program *runp, double tim)
{
double t, total;
Evas_List *l;
_edje_ref(runp->edje);
_edje_freeze(runp->edje);
t = tim - runp->start_time;
total = runp->program->tween.time;
t /= total;
if (t > 1.0) t = 1.0;
for (l = runp->program->targets; l; l = l->next)
{
Edje_Real_Part *rp;
Edje_Program_Target *pt;
pt = l->data;
rp = evas_list_nth(runp->edje->parts, pt->id);
if (rp) _edje_part_pos_set(runp->edje, rp,
runp->program->tween.mode, t);
}
if (t >= 1.0)
{
for (l = runp->program->targets; l; l = l->next)
{
Edje_Real_Part *rp;
Edje_Program_Target *pt;
pt = l->data;
rp = evas_list_nth(runp->edje->parts, pt->id);
if (rp)
{
_edje_part_description_apply(runp->edje, rp,
runp->program->state,
runp->program->value,
NULL,
0.0);
_edje_part_pos_set(runp->edje, rp,
runp->program->tween.mode, 0.0);
rp->program = NULL;
}
}
_edje_recalc(runp->edje);
_edje_anim_count--;
runp->edje->actions = evas_list_remove(runp->edje->actions, runp);
if (!runp->edje->actions)
_edje_animators = evas_list_remove(_edje_animators, runp->edje);
_edje_emit(runp->edje, "program,stop", runp->program->name);
if (runp->program->after >= 0)
{
Edje_Program *pr;
pr = evas_list_nth(runp->edje->collection->programs,
runp->program->after);
if (pr) _edje_program_run(runp->edje, pr, 0);
}
_edje_thaw(runp->edje);
_edje_unref(runp->edje);
free(runp);
return 0;
}
_edje_recalc(runp->edje);
_edje_thaw(runp->edje);
_edje_unref(runp->edje);
return 1;
}
void
_edje_program_end(Edje *ed, Edje_Running_Program *runp)
{
Evas_List *l;
_edje_ref(runp->edje);
_edje_freeze(runp->edje);
for (l = runp->program->targets; l; l = l->next)
{
Edje_Real_Part *rp;
Edje_Program_Target *pt;
pt = l->data;
rp = evas_list_nth(runp->edje->parts, pt->id);
if (rp)
{
_edje_part_description_apply(runp->edje, rp,
runp->program->state,
runp->program->value,
NULL,
0.0);
_edje_part_pos_set(runp->edje, rp,
runp->program->tween.mode, 0.0);
rp->program = NULL;
}
}
_edje_recalc(runp->edje);
_edje_anim_count--;
runp->edje->actions = evas_list_remove(runp->edje->actions, runp);
if (!runp->edje->actions)
_edje_animators = evas_list_remove(_edje_animators, runp->edje);
_edje_emit(runp->edje, "program,stop", runp->program->name);
_edje_thaw(runp->edje);
_edje_unref(runp->edje);
free(runp);
}
void
_edje_program_run(Edje *ed, Edje_Program *pr, int force)
{
Evas_List *l;
/* limit self-feeding loops in programs to 64 levels */
static int recursions = 0;
static int recursion_limit = 0;
if ((pr->in.from != 0.0) && (pr->in.range != 0.0) && (!force))
{
Edje_Pending_Program *pp;
double r;
pp = calloc(1, sizeof(Edje_Pending_Program));
if (!pp) return;
if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
_edje_pending_timer_cb, pp);
if (!pp->timer)
{
free(pp);
return;
}
pp->edje = ed;
pp->program = pr;
ed->pending_actions = evas_list_append(ed->pending_actions, pp);
return;
}
if ((recursions >= 64) || (recursion_limit))
{
recursion_limit = 1;
return;
}
recursions++;
_edje_freeze(ed);
_edje_ref(ed);
if (pr->action == EDJE_ACTION_TYPE_STATE_SET)
{
if ((pr->tween.time > 0.0) && (!ed->no_anim))
{
Edje_Running_Program *runp;
runp = calloc(1, sizeof(Edje_Running_Program));
for (l = pr->targets; l; l = l->next)
{
Edje_Real_Part *rp;
Edje_Program_Target *pt;
pt = l->data;
rp = evas_list_nth(ed->parts, pt->id);
if (rp)
{
if (rp->program)
_edje_program_end(ed, rp->program);
_edje_part_description_apply(ed, rp,
rp->param1.description->state.name,
rp->param1.description->state.value,
pr->state,
pr->value);
_edje_part_pos_set(ed, rp, pr->tween.mode, 0.0);
rp->program = runp;
}
}
_edje_emit(ed, "program,start", pr->name);
if (!ed->actions)
_edje_animators = evas_list_append(_edje_animators, ed);
ed->actions = evas_list_append(ed->actions, runp);
runp->start_time = ecore_time_get();
runp->edje = ed;
runp->program = pr;
if (!_edje_timer)
_edje_timer = ecore_timer_add(_edje_frametime, _edje_timer_cb, NULL);
_edje_anim_count++;
}
else
{
for (l = pr->targets; l; l = l->next)
{
Edje_Real_Part *rp;
Edje_Program_Target *pt;
pt = l->data;
rp = evas_list_nth(ed->parts, pt->id);
if (rp)
{
if (rp->program)
_edje_program_end(ed, rp->program);
_edje_part_description_apply(ed, rp,
pr->state,
pr->value,
NULL,
0.0);
_edje_part_pos_set(ed, rp, pr->tween.mode, 0.0);
}
}
_edje_emit(ed, "program,start", pr->name);
_edje_emit(ed, "program,stop", pr->name);
_edje_recalc(ed);
}
}
else if (pr->action == EDJE_ACTION_TYPE_ACTION_STOP)
{
_edje_emit(ed, "program,start", pr->name);
for (l = pr->targets; l; l = l->next)
{
Edje_Program_Target *pt;
Evas_List *ll;
pt = l->data;
for (ll = ed->actions; ll; ll = ll->next)
{
Edje_Running_Program *runp;
runp = ll->data;
if (pt->id == runp->program->id)
{
_edje_program_end(ed, runp);
break;
}
}
}
_edje_emit(ed, "program,stop", pr->name);
}
else if (pr->action == EDJE_ACTION_TYPE_SIGNAL_EMIT)
{
_edje_emit(ed, "program,start", pr->name);
_edje_emit(ed, pr->state, pr->state2);
_edje_emit(ed, "program,start", pr->name);
}
_edje_unref(ed);
_edje_thaw(ed);
recursions--;
if (recursions == 0) recursion_limit = 0;
}
void
_edje_emit(Edje *ed, char *sig, char *src)
{
Evas_List *l;
static Evas_List *emissions = NULL;
Edje_Emission *ee;
/* limit self-feeding loops in callbacks to 64 levels */
static int recursions = 0;
static int recursion_limit = 0;
if ((recursions >= 64) || (recursion_limit))
{
recursion_limit = 1;
return;
}
recursions++;
_edje_ref(ed);
_edje_freeze(ed);
2003-07-29 19:58:22 -07:00
// printf("EMIT \"%s\" \"%s\"\n", sig, src);
ee = calloc(1, sizeof(Edje_Emission));
if (!ee)
{
recursions--;
if (recursions == 0) recursion_limit = 0;
return;
}
ee->signal = strdup(sig);
ee->source = strdup(src);
if (emissions)
{
emissions = evas_list_append(emissions, ee);
_edje_thaw(ed);
_edje_unref(ed);
recursions--;
if (recursions == 0) recursion_limit = 0;
return;
}
else
emissions = evas_list_append(emissions, ee);
while (emissions)
{
ee = emissions->data;
emissions = evas_list_remove(emissions, ee);
if (ed->collection)
{
Edje_Part_Collection *ec;
char *tmps;
int l1, l2;
int done;
ec = ed->collection;
l1 = strlen(ee->signal);
l2 = strlen(ee->source);
tmps = malloc(l1 + l2 + 2);
if (tmps)
{
strcpy(tmps, ee->signal);
tmps[l1] = '\377';
strcpy(&(tmps[l1 + 1]), ee->source);
}
done = 0;
if (tmps)
{
Evas_List *matches;
if (evas_hash_find(ec->prog_cache.no_matches, tmps))
done = 1;
else if ((matches = evas_hash_find(ec->prog_cache.matches, tmps)))
{
for (l = matches; l; l = l->next)
{
Edje_Program *pr;
pr = l->data;
_edje_program_run(ed, pr, 0);
}
done = 1;
}
}
if (!done)
{
int matched = 0;
Evas_List *matches = NULL;
for (l = ed->collection->programs; l; l = l->next)
{
Edje_Program *pr;
pr = l->data;
if ((pr->signal) &&
(pr->source) &&
(_edje_glob_match(ee->signal, pr->signal)) &&
(_edje_glob_match(ee->source, pr->source)))
{
matched++;
_edje_program_run(ed, pr, 0);
matches = evas_list_append(matches, pr);
}
}
if (tmps)
{
if (matched == 0)
ec->prog_cache.no_matches =
evas_hash_add(ec->prog_cache.no_matches, tmps, ed);
else
ec->prog_cache.matches =
evas_hash_add(ec->prog_cache.matches, tmps, matches);
}
}
if (tmps) free(tmps);
ed->walking_callbacks = 1;
for (l = ed->callbacks; l; l = l->next)
{
Edje_Signal_Callback *escb;
escb = l->data;
if ((!escb->just_added) &&
(!escb->delete_me) &&
(_edje_glob_match(ee->signal, escb->signal)) &&
(_edje_glob_match(ee->source, escb->source)))
escb->func(escb->data, ed->obj, ee->signal, ee->source);
}
ed->walking_callbacks = 0;
if ((ed->delete_callbacks) || (ed->just_added_callbacks))
{
ed->delete_callbacks = 0;
ed->just_added_callbacks = 0;
for (l = ed->callbacks; l;)
{
Edje_Signal_Callback *escb;
Evas_List *next_l;
escb = l->data;
next_l = l->next;
if (escb->just_added)
escb->just_added = 0;
if (escb->delete_me)
{
ed->callbacks = evas_list_remove_list(ed->callbacks, l);
free(escb->signal);
free(escb->source);
free(escb);
}
l = next_l;
}
}
}
free(ee->signal);
free(ee->source);
free(ee);
}
_edje_thaw(ed);
_edje_unref(ed);
recursions--;
if (recursions == 0) recursion_limit = 0;
}