aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/edje/src/lib/edje_program.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/edje/src/lib/edje_program.c')
-rw-r--r--libraries/edje/src/lib/edje_program.c2090
1 files changed, 2090 insertions, 0 deletions
diff --git a/libraries/edje/src/lib/edje_program.c b/libraries/edje/src/lib/edje_program.c
new file mode 100644
index 0000000..505b6a2
--- /dev/null
+++ b/libraries/edje/src/lib/edje_program.c
@@ -0,0 +1,2090 @@
1#include "edje_private.h"
2
3static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop);
4static void _edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param);
5static void _edje_param_set(Edje_Real_Part *part, const char *param, const char *value);
6
7int _edje_anim_count = 0;
8Ecore_Animator *_edje_timer = NULL;
9Eina_List *_edje_animators = NULL;
10
11
12/*============================================================================*
13 * API *
14 *============================================================================*/
15
16EAPI void
17edje_frametime_set(double t)
18{
19 ecore_animator_frametime_set(t);
20}
21
22EAPI double
23edje_frametime_get(void)
24{
25 return ecore_animator_frametime_get();
26}
27
28void
29edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data)
30{
31 Edje *ed;
32 Edje_Signal_Callback *escb;
33
34 ed = _edje_fetch(obj);
35 if (!ed) return;
36 if (ed->delete_me) return;
37 escb = calloc(1, sizeof(Edje_Signal_Callback));
38 escb->propagate = EINA_TRUE;
39 escb->signal = eina_stringshare_add("*");
40 escb->source = eina_stringshare_add("*");
41 escb->func = func;
42 escb->data = data;
43 ed->callbacks = eina_list_append(ed->callbacks, escb);
44 if (ed->walking_callbacks)
45 {
46 escb->just_added = 1;
47 ed->just_added_callbacks = 1;
48 }
49 else
50 _edje_callbacks_patterns_clean(ed);
51}
52
53EAPI void
54edje_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)
55{
56 Edje *ed;
57 Edje_Signal_Callback *escb;
58
59 if ((!emission) || (!source) || (!func)) return;
60 ed = _edje_fetch(obj);
61 if (!ed) return;
62 if (ed->delete_me) return;
63 escb = calloc(1, sizeof(Edje_Signal_Callback));
64 if (emission[0])
65 escb->signal = eina_stringshare_add(emission);
66 if (source[0])
67 escb->source = eina_stringshare_add(source);
68 escb->func = func;
69 escb->data = data;
70 ed->callbacks = eina_list_append(ed->callbacks, escb);
71 if (ed->walking_callbacks)
72 {
73 escb->just_added = 1;
74 ed->just_added_callbacks = 1;
75 }
76 else
77 _edje_callbacks_patterns_clean(ed);
78}
79
80EAPI void *
81edje_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))
82{
83 Edje *ed;
84 Eina_List *l;
85 Edje_Signal_Callback *escb;
86
87 if ((!emission) || (!source) || (!func)) return NULL;
88 ed = _edje_fetch(obj);
89 if (!ed) return NULL;
90 if (ed->delete_me) return NULL;
91 EINA_LIST_FOREACH(ed->callbacks, l, escb)
92 {
93 if ((escb->func == func) &&
94 ((!escb->signal && !emission[0]) ||
95 (escb->signal && !strcmp(escb->signal, emission))) &&
96 ((!escb->source && !source[0]) ||
97 (escb->source && !strcmp(escb->source, source))))
98 {
99 void *data;
100
101 data = escb->data;
102 if (ed->walking_callbacks)
103 {
104 escb->delete_me = 1;
105 ed->delete_callbacks = 1;
106 }
107 else
108 {
109 _edje_callbacks_patterns_clean(ed);
110
111 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
112 if (escb->signal) eina_stringshare_del(escb->signal);
113 if (escb->source) eina_stringshare_del(escb->source);
114 free(escb);
115 }
116 return data;
117 }
118 }
119 return NULL;
120}
121
122EAPI void *
123edje_object_signal_callback_del_full(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
124{
125 Edje *ed;
126 Eina_List *l;
127 Edje_Signal_Callback *escb;
128
129 if ((!emission) || (!source) || (!func)) return NULL;
130 ed = _edje_fetch(obj);
131 if (!ed) return NULL;
132 if (ed->delete_me) return NULL;
133 EINA_LIST_FOREACH(ed->callbacks, l, escb)
134 {
135 if ((escb->func == func) && (escb->data == data) &&
136 ((!escb->signal && !emission[0]) ||
137 (escb->signal && !strcmp(escb->signal, emission))) &&
138 ((!escb->source && !source[0]) ||
139 (escb->source && !strcmp(escb->source, source))))
140 {
141 void *data2;
142
143 data2 = escb->data;
144 if (ed->walking_callbacks)
145 {
146 escb->delete_me = 1;
147 ed->delete_callbacks = 1;
148 }
149 else
150 {
151 _edje_callbacks_patterns_clean(ed);
152
153 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
154 if (escb->signal) eina_stringshare_del(escb->signal);
155 if (escb->source) eina_stringshare_del(escb->source);
156 free(escb);
157 }
158 return data2;
159 }
160 }
161 return NULL;
162}
163
164EAPI void
165edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source)
166{
167 Edje *ed;
168
169 if ((!emission) || (!source)) return;
170 ed = _edje_fetch(obj);
171 if (!ed) return;
172 if (ed->delete_me) return;
173 _edje_emit(ed, (char *)emission, (char *)source);
174}
175
176/* FIXDOC: Verify/Expand */
177EAPI void
178edje_object_play_set(Evas_Object *obj, Eina_Bool play)
179{
180 Edje *ed;
181 double t;
182 Eina_List *l;
183 Edje_Running_Program *runp;
184 unsigned int i;
185
186 ed = _edje_fetch(obj);
187 if (!ed) return;
188 if (ed->delete_me) return;
189 if (play)
190 {
191 if (!ed->paused) return;
192 ed->paused = 0;
193 t = ecore_time_get() - ed->paused_at;
194 EINA_LIST_FOREACH(ed->actions, l, runp)
195 runp->start_time += t;
196 }
197 else
198 {
199 if (ed->paused) return;
200 ed->paused = EINA_TRUE;
201 ed->paused_at = ecore_time_get();
202 }
203
204 for (i = 0; i < ed->table_parts_size; i++)
205 {
206 Edje_Real_Part *rp;
207 rp = ed->table_parts[i];
208 if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
209 edje_object_play_set(rp->swallowed_object, play);
210 }
211}
212
213EAPI Eina_Bool
214edje_object_play_get(const Evas_Object *obj)
215{
216 Edje *ed;
217
218 ed = _edje_fetch(obj);
219 if (!ed) return EINA_FALSE;
220 if (ed->delete_me) return EINA_FALSE;
221 if (ed->paused) return EINA_FALSE;
222 return EINA_TRUE;
223}
224
225/* FIXDOC: Verify/Expand */
226EAPI void
227edje_object_animation_set(Evas_Object *obj, Eina_Bool on)
228{
229 Edje *ed;
230 Eina_List *l;
231 unsigned int i;
232
233 ed = _edje_fetch(obj);
234 if (!ed) return;
235 if (ed->delete_me) return;
236 _edje_block(ed);
237 ed->no_anim = !on;
238 _edje_freeze(ed);
239 if (!on)
240 {
241 Eina_List *newl = NULL;
242 const void *data;
243
244 EINA_LIST_FOREACH(ed->actions, l, data)
245 newl = eina_list_append(newl, data);
246 while (newl)
247 {
248 Edje_Running_Program *runp;
249
250 runp = eina_list_data_get(newl);
251 newl = eina_list_remove(newl, eina_list_data_get(newl));
252 _edje_program_run_iterate(runp, runp->start_time + TO_DOUBLE(runp->program->tween.time));
253 if (_edje_block_break(ed))
254 {
255 eina_list_free(newl);
256 goto break_prog;
257 }
258 }
259 }
260 else
261 {
262 _edje_emit(ed, "load", NULL);
263 if (evas_object_visible_get(obj))
264 {
265 evas_object_hide(obj);
266 evas_object_show(obj);
267 }
268 }
269 break_prog:
270
271 for (i = 0; i < ed->table_parts_size; i++)
272 {
273 Edje_Real_Part *rp;
274 rp = ed->table_parts[i];
275 if (rp->part->type == EDJE_PART_TYPE_GROUP && rp->swallowed_object)
276 edje_object_animation_set(rp->swallowed_object, on);
277 }
278
279 _edje_thaw(ed);
280 _edje_unblock(ed);
281}
282
283
284EAPI Eina_Bool
285edje_object_animation_get(const Evas_Object *obj)
286{
287 Edje *ed;
288
289 ed = _edje_fetch(obj);
290 if (!ed) return EINA_FALSE;
291 if (ed->delete_me) return EINA_FALSE;
292 if (ed->no_anim) return EINA_FALSE;
293 return EINA_TRUE;
294}
295
296/* Private Routines */
297
298Eina_Bool
299_edje_program_run_iterate(Edje_Running_Program *runp, double tim)
300{
301 FLOAT_T t, total;
302 Eina_List *l;
303 Edje *ed;
304 Edje_Program_Target *pt;
305 Edje_Real_Part *rp;
306
307 ed = runp->edje;
308 if (ed->delete_me) return EINA_FALSE;
309 _edje_block(ed);
310 _edje_ref(ed);
311 _edje_freeze(ed);
312 t = FROM_DOUBLE(tim - runp->start_time);
313 total = runp->program->tween.time;
314 t = DIV(t, total);
315 if (t > FROM_INT(1)) t = FROM_INT(1);
316 EINA_LIST_FOREACH(runp->program->targets, l, pt)
317 {
318 if (pt->id >= 0)
319 {
320 rp = ed->table_parts[pt->id % ed->table_parts_size];
321 if (rp) _edje_part_pos_set(ed, rp,
322 runp->program->tween.mode, t,
323 runp->program->tween.v1,
324 runp->program->tween.v2);
325 }
326 }
327 if (t >= FROM_INT(1))
328 {
329 Edje_Program_After *pa;
330
331 EINA_LIST_FOREACH(runp->program->targets, l, pt)
332 {
333 if (pt->id >= 0)
334 {
335 rp = ed->table_parts[pt->id % ed->table_parts_size];
336 if (rp)
337 {
338 _edje_part_description_apply(ed, rp,
339 runp->program->state,
340 runp->program->value,
341 NULL,
342 0.0);
343 _edje_part_pos_set(ed, rp,
344 runp->program->tween.mode, ZERO,
345 runp->program->tween.v1,
346 runp->program->tween.v2);
347 rp->program = NULL;
348 }
349 }
350 }
351 _edje_recalc(ed);
352 runp->delete_me = 1;
353 if (!ed->walking_actions)
354 {
355 _edje_anim_count--;
356 ed->actions = eina_list_remove(ed->actions, runp);
357 if (!ed->actions)
358 _edje_animators = eina_list_remove(_edje_animators, ed);
359 }
360// _edje_emit(ed, "program,stop", runp->program->name);
361 if (_edje_block_break(ed))
362 {
363 if (!ed->walking_actions) free(runp);
364 goto break_prog;
365 }
366 EINA_LIST_FOREACH(runp->program->after, l, pa)
367 {
368 Edje_Program *pr;
369
370 if (pa->id >= 0)
371 {
372 pr = ed->table_programs[pa->id % ed->table_programs_size];
373 if (pr) _edje_program_run(ed, pr, 0, "", "");
374 if (_edje_block_break(ed))
375 {
376 if (!ed->walking_actions) free(runp);
377 goto break_prog;
378 }
379 }
380 }
381 _edje_thaw(ed);
382 _edje_unref(ed);
383 if (!ed->walking_actions) free(runp);
384 _edje_unblock(ed);
385 return EINA_FALSE;
386 }
387 break_prog:
388 _edje_recalc(ed);
389 _edje_thaw(ed);
390 _edje_unref(ed);
391 _edje_unblock(ed);
392 return EINA_TRUE;
393}
394
395void
396_edje_program_end(Edje *ed, Edje_Running_Program *runp)
397{
398 Eina_List *l;
399 Edje_Program_Target *pt;
400// const char *pname = NULL;
401 int free_runp = 0;
402
403 if (ed->delete_me) return;
404 _edje_ref(ed);
405 _edje_freeze(ed);
406 EINA_LIST_FOREACH(runp->program->targets, l, pt)
407 {
408 Edje_Real_Part *rp;
409
410 if (pt->id >= 0)
411 {
412 rp = ed->table_parts[pt->id % ed->table_parts_size];
413 if (rp)
414 {
415 _edje_part_description_apply(ed, rp,
416 runp->program->state,
417 runp->program->value,
418 NULL,
419 0.0);
420 _edje_part_pos_set(ed, rp,
421 runp->program->tween.mode, ZERO,
422 runp->program->tween.v1,
423 runp->program->tween.v2);
424 rp->program = NULL;
425 }
426 }
427 }
428 _edje_recalc(ed);
429 runp->delete_me = 1;
430// pname = runp->program->name;
431 if (!ed->walking_actions)
432 {
433 _edje_anim_count--;
434 ed->actions = eina_list_remove(ed->actions, runp);
435 free_runp = 1;
436 if (!ed->actions)
437 {
438 _edje_animators = eina_list_remove(_edje_animators, ed);
439 }
440 }
441// _edje_emit(ed, "program,stop", pname);
442 _edje_thaw(ed);
443 _edje_unref(ed);
444 if (free_runp) free(runp);
445}
446
447void
448_edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, const char *ssrc)
449{
450 Eina_List *l;
451 Edje_Real_Part *rp;
452 Edje_Program_Target *pt;
453 Edje_Program *pr2;
454 Edje_Program_After *pa;
455 /* limit self-feeding loops in programs to 64 levels */
456 static int recursions = 0;
457 static int recursion_limit = 0;
458
459 if (ed->delete_me) return;
460 if ((pr->in.from > 0.0) && (pr->in.range >= 0.0) && (!force))
461 {
462 Edje_Pending_Program *pp;
463 double r = 0.0;
464
465 pp = calloc(1, sizeof(Edje_Pending_Program));
466 if (!pp) return;
467 if (pr->in.range > 0.0) r = ((double)rand() / RAND_MAX);
468 pp->timer = ecore_timer_add(pr->in.from + (pr->in.range * r),
469 _edje_pending_timer_cb, pp);
470 if (!pp->timer)
471 {
472 free(pp);
473 return;
474 }
475 pp->edje = ed;
476 pp->program = pr;
477 ed->pending_actions = eina_list_append(ed->pending_actions, pp);
478 return;
479 }
480 if ((recursions >= 64) || (recursion_limit))
481 {
482 ERR("Programs recursing up to recursion limit of %i. Disabled.",
483 64);
484 recursion_limit = 1;
485 return;
486 }
487 recursions++;
488 _edje_block(ed);
489 _edje_ref(ed);
490 _edje_freeze(ed);
491 switch (pr->action)
492 {
493 case EDJE_ACTION_TYPE_STATE_SET:
494 if ((pr->tween.time > ZERO) && (!ed->no_anim))
495 {
496 Edje_Running_Program *runp;
497
498 runp = calloc(1, sizeof(Edje_Running_Program));
499 EINA_LIST_FOREACH(pr->targets, l, pt)
500 {
501 if (pt->id >= 0)
502 {
503 rp = ed->table_parts[pt->id % ed->table_parts_size];
504 if (rp)
505 {
506 if ((rp->object) && (pr->tween.mode & EDJE_TWEEN_MODE_OPT_FROM_CURRENT))
507 {
508 Edje_Calc_Params *tmp;
509
510 tmp = calloc(1, sizeof(Edje_Calc_Params));
511 if (!tmp) goto low_mem_current;
512 _edje_part_recalc(ed, rp, FLAG_XY, tmp);
513
514 if (rp->current) free(rp->current);
515 rp->current = tmp;
516
517 rp->current->x -= ed->x;
518 rp->current->y -= ed->y;
519 rp->current->map.center.x -= ed->x;
520 rp->current->map.center.y -= ed->y;
521 rp->current->map.light.x -= ed->x;
522 rp->current->map.light.y -= ed->y;
523 rp->current->map.persp.x -= ed->x;
524 rp->current->map.persp.y -= ed->y;
525 }
526 else
527 {
528 low_mem_current:
529 if (rp->current) free(rp->current);
530 rp->current = NULL;
531 }
532
533 if (rp->program)
534 _edje_program_end(ed, rp->program);
535 _edje_part_description_apply(ed, rp,
536 rp->param1.description->state.name,
537 rp->param1.description->state.value,
538 pr->state,
539 pr->value);
540 _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
541 pr->tween.v1,
542 pr->tween.v2);
543 rp->program = runp;
544 }
545 }
546 }
547 // _edje_emit(ed, "program,start", pr->name);
548 if (_edje_block_break(ed))
549 {
550 ed->actions = eina_list_append(ed->actions, runp);
551 goto break_prog;
552 }
553 if (!ed->actions)
554 _edje_animators = eina_list_append(_edje_animators, ed);
555 ed->actions = eina_list_append(ed->actions, runp);
556 runp->start_time = ecore_loop_time_get();
557 runp->edje = ed;
558 runp->program = pr;
559 if (!_edje_timer)
560 _edje_timer = ecore_animator_add(_edje_timer_cb, NULL);
561 _edje_anim_count++;
562 }
563 else
564 {
565 EINA_LIST_FOREACH(pr->targets, l, pt)
566 {
567 if (pt->id >= 0)
568 {
569 rp = ed->table_parts[pt->id % ed->table_parts_size];
570 if (rp)
571 {
572 if (rp->program)
573 _edje_program_end(ed, rp->program);
574 _edje_part_description_apply(ed, rp,
575 pr->state,
576 pr->value,
577 NULL,
578 0.0);
579 _edje_part_pos_set(ed, rp, pr->tween.mode, ZERO,
580 pr->tween.v1,
581 pr->tween.v2);
582 }
583 }
584 }
585 // _edje_emit(ed, "program,start", pr->name);
586 if (_edje_block_break(ed)) goto break_prog;
587 // _edje_emit(ed, "program,stop", pr->name);
588 if (_edje_block_break(ed)) goto break_prog;
589
590 EINA_LIST_FOREACH(pr->after, l, pa)
591 {
592 if (pa->id >= 0)
593 {
594 pr2 = ed->table_programs[pa->id % ed->table_programs_size];
595 if (pr2) _edje_program_run(ed, pr2, 0, "", "");
596 if (_edje_block_break(ed)) goto break_prog;
597 }
598 }
599 _edje_recalc(ed);
600 }
601 break;
602 case EDJE_ACTION_TYPE_ACTION_STOP:
603 // _edje_emit(ed, "program,start", pr->name);
604 EINA_LIST_FOREACH(pr->targets, l, pt)
605 {
606 Eina_List *ll;
607 Edje_Running_Program *runp;
608 Edje_Pending_Program *pp;
609
610 for (ll = ed->actions; ll; )
611 {
612 runp = ll->data;
613 ll = ll->next;
614 if (pt->id == runp->program->id)
615 {
616 _edje_program_end(ed, runp);
617// goto done;
618 }
619 }
620 for (ll = ed->pending_actions; ll; )
621 {
622 pp = ll->data;
623 ll = ll->next;
624 if (pt->id == pp->program->id)
625 {
626 ed->pending_actions = eina_list_remove(ed->pending_actions, pp);
627 ecore_timer_del(pp->timer);
628 free(pp);
629// goto done;
630 }
631 }
632// done:
633// continue;
634 }
635 // _edje_emit(ed, "program,stop", pr->name);
636 if (_edje_block_break(ed)) goto break_prog;
637 break;
638 case EDJE_ACTION_TYPE_SIGNAL_EMIT:
639 // _edje_emit(ed, "program,start", pr->name);
640 if (_edje_block_break(ed)) goto break_prog;
641 _edje_emit(ed, pr->state, pr->state2);
642 if (_edje_block_break(ed)) goto break_prog;
643 // _edje_emit(ed, "program,stop", pr->name);
644 if (_edje_block_break(ed)) goto break_prog;
645 break;
646 case EDJE_ACTION_TYPE_DRAG_VAL_SET:
647 // _edje_emit(ed, "program,start", pr->name);
648 if (_edje_block_break(ed)) goto break_prog;
649 EINA_LIST_FOREACH(pr->targets, l, pt)
650 {
651 if (pt->id >= 0)
652 {
653 rp = ed->table_parts[pt->id % ed->table_parts_size];
654 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
655 {
656 rp->drag->val.x = pr->value;
657 rp->drag->val.y = pr->value2;
658 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
659 else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
660 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
661 else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
662 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
663 _edje_emit(ed, "drag,set", rp->part->name);
664 if (_edje_block_break(ed)) goto break_prog;
665 }
666 }
667 }
668 // _edje_emit(ed, "program,stop", pr->name);
669 if (_edje_block_break(ed)) goto break_prog;
670 break;
671 case EDJE_ACTION_TYPE_DRAG_VAL_STEP:
672 // _edje_emit(ed, "program,start", pr->name);
673 if (_edje_block_break(ed)) goto break_prog;
674 EINA_LIST_FOREACH(pr->targets, l, pt)
675 {
676 if (pt->id >= 0)
677 {
678 rp = ed->table_parts[pt->id % ed->table_parts_size];
679 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
680 {
681 rp->drag->val.x += pr->value * rp->drag->step.x * rp->part->dragable.x;
682 rp->drag->val.y += pr->value2 * rp->drag->step.y * rp->part->dragable.y;
683 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
684 else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
685 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
686 else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
687 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
688 _edje_emit(ed, "drag,step", rp->part->name);
689 if (_edje_block_break(ed)) goto break_prog;
690 }
691 }
692 }
693 // _edje_emit(ed, "program,stop", pr->name);
694 if (_edje_block_break(ed)) goto break_prog;
695 break;
696 case EDJE_ACTION_TYPE_DRAG_VAL_PAGE:
697 // _edje_emit(ed, "program,start", pr->name);
698 if (_edje_block_break(ed)) goto break_prog;
699 EINA_LIST_FOREACH(pr->targets, l, pt)
700 {
701 if (pt->id >= 0)
702 {
703 rp = ed->table_parts[pt->id % ed->table_parts_size];
704 if ((rp) && (rp->drag) && (rp->drag->down.count == 0))
705 {
706 rp->drag->val.x += pr->value * rp->drag->page.x * rp->part->dragable.x;
707 rp->drag->val.y += pr->value2 * rp->drag->page.y * rp->part->dragable.y;
708 if (rp->drag->val.x < 0.0) rp->drag->val.x = 0.0;
709 else if (rp->drag->val.x > 1.0) rp->drag->val.x = 1.0;
710 if (rp->drag->val.y < 0.0) rp->drag->val.y = 0.0;
711 else if (rp->drag->val.y > 1.0) rp->drag->val.y = 1.0;
712 _edje_dragable_pos_set(ed, rp, rp->drag->val.x, rp->drag->val.y);
713 _edje_emit(ed, "drag,page", rp->part->name);
714 if (_edje_block_break(ed)) goto break_prog;
715 }
716 }
717 }
718 // _edje_emit(ed, "program,stop", pr->name);
719 if (_edje_block_break(ed)) goto break_prog;
720 break;
721 case EDJE_ACTION_TYPE_SCRIPT:
722 {
723 char fname[128];
724
725 // _edje_emit(ed, "program,start", pr->name);
726 if (_edje_block_break(ed)) goto break_prog;
727 snprintf(fname, sizeof(fname), "_p%i", pr->id);
728 _edje_embryo_test_run(ed, fname, ssig, ssrc);
729 // _edje_emit(ed, "program,stop", pr->name);
730 if (_edje_block_break(ed)) goto break_prog;
731 _edje_recalc_do(ed);
732 }
733 break;
734 case EDJE_ACTION_TYPE_FOCUS_SET:
735 if (!pr->targets)
736 ed->focused_part = NULL;
737 else
738 {
739 EINA_LIST_FOREACH(pr->targets, l, pt)
740 {
741 if (pt->id >= 0)
742 {
743 rp = ed->table_parts[pt->id % ed->table_parts_size];
744 if (rp)
745 {
746 if (ed->focused_part != rp)
747 {
748 if (ed->focused_part)
749 _edje_emit(ed, "focus,part,out",
750 ed->focused_part->part->name);
751 ed->focused_part = rp;
752 _edje_emit(ed, "focus,part,in",
753 ed->focused_part->part->name);
754 }
755 }
756 }
757 }
758 }
759 break;
760 case EDJE_ACTION_TYPE_FOCUS_OBJECT:
761 if (!pr->targets)
762 {
763 Evas_Object *focused;
764
765 focused = evas_focus_get(evas_object_evas_get(ed->obj));
766 if (focused)
767 {
768 unsigned int i;
769
770 /* Check if the current swallowed object is one of my child. */
771 for (i = 0; i < ed->table_parts_size; ++i)
772 {
773 rp = ed->table_parts[i];
774 if (rp && rp->swallowed_object == focused)
775 {
776 evas_object_focus_set(focused, EINA_FALSE);
777 break;
778 }
779 }
780 }
781 }
782 else
783 {
784 EINA_LIST_FOREACH(pr->targets, l, pt)
785 {
786 if (pt->id >= 0)
787 {
788 rp = ed->table_parts[pt->id % ed->table_parts_size];
789 if (rp && rp->swallowed_object)
790 evas_object_focus_set(rp->swallowed_object, EINA_TRUE);
791 }
792 }
793 }
794 break;
795 case EDJE_ACTION_TYPE_SOUND_SAMPLE:
796 if (_edje_block_break(ed))
797 goto break_prog;
798 _edje_multisense_internal_sound_sample_play(ed, pr->sample_name, pr->speed);
799 break;
800 case EDJE_ACTION_TYPE_SOUND_TONE:
801 if (_edje_block_break(ed))
802 goto break_prog;
803 _edje_multisense_internal_sound_tone_play(ed, pr->tone_name, pr->duration);
804 break;
805 case EDJE_ACTION_TYPE_PARAM_COPY:
806 {
807 Edje_Real_Part *src_part, *dst_part;
808
809 // _edje_emit(ed, "program,start", pr->name);
810 if (_edje_block_break(ed)) goto break_prog;
811
812 src_part = ed->table_parts[pr->param.src % ed->table_parts_size];
813 dst_part = ed->table_parts[pr->param.dst % ed->table_parts_size];
814 _edje_param_copy(src_part, pr->state, dst_part, pr->state2);
815
816 if (_edje_block_break(ed)) goto break_prog;
817 // _edje_emit(ed, "program,stop", pr->name);
818 if (_edje_block_break(ed)) goto break_prog;
819 }
820 break;
821 case EDJE_ACTION_TYPE_PARAM_SET:
822 {
823 Edje_Real_Part *part;
824
825 // _edje_emit(ed, "program,start", pr->name);
826 if (_edje_block_break(ed)) goto break_prog;
827
828 part = ed->table_parts[pr->param.dst % ed->table_parts_size];
829 _edje_param_set(part, pr->state, pr->state2);
830
831 if (_edje_block_break(ed)) goto break_prog;
832 // _edje_emit(ed, "program,stop", pr->name);
833 if (_edje_block_break(ed)) goto break_prog;
834 }
835 break;
836 default:
837 // _edje_emit(ed, "program,start", pr->name);
838 // _edje_emit(ed, "program,stop", pr->name);
839 break;
840 }
841 if (!((pr->action == EDJE_ACTION_TYPE_STATE_SET)
842 /* hmm this fucks somethgin up. must look into it later */
843 /* && (pr->tween.time > ZERO) && (!ed->no_anim))) */
844 ))
845 {
846 EINA_LIST_FOREACH(pr->after, l, pa)
847 {
848 if (pa->id >= 0)
849 {
850 pr2 = ed->table_programs[pa->id % ed->table_programs_size];
851 if (pr2) _edje_program_run(ed, pr2, 0, "", "");
852 if (_edje_block_break(ed)) goto break_prog;
853 }
854 }
855 }
856 break_prog:
857 _edje_thaw(ed);
858 _edje_unref(ed);
859 recursions--;
860 if (recursions == 0) recursion_limit = 0;
861 _edje_unblock(ed);
862}
863
864void
865_edje_emit(Edje *ed, const char *sig, const char *src)
866{
867 _edje_emit_full(ed, sig, src, NULL, NULL);
868}
869
870/* data should either be NULL or a malloc allocated data */
871void
872_edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *))
873{
874 Edje_Message_Signal emsg;
875 const char *sep;
876
877 if (ed->delete_me) return;
878
879 sep = strchr(sig, EDJE_PART_PATH_SEPARATOR);
880
881 /* If we are not sending the signal to a part of the child, the
882 * signal if for ourself
883 */
884 if (sep)
885 {
886 Edje_Real_Part *rp = NULL;
887 const char *newsig;
888 Edje *ed2;
889 char *part;
890 char *idx;
891 size_t length;
892
893 /* the signal contains a colon, split the signal into "parts:signal" */
894 length = sep - sig + 1;
895 part = alloca(length);
896 memcpy(part, sig, length - 1);
897 part[length - 1] = '\0';
898
899 newsig = sep + 1;
900
901 /* lookup for alias */
902 if (ed->collection && ed->collection->alias)
903 {
904 char *alias;
905
906 alias = eina_hash_find(ed->collection->alias, part);
907 if (alias) {
908 char *aliased;
909 int alien;
910 int nslen;
911
912 alien = strlen(alias);
913 nslen = strlen(newsig);
914 length = alien + nslen + 2;
915
916 aliased = alloca(length);
917 memcpy(aliased, alias, alien);
918 aliased[alien] = EDJE_PART_PATH_SEPARATOR;
919 memcpy(aliased + alien + 1, newsig, nslen + 1);
920
921 _edje_emit(ed, aliased, src);
922 return;
923 }
924 }
925
926 /* search for the index if present and remove it from the part */
927 idx = strchr(part, EDJE_PART_PATH_SEPARATOR_INDEXL);
928 if (idx)
929 {
930 char *end;
931
932 end = strchr(idx + 1, EDJE_PART_PATH_SEPARATOR_INDEXR);
933 if (end && end != idx + 1)
934 {
935 char *tmp;
936
937 tmp = alloca(end - idx - 1);
938 memcpy(tmp, idx + 1, end - idx - 1);
939 tmp[end - idx - 1] = '\0';
940 *idx = '\0';
941 idx = tmp;
942 }
943 else
944 {
945 idx = NULL;
946 }
947 }
948
949 /* search for the right part now */
950 rp = _edje_real_part_get(ed, part);
951 if (!rp) goto end;
952
953 switch (rp->part->type)
954 {
955 case EDJE_PART_TYPE_GROUP:
956 if (!rp->swallowed_object) goto end;
957 ed2 = _edje_fetch(rp->swallowed_object);
958 if (!ed2) goto end;
959
960 _edje_emit(ed2, newsig, src);
961 break;
962
963 case EDJE_PART_TYPE_EXTERNAL:
964 if (!rp->swallowed_object) break ;
965
966 if (!idx)
967 {
968 _edje_external_signal_emit(rp->swallowed_object, newsig, src);
969 }
970 else
971 {
972 Evas_Object *child;
973
974 child = _edje_children_get(rp, idx);
975 ed2 = _edje_fetch(child);
976 if (!ed2) goto end;
977 _edje_emit(ed2, newsig, src);
978 }
979 break ;
980
981 case EDJE_PART_TYPE_BOX:
982 case EDJE_PART_TYPE_TABLE:
983 if (idx)
984 {
985 Evas_Object *child;
986
987 child = _edje_children_get(rp, idx);
988 ed2 = _edje_fetch(child);
989 if (!ed2) goto end;
990 _edje_emit(ed2, newsig, src);
991 }
992 break ;
993
994 default:
995 fprintf(stderr, "SPANK SPANK SPANK !!!\nYou should never be here !\n");
996 break;
997 }
998 }
999
1000 end:
1001 emsg.sig = sig;
1002 emsg.src = src;
1003 if (data)
1004 {
1005 emsg.data = calloc(1, sizeof(*(emsg.data)));
1006 emsg.data->ref = 1;
1007 emsg.data->data = data;
1008 emsg.data->free_func = free_func;
1009 }
1010 else
1011 {
1012 emsg.data = NULL;
1013 }
1014/* new sends code */
1015 edje_object_message_send(ed->obj, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1016/* old send code - use api now
1017 _edje_message_send(ed, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1018 EINA_LIST_FOREACH(ed->subobjs, l, obj)
1019 {
1020 Edje *ed2;
1021
1022 ed2 = _edje_fetch(obj);
1023 if (!ed2) continue;
1024 if (ed2->delete_me) continue;
1025 _edje_message_send(ed2, EDJE_QUEUE_SCRIPT, EDJE_MESSAGE_SIGNAL, 0, &emsg);
1026 }
1027 */
1028 if (emsg.data && (--(emsg.data->ref) == 0))
1029 {
1030 if (emsg.data->free_func)
1031 {
1032 emsg.data->free_func(emsg.data->data);
1033 }
1034 free(emsg.data);
1035 }
1036}
1037
1038struct _Edje_Program_Data
1039{
1040#ifdef EDJE_PROGRAM_CACHE
1041 Eina_List *matches;
1042 int matched;
1043#endif
1044 Edje *ed;
1045 const char *signal;
1046 const char *source;
1047};
1048
1049static Eina_Bool _edje_glob_callback(Edje_Program *pr, void *dt)
1050{
1051 struct _Edje_Program_Data *data = dt;
1052 Edje_Real_Part *rp = NULL;
1053 Eina_Bool exec = EINA_TRUE;
1054
1055 if (pr->filter.state)
1056 {
1057 rp = _edje_real_part_get(data->ed, pr->filter.part ? pr->filter.part : data->source);
1058 if (rp)
1059 exec = (rp->chosen_description->state.name == pr->filter.state);
1060 }
1061
1062#ifdef EDJE_PROGRAM_CACHE
1063 data->matched++;
1064#endif
1065
1066 if (exec)
1067 _edje_program_run(data->ed, pr, 0, data->signal, data->source);
1068
1069 if (_edje_block_break(data->ed))
1070 {
1071#ifdef EDJE_PROGRAM_CACHE
1072 eina_list_free(data->matches);
1073 data->matches = NULL;
1074#endif
1075 return EINA_TRUE;
1076 }
1077
1078#ifdef EDJE_PROGRAM_CACHE
1079 data->matches = eina_list_append(data->matches, pr);
1080#endif
1081
1082 return EINA_FALSE;
1083}
1084
1085
1086void
1087_edje_callbacks_patterns_clean(Edje *ed)
1088{
1089 _edje_signals_sources_patterns_clean(&ed->patterns.callbacks);
1090
1091 eina_rbtree_delete(ed->patterns.callbacks.exact_match,
1092 EINA_RBTREE_FREE_CB(edje_match_signal_source_free),
1093 NULL);
1094 ed->patterns.callbacks.exact_match = NULL;
1095
1096 ed->patterns.callbacks.u.callbacks.globing = eina_list_free(ed->patterns.callbacks.u.callbacks.globing);
1097}
1098
1099static void
1100_edje_callbacks_patterns_init(Edje *ed)
1101{
1102 Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks;
1103
1104 if ((ssp->signals_patterns) || (ssp->sources_patterns) ||
1105 (ssp->u.callbacks.globing) || (ssp->exact_match))
1106 return;
1107
1108 ssp->u.callbacks.globing = edje_match_callback_hash_build(ed->callbacks,
1109 &ssp->exact_match);
1110
1111 ssp->signals_patterns = edje_match_callback_signal_init(ssp->u.callbacks.globing);
1112 ssp->sources_patterns = edje_match_callback_source_init(ssp->u.callbacks.globing);
1113}
1114
1115/* FIXME: what if we delete the evas object??? */
1116void
1117_edje_emit_handle(Edje *ed, const char *sig, const char *src,
1118 Edje_Message_Signal_Data *sdata, Eina_Bool prop)
1119{
1120 if (ed->delete_me) return;
1121 if (!sig) sig = "";
1122 if (!src) src = "";
1123// printf("EDJE EMIT: (%p) signal: \"%s\" source: \"%s\"\n", ed, sig, src);
1124 _edje_block(ed);
1125 _edje_ref(ed);
1126 _edje_freeze(ed);
1127
1128 if (ed->collection && ed->L)
1129 _edje_lua2_script_func_signal(ed, sig, src);
1130
1131 if (ed->collection)
1132 {
1133#ifdef EDJE_PROGRAM_CACHE
1134 Edje_Part_Collection *ec;
1135 char *tmps;
1136 int l1, l2;
1137#endif
1138 int done;
1139
1140#ifdef EDJE_PROGRAM_CACHE
1141 ec = ed->collection;
1142 l1 = strlen(sig);
1143 l2 = strlen(src);
1144 tmps = alloca(l1 + l2 + 3); /* \0, \337, \0 */
1145 strcpy(tmps, sig);
1146 tmps[l1] = '\377';
1147 strcpy(&(tmps[l1 + 1]), src);
1148#endif
1149 done = 0;
1150
1151#ifdef EDJE_PROGRAM_CACHE
1152 {
1153 Eina_List *matches;
1154 Eina_List *l;
1155 Edje_Program *pr;
1156
1157 if (eina_hash_find(ec->prog_cache.no_matches, tmps))
1158 {
1159 done = 1;
1160 }
1161 else if ((matches = eina_hash_find(ec->prog_cache.matches, tmps)))
1162 {
1163 EINA_LIST_FOREACH(matches, l, pr)
1164 {
1165 Eina_Bool exec = EINA_TRUE;
1166
1167 if (pr->filter.state)
1168 {
1169 Edje_Real_Part *rp;
1170
1171 rp = _edje_real_part_get(ed, pr->filter.part ? pr->filter.part : src);
1172 if (rp)
1173 exec = (rp->chosen_description->state.name == pr->filter.state);
1174 }
1175
1176 if (exec)
1177 {
1178 _edje_program_run(ed, pr, 0, sig, src);
1179 if (_edje_block_break(ed))
1180 {
1181 goto break_prog;
1182 }
1183 }
1184 }
1185 done = 1;
1186 }
1187 }
1188#endif
1189 if (!done)
1190 {
1191 struct _Edje_Program_Data data;
1192
1193 data.ed = ed;
1194 data.source = src;
1195 data.signal = sig;
1196#ifdef EDJE_PROGRAM_CACHE
1197 data.matched = 0;
1198 data.matches = NULL;
1199#endif
1200 if (ed->table_programs_size > 0)
1201 {
1202 const Eina_List *match;
1203 const Eina_List *l;
1204 Edje_Program *pr;
1205
1206 if (ed->patterns.programs.u.programs.globing)
1207 if (edje_match_programs_exec(ed->patterns.programs.signals_patterns,
1208 ed->patterns.programs.sources_patterns,
1209 sig,
1210 src,
1211 ed->patterns.programs.u.programs.globing,
1212 _edje_glob_callback,
1213 &data,
1214 prop) == 0)
1215 goto break_prog;
1216
1217 match = edje_match_signal_source_hash_get(sig, src,
1218 ed->patterns.programs.exact_match);
1219 EINA_LIST_FOREACH(match, l, pr)
1220 _edje_glob_callback(pr, &data);
1221 }
1222
1223#ifdef EDJE_PROGRAM_CACHE
1224 if (tmps)
1225 {
1226 if (data.matched == 0)
1227 {
1228 if (!ec->prog_cache.no_matches)
1229 ec->prog_cache.no_matches = eina_hash_string_superfast_new(NULL);
1230 eina_hash_add(ec->prog_cache.no_matches, tmps, ed);
1231 }
1232 else
1233 {
1234 if (!ec->prog_cache.matches)
1235 ec->prog_cache.matches = eina_hash_string_superfast_new(NULL);
1236 eina_hash_add(ec->prog_cache.matches, tmps, data.matches);
1237 }
1238 }
1239#endif
1240 }
1241 _edje_emit_cb(ed, sig, src, sdata, prop);
1242 if (_edje_block_break(ed))
1243 {
1244 goto break_prog;
1245 }
1246 }
1247 break_prog:
1248 _edje_thaw(ed);
1249 _edje_unref(ed);
1250 _edje_unblock(ed);
1251}
1252
1253/* Extra data for callbacks */
1254static void *callback_extra_data = NULL;
1255
1256EAPI void *
1257edje_object_signal_callback_extra_data_get(void)
1258{
1259 return callback_extra_data;
1260}
1261
1262/* FIXME: what if we delete the evas object??? */
1263static void
1264_edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop)
1265{
1266 Eina_List *l;
1267
1268 if (ed->delete_me) return;
1269 _edje_ref(ed);
1270 _edje_freeze(ed);
1271 _edje_block(ed);
1272
1273 if (ed->just_added_callbacks)
1274 _edje_callbacks_patterns_clean(ed);
1275
1276 ed->walking_callbacks = 1;
1277
1278 if (ed->callbacks)
1279 {
1280 Edje_Signal_Callback *escb;
1281 const Eina_List *match;
1282 const Eina_List *l2;
1283 int r = 1;
1284 callback_extra_data = (data) ? data->data : NULL;
1285
1286 _edje_callbacks_patterns_init(ed);
1287 if (ed->patterns.callbacks.u.callbacks.globing)
1288 r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns,
1289 ed->patterns.callbacks.sources_patterns,
1290 sig,
1291 src,
1292 ed->patterns.callbacks.u.callbacks.globing,
1293 ed,
1294 prop);
1295
1296 if (!r)
1297 goto break_prog;
1298
1299 match = edje_match_signal_source_hash_get(sig, src,
1300 ed->patterns.callbacks.exact_match);
1301 EINA_LIST_FOREACH(match, l2, escb)
1302 {
1303 if ((prop) && (escb->propagate)) continue;
1304 if ((!escb->just_added) && (!escb->delete_me))
1305 {
1306 escb->func(escb->data, ed->obj, sig, src);
1307 if (_edje_block_break(ed))
1308 goto break_prog;
1309 }
1310 }
1311 }
1312 break_prog:
1313
1314 ed->walking_callbacks = 0;
1315 if ((ed->delete_callbacks) || (ed->just_added_callbacks))
1316 {
1317 ed->delete_callbacks = 0;
1318 ed->just_added_callbacks = 0;
1319 l = ed->callbacks;
1320 while (l)
1321 {
1322 Edje_Signal_Callback *escb = l->data;
1323 Eina_List *next_l = l->next;
1324
1325 if (escb->just_added)
1326 escb->just_added = 0;
1327 if (escb->delete_me)
1328 {
1329 ed->callbacks = eina_list_remove_list(ed->callbacks, l);
1330 if (escb->signal) eina_stringshare_del(escb->signal);
1331 if (escb->source) eina_stringshare_del(escb->source);
1332 free(escb);
1333 }
1334 l = next_l;
1335 }
1336
1337 _edje_callbacks_patterns_clean(ed);
1338 }
1339 _edje_unblock(ed);
1340 _edje_thaw(ed);
1341 _edje_unref(ed);
1342}
1343
1344static const Edje_External_Param_Info *
1345_edje_external_param_info_get(const Evas_Object *obj, const char *name)
1346{
1347 const Edje_External_Type *type;
1348 const Edje_External_Param_Info *info;
1349
1350 type = evas_object_data_get(obj, "Edje_External_Type");
1351 if (!type) return NULL;
1352 for (info = type->parameters_info; info->name; info++)
1353 if (!strcmp(info->name, name)) return info;
1354
1355 return NULL;
1356}
1357
1358static Edje_External_Param *
1359_edje_param_external_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param)
1360{
1361 Evas_Object *swallowed_object = rp->swallowed_object;
1362 const Edje_External_Param_Info *info;
1363
1364 info = _edje_external_param_info_get(swallowed_object, name);
1365 if (!info) return NULL;
1366
1367 memset(param, 0, sizeof(*param));
1368 param->name = info->name;
1369 param->type = info->type;
1370 if (!_edje_external_param_get(NULL, rp, param)) return NULL;
1371 return param;
1372}
1373
1374/* simulate external properties for native objects */
1375static Edje_External_Param *
1376_edje_param_native_get(Edje_Real_Part *rp, const char *name, Edje_External_Param *param, void **free_ptr)
1377{
1378 *free_ptr = NULL;
1379 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1380 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1381 {
1382 if (!strcmp(name, "text"))
1383 {
1384 param->name = name;
1385 param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1386
1387 _edje_recalc_do(rp->edje);
1388 if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1389 param->s = _edje_entry_text_get(rp);
1390 else if (rp->part->type == EDJE_PART_TYPE_TEXT)
1391 param->s = rp->text.text;
1392 else
1393 param->s = evas_object_textblock_text_markup_get(rp->object);
1394 return param;
1395 }
1396 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1397 {
1398 if (!strcmp(name, "text_unescaped"))
1399 {
1400 param->name = name;
1401 param->type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
1402
1403 _edje_recalc_do(rp->edje);
1404 if (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE)
1405 {
1406 const char *tmp = _edje_entry_text_get(rp);
1407 char *unescaped = _edje_text_unescape(tmp);
1408 *free_ptr = unescaped;
1409 param->s = unescaped;
1410 }
1411 else if (rp->part->type == EDJE_PART_TYPE_TEXT)
1412 param->s = rp->text.text;
1413 else
1414 {
1415 const char *tmp;
1416 char *unescaped;
1417
1418 tmp = evas_object_textblock_text_markup_get(rp->object);
1419 unescaped = _edje_text_unescape(tmp);
1420 *free_ptr = unescaped;
1421 param->s = unescaped;
1422 }
1423
1424 return param;
1425 }
1426
1427 if ((rp->entry_data) &&
1428 (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1429 (!strcmp(name, "select_allow")))
1430 {
1431 param->name = name;
1432 param->type = EDJE_EXTERNAL_PARAM_TYPE_BOOL;
1433 param->i = _edje_entry_select_allow_get(rp);
1434 return param;
1435 }
1436 }
1437 }
1438
1439 if ((rp->drag) && (rp->drag->down.count == 0))
1440 {
1441 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1442 {
1443 const char *sub_name = name + sizeof("drag_") - 1;
1444 if (!strcmp(sub_name, "value_x"))
1445 {
1446 double d;
1447
1448 _edje_recalc_do(rp->edje);
1449 d = TO_DOUBLE(rp->drag->val.x);
1450 if (rp->part->dragable.x < 0) d = 1.0 - d;
1451 param->name = name;
1452 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1453 param->d = d;
1454 return param;
1455 }
1456 if (!strcmp(sub_name, "value_y"))
1457 {
1458 double d;
1459
1460 _edje_recalc_do(rp->edje);
1461 d = TO_DOUBLE(rp->drag->val.y);
1462 if (rp->part->dragable.y < 0) d = 1.0 - d;
1463 param->name = name;
1464 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1465 param->d = d;
1466 return param;
1467 }
1468
1469 if (!strcmp(sub_name, "size_w"))
1470 {
1471 _edje_recalc_do(rp->edje);
1472 param->name = name;
1473 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1474 param->d = TO_DOUBLE(rp->drag->size.x);
1475 return param;
1476 }
1477 if (!strcmp(sub_name, "size_h"))
1478 {
1479 _edje_recalc_do(rp->edje);
1480 param->name = name;
1481 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1482 param->d = TO_DOUBLE(rp->drag->size.y);
1483 return param;
1484 }
1485
1486 if (!strcmp(sub_name, "step_x"))
1487 {
1488 _edje_recalc_do(rp->edje);
1489 param->name = name;
1490 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1491 param->d = TO_DOUBLE(rp->drag->step.x);
1492 return param;
1493 }
1494 if (!strcmp(sub_name, "step_y"))
1495 {
1496 _edje_recalc_do(rp->edje);
1497 param->name = name;
1498 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1499 param->d = TO_DOUBLE(rp->drag->step.y);
1500 return param;
1501 }
1502
1503 if (!strcmp(sub_name, "page_x"))
1504 {
1505 _edje_recalc_do(rp->edje);
1506 param->name = name;
1507 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1508 param->d = TO_DOUBLE(rp->drag->page.x);
1509 return param;
1510 }
1511 if (!strcmp(sub_name, "page_y"))
1512 {
1513 _edje_recalc_do(rp->edje);
1514 param->name = name;
1515 param->type = EDJE_EXTERNAL_PARAM_TYPE_DOUBLE;
1516 param->d = TO_DOUBLE(rp->drag->page.y);
1517 return param;
1518 }
1519
1520 return NULL;
1521 }
1522 }
1523
1524 return NULL;
1525}
1526
1527static Eina_Bool
1528_edje_param_native_set(Edje_Real_Part *rp, const char *name, const Edje_External_Param *param)
1529{
1530 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1531 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1532 {
1533 if (!strcmp(name, "text"))
1534 {
1535 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1536 return EINA_FALSE;
1537
1538 _edje_object_part_text_raw_set
1539 (rp->edje->obj, rp, rp->part->name, param->s);
1540 return EINA_TRUE;
1541 }
1542 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1543 {
1544 if (!strcmp(name, "text_unescaped"))
1545 {
1546 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_STRING)
1547 return EINA_FALSE;
1548
1549 if (rp->part->type == EDJE_PART_TYPE_TEXT)
1550 _edje_object_part_text_raw_set
1551 (rp->edje->obj, rp, rp->part->name, param->s);
1552 else
1553 {
1554 char *escaped = _edje_text_escape(param->s);
1555 _edje_object_part_text_raw_set
1556 (rp->edje->obj, rp, rp->part->name, escaped);
1557 free(escaped);
1558 }
1559
1560 return EINA_TRUE;
1561 }
1562
1563 if ((rp->entry_data) &&
1564 (rp->part->entry_mode > EDJE_ENTRY_EDIT_MODE_NONE) &&
1565 (!strcmp(name, "select_allow")))
1566 {
1567 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_BOOL)
1568 return EINA_FALSE;
1569 _edje_entry_select_allow_set(rp, param->i);
1570 return EINA_TRUE;
1571 }
1572 }
1573 }
1574
1575 if ((rp->drag) && (rp->drag->down.count == 0))
1576 {
1577 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1578 {
1579 const char *sub_name = name + sizeof("drag_") - 1;
1580 if (!strcmp(sub_name, "value_x"))
1581 {
1582 double d;
1583 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1584 return EINA_FALSE;
1585 d = param->d;
1586 if (rp->part->dragable.confine_id != -1)
1587 d = CLAMP(d, 0.0, 1.0);
1588 if (rp->part->dragable.x < 0) d = 1.0 - d;
1589 if (rp->drag->val.x == FROM_DOUBLE(d)) return EINA_TRUE;
1590 rp->drag->val.x = FROM_DOUBLE(d);
1591#ifdef EDJE_CALC_CACHE
1592 rp->invalidate = 1;
1593#endif
1594 _edje_dragable_pos_set
1595 (rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
1596 _edje_emit(rp->edje, "drag,set", rp->part->name);
1597 return EINA_TRUE;
1598 }
1599 if (!strcmp(sub_name, "value_y"))
1600 {
1601 double d;
1602 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1603 return EINA_FALSE;
1604 d = param->d;
1605 if (rp->part->dragable.confine_id != -1)
1606 d = CLAMP(d, 0.0, 1.0);
1607 if (rp->part->dragable.y < 0) d = 1.0 - d;
1608 if (rp->drag->val.y == FROM_DOUBLE(d)) return EINA_TRUE;
1609 rp->drag->val.y = FROM_DOUBLE(d);
1610#ifdef EDJE_CALC_CACHE
1611 rp->invalidate = 1;
1612#endif
1613 _edje_dragable_pos_set
1614 (rp->edje, rp, rp->drag->val.x, rp->drag->val.y);
1615 _edje_emit(rp->edje, "drag,set", rp->part->name);
1616 return EINA_TRUE;
1617 }
1618
1619 if (!strcmp(sub_name, "size_w"))
1620 {
1621 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1622 return EINA_FALSE;
1623 rp->drag->size.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1624 rp->edje->dirty = 1;
1625#ifdef EDJE_CALC_CACHE
1626 rp->invalidate = 1;
1627#endif
1628 _edje_recalc(rp->edje);
1629 return EINA_TRUE;
1630 }
1631 if (!strcmp(sub_name, "size_h"))
1632 {
1633 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1634 return EINA_FALSE;
1635 rp->drag->size.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1636 rp->edje->dirty = 1;
1637#ifdef EDJE_CALC_CACHE
1638 rp->invalidate = 1;
1639#endif
1640 _edje_recalc(rp->edje);
1641 return EINA_TRUE;
1642 }
1643
1644 if (!strcmp(sub_name, "step_x"))
1645 {
1646 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1647 return EINA_FALSE;
1648 rp->drag->step.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1649#ifdef EDJE_CALC_CACHE
1650 rp->invalidate = 1;
1651#endif
1652 return EINA_TRUE;
1653 }
1654 if (!strcmp(sub_name, "step_y"))
1655 {
1656 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1657 return EINA_FALSE;
1658 rp->drag->step.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1659#ifdef EDJE_CALC_CACHE
1660 rp->invalidate = 1;
1661#endif
1662 return EINA_TRUE;
1663 }
1664
1665 if (!strcmp(sub_name, "page_x"))
1666 {
1667 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1668 return EINA_FALSE;
1669 rp->drag->page.x = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1670#ifdef EDJE_CALC_CACHE
1671 rp->invalidate = 1;
1672#endif
1673 return EINA_TRUE;
1674 }
1675 if (!strcmp(sub_name, "page_y"))
1676 {
1677 if (param->type != EDJE_EXTERNAL_PARAM_TYPE_DOUBLE)
1678 return EINA_FALSE;
1679 rp->drag->page.y = FROM_DOUBLE(CLAMP(param->d, 0.0, 1.0));
1680#ifdef EDJE_CALC_CACHE
1681 rp->invalidate = 1;
1682#endif
1683 return EINA_TRUE;
1684 }
1685
1686 return EINA_FALSE;
1687 }
1688 }
1689
1690 return EINA_FALSE;
1691}
1692
1693static const Edje_External_Param_Info *
1694_edje_native_param_info_get(const Edje_Real_Part *rp, const char *name)
1695{
1696 if ((rp->part->type == EDJE_PART_TYPE_TEXT) ||
1697 (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK))
1698 {
1699 if (!strcmp(name, "text"))
1700 {
1701 static const Edje_External_Param_Info pi =
1702 EDJE_EXTERNAL_PARAM_INFO_STRING("text");
1703 return &pi;
1704 }
1705 if (rp->part->type == EDJE_PART_TYPE_TEXTBLOCK)
1706 {
1707 if (!strcmp(name, "text_unescaped"))
1708 {
1709 static const Edje_External_Param_Info pi =
1710 EDJE_EXTERNAL_PARAM_INFO_STRING("text_unescaped");
1711 return &pi;
1712 }
1713 if (!strcmp(name, "select_allow"))
1714 {
1715 static const Edje_External_Param_Info pi =
1716 EDJE_EXTERNAL_PARAM_INFO_BOOL("text_unescaped");
1717 return &pi;
1718 }
1719 }
1720 }
1721
1722 if ((rp->drag) && (rp->drag->down.count == 0))
1723 {
1724 if (!strncmp(name, "drag_", sizeof("drag_") - 1))
1725 {
1726 name += sizeof("drag_") - 1;
1727 if (!strcmp(name, "value_x"))
1728 {
1729 static const Edje_External_Param_Info pi =
1730 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_x");
1731 return &pi;
1732 }
1733 if (!strcmp(name, "value_y"))
1734 {
1735 static const Edje_External_Param_Info pi =
1736 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_value_y");
1737 return &pi;
1738 }
1739 if (!strcmp(name, "size_w"))
1740 {
1741 static const Edje_External_Param_Info pi =
1742 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_w");
1743 return &pi;
1744 }
1745 if (!strcmp(name, "size_h"))
1746 {
1747 static const Edje_External_Param_Info pi =
1748 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_size_h");
1749 return &pi;
1750 }
1751 if (!strcmp(name, "step_x"))
1752 {
1753 static const Edje_External_Param_Info pi =
1754 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_x");
1755 return &pi;
1756 }
1757 if (!strcmp(name, "step_y"))
1758 {
1759 static const Edje_External_Param_Info pi =
1760 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_step_y");
1761 return &pi;
1762 }
1763 if (!strcmp(name, "page_x"))
1764 {
1765 static const Edje_External_Param_Info pi =
1766 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_x");
1767 return &pi;
1768 }
1769 if (!strcmp(name, "page_y"))
1770 {
1771 static const Edje_External_Param_Info pi =
1772 EDJE_EXTERNAL_PARAM_INFO_DOUBLE("drag_page_y");
1773 return &pi;
1774 }
1775
1776 return NULL;
1777 }
1778 }
1779
1780 return NULL;
1781}
1782
1783static Edje_External_Param *
1784_edje_param_convert(Edje_External_Param *param, const Edje_External_Param_Info *dst_info)
1785{
1786 if (param->type == dst_info->type) return param;
1787
1788 switch (dst_info->type)
1789 {
1790 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1791 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1792 {
1793 int i;
1794 switch (param->type)
1795 {
1796 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1797 i = (int)param->d;
1798 break;
1799 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1800 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1801 i = (param->s) ? atoi(param->s) : 0;
1802 break;
1803 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1804 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1805 i = param->i;
1806 break;
1807 default:
1808 return NULL;
1809 }
1810 if (dst_info->type == EDJE_EXTERNAL_PARAM_TYPE_BOOL)
1811 i = !!i;
1812 param->type = dst_info->type;
1813 param->i = i;
1814 return param;
1815 }
1816
1817 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1818 {
1819 double d;
1820 switch (param->type)
1821 {
1822 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1823 d = (double)param->i;
1824 break;
1825 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1826 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1827 d = (param->s) ? atof(param->s) : 0.0;
1828 break;
1829 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1830 d = (double)param->i;
1831 break;
1832 default:
1833 return NULL;
1834 }
1835 param->type = dst_info->type;
1836 param->d = d;
1837 return param;
1838 }
1839
1840 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1841 {
1842 static char s[64];
1843 switch (param->type)
1844 {
1845 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1846 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1847 if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
1848 break;
1849 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1850 if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
1851 break;
1852 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1853 param->type = dst_info->type;
1854 return param;
1855 default:
1856 return NULL;
1857 }
1858 param->type = dst_info->type;
1859 param->s = s;
1860 return param;
1861 }
1862
1863 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1864 {
1865 static char s[64];
1866 const char *val;
1867 switch (param->type)
1868 {
1869 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1870 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1871 if (!snprintf(s, sizeof(s), "%i", param->i)) return NULL;
1872 val = s;
1873 break;
1874 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1875 if (!snprintf(s, sizeof(s), "%f", param->d)) return NULL;
1876 val = s;
1877 break;
1878 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1879 val = param->s;
1880 break;
1881 default:
1882 return NULL;
1883 }
1884
1885 param->type = dst_info->type;
1886 if (param->s != val) param->s = val;
1887 return param;
1888 }
1889
1890 default: return NULL;
1891 }
1892}
1893
1894static Eina_Bool
1895_edje_param_validate(const Edje_External_Param *param, const Edje_External_Param_Info *info)
1896{
1897 switch (info->type)
1898 {
1899 case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
1900 return ((param->i == 0) || (param->i == 1));
1901
1902 case EDJE_EXTERNAL_PARAM_TYPE_INT:
1903 if ((info->info.i.min != EDJE_EXTERNAL_INT_UNSET) &&
1904 (info->info.i.min > param->i))
1905 return EINA_FALSE;
1906
1907 if ((info->info.i.max != EDJE_EXTERNAL_INT_UNSET) &&
1908 (info->info.i.max < param->i))
1909 return EINA_FALSE;
1910
1911 return EINA_TRUE;
1912
1913 case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
1914 if ((info->info.d.min != EDJE_EXTERNAL_DOUBLE_UNSET) &&
1915 (info->info.d.min > param->d))
1916 return EINA_FALSE;
1917
1918 if ((info->info.d.max != EDJE_EXTERNAL_DOUBLE_UNSET) &&
1919 (info->info.d.max < param->d))
1920 return EINA_FALSE;
1921
1922 return EINA_TRUE;
1923
1924 case EDJE_EXTERNAL_PARAM_TYPE_STRING:
1925 if (!param->s) return EINA_FALSE;
1926 if (info->info.s.accept_fmt)
1927 INF("string 'accept_fmt' validation not implemented.");
1928 if (info->info.s.deny_fmt)
1929 INF("string 'deny_fmt' validation not implemented.");
1930 return EINA_TRUE;
1931
1932 case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
1933 {
1934 const char **itr = info->info.c.choices;
1935 if (!itr) return EINA_FALSE;
1936 for (; *itr; itr++)
1937 if (!strcmp(*itr, param->s))
1938 return EINA_TRUE;
1939 return EINA_FALSE;
1940 }
1941
1942 default: return EINA_FALSE;
1943 }
1944}
1945
1946static void
1947_edje_param_copy(Edje_Real_Part *src_part, const char *src_param, Edje_Real_Part *dst_part, const char *dst_param)
1948{
1949 Edje_External_Param val;
1950 const Edje_External_Param_Info *dst_info;
1951 void *free_ptr = NULL;
1952
1953 if ((!src_part) || (!src_param) || (!dst_part) || (!dst_param))
1954 return;
1955
1956 if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
1957 dst_info = _edje_external_param_info_get
1958 (dst_part->swallowed_object, dst_param);
1959 else
1960 dst_info = _edje_native_param_info_get(dst_part, dst_param);
1961
1962 if (!dst_info)
1963 {
1964 ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
1965 dst_param, dst_part->part->name);
1966 return;
1967 }
1968
1969 if (src_part->part->type == EDJE_PART_TYPE_EXTERNAL)
1970 {
1971 if (!_edje_param_external_get
1972 (src_part, src_param, &val))
1973 {
1974 ERR("cannot get parameter '%s' of part '%s'",
1975 src_param, src_part->part->name);
1976 return;
1977 }
1978 }
1979 else
1980 {
1981 if (!_edje_param_native_get(src_part, src_param, &val, &free_ptr))
1982 {
1983 ERR("cannot get parameter '%s' of part '%s'",
1984 src_param, src_part->part->name);
1985 return;
1986 }
1987 }
1988
1989 if (!_edje_param_convert(&val, dst_info))
1990 {
1991 ERR("cannot convert parameter type %s to requested type %s",
1992 edje_external_param_type_str(val.type),
1993 edje_external_param_type_str(dst_info->type));
1994 goto end;
1995 }
1996
1997 if (!_edje_param_validate(&val, dst_info))
1998 {
1999 ERR("incorrect parameter value failed validation for type %s",
2000 edje_external_param_type_str(dst_info->type));
2001 goto end;
2002 }
2003
2004 if (dst_part->part->type == EDJE_PART_TYPE_EXTERNAL)
2005 {
2006 val.name = dst_param;
2007 if (!_edje_external_param_set(NULL, dst_part, &val))
2008 {
2009 ERR("failed to set parameter '%s' (%s) of part '%s'",
2010 dst_param, edje_external_param_type_str(dst_info->type),
2011 dst_part->part->name);
2012 goto end;
2013 }
2014 }
2015 else
2016 {
2017 if (!_edje_param_native_set(dst_part, dst_param, &val))
2018 {
2019 ERR("failed to set parameter '%s' (%s) of part '%s'",
2020 dst_param, edje_external_param_type_str(dst_info->type),
2021 dst_part->part->name);
2022 goto end;
2023 }
2024 }
2025
2026 end:
2027 free(free_ptr);
2028}
2029
2030static void
2031_edje_param_set(Edje_Real_Part *part, const char *param, const char *value)
2032{
2033 Edje_External_Param val;
2034 const Edje_External_Param_Info *info;
2035
2036 if ((!part) || (!param) || (!value))
2037 return;
2038
2039 if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2040 info = _edje_external_param_info_get(part->swallowed_object, param);
2041 else
2042 info = _edje_native_param_info_get(part, param);
2043
2044 if (!info)
2045 {
2046 ERR("cannot copy, invalid destination parameter '%s' of part '%s'",
2047 param, part->part->name);
2048 return;
2049 }
2050
2051 val.name = "(temp)";
2052 val.type = EDJE_EXTERNAL_PARAM_TYPE_STRING;
2053 val.s = value;
2054
2055 if (!_edje_param_convert(&val, info))
2056 {
2057 ERR("cannot convert parameter type STRING to requested type %s",
2058 edje_external_param_type_str(info->type));
2059 return;
2060 }
2061
2062 if (!_edje_param_validate(&val, info))
2063 {
2064 ERR("incorrect parameter value failed validation for type %s",
2065 edje_external_param_type_str(info->type));
2066 return;
2067 }
2068
2069 if (part->part->type == EDJE_PART_TYPE_EXTERNAL)
2070 {
2071 val.name = param;
2072 if (!_edje_external_param_set(NULL, part, &val))
2073 {
2074 ERR("failed to set parameter '%s' (%s) of part '%s'",
2075 param, edje_external_param_type_str(info->type),
2076 part->part->name);
2077 return;
2078 }
2079 }
2080 else
2081 {
2082 if (!_edje_param_native_set(part, param, &val))
2083 {
2084 ERR("failed to set parameter '%s' (%s) of part '%s'",
2085 param, edje_external_param_type_str(info->type),
2086 part->part->name);
2087 return;
2088 }
2089 }
2090}