aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/examples/evas-smart-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/examples/evas-smart-object.c')
-rw-r--r--libraries/evas/src/examples/evas-smart-object.c708
1 files changed, 708 insertions, 0 deletions
diff --git a/libraries/evas/src/examples/evas-smart-object.c b/libraries/evas/src/examples/evas-smart-object.c
new file mode 100644
index 0000000..8a36b62
--- /dev/null
+++ b/libraries/evas/src/examples/evas-smart-object.c
@@ -0,0 +1,708 @@
1/**
2 * Simple Evas example illustrating a custom Evas smart object
3 *
4 * You'll need at least one engine built for it (excluding the buffer
5 * one). See stdout/stderr for output.
6 *
7 * @verbatim
8 * gcc -o evas-smart-object evas-smart-object.c `pkg-config --libs --cflags evas ecore ecore-evas`
9 * @endverbatim
10 */
11
12#ifdef HAVE_CONFIG_H
13
14#include "config.h"
15#else
16
17#define PACKAGE_EXAMPLES_DIR "."
18#define __UNUSED__
19
20#endif
21
22#include <Ecore.h>
23#include <Ecore_Evas.h>
24#include <stdio.h>
25#include <errno.h>
26
27#define WIDTH (320)
28#define HEIGHT (240)
29
30static const char *commands = \
31 "commands are:\n"
32 "\tl - insert child rectangle on the left\n"
33 "\tr - insert child rectangle on the right\n"
34 "\tw - remove and delete all members from the smart object\n"
35 "\tright arrow - move smart object to the right\n"
36 "\tleft arrow - move smart object to the left\n"
37 "\tup arrow - move smart object up\n"
38 "\tdown arrow - move smart object down\n"
39 "\td - decrease smart object's size\n"
40 "\ti - increase smart object's size\n"
41 "\tc - change smart object's clipper color\n"
42 "\th - print help\n";
43
44#define WHITE {255, 255, 255, 255}
45#define RED {255, 0, 0, 255}
46#define GREEN {0, 255, 0, 255}
47#define BLUE {0, 0, 255, 255}
48
49struct test_data
50{
51 Ecore_Evas *ee;
52 Evas *evas;
53 Evas_Object *smt, *bg, *clipper, *rects[2];
54};
55
56struct color_tuple
57{
58 int r, g, b, a;
59} clipper_colors[4] = {WHITE, RED, GREEN, BLUE};
60int cur_color = 0;
61
62static const char *
63_index_to_color(int i)
64{
65 switch (i)
66 {
67 case 0:
68 return "WHITE (default)";
69
70 case 1:
71 return "RED";
72
73 case 2:
74 return "GREEN";
75
76 case 3:
77 return "BLUE";
78
79 default:
80 return "other";
81 }
82}
83
84static struct test_data d = {0};
85static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
86
87#define _evas_smart_example_type "Evas_Smart_Example"
88#define EVT_CHILDREN_NUMBER_CHANGED "children,changed"
89
90static const Evas_Smart_Cb_Description _smart_callbacks[] =
91{
92 {EVT_CHILDREN_NUMBER_CHANGED, "i"},
93 {NULL, NULL}
94};
95
96typedef struct _Evas_Smart_Example_Data Evas_Smart_Example_Data;
97/*
98 * This structure augments clipped smart object's instance data,
99 * providing extra members required by our example smart object's
100 * implementation.
101 */
102struct _Evas_Smart_Example_Data
103{
104 Evas_Object_Smart_Clipped_Data base;
105 Evas_Object *children[2], *border;
106 int child_count;
107};
108
109#define EVAS_SMART_EXAMPLE_DATA_GET(o, ptr) \
110 Evas_Smart_Example_Data * ptr = evas_object_smart_data_get(o)
111
112#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, ptr) \
113 EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
114 if (!ptr) \
115 { \
116 fprintf(stderr, "No widget data for object %p (%s)!", \
117 o, evas_object_type_get(o)); \
118 fflush(stderr); \
119 abort(); \
120 return; \
121 }
122
123#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
124 EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
125 if (!ptr) \
126 { \
127 fprintf(stderr, "No widget data for object %p (%s)!", \
128 o, evas_object_type_get(o)); \
129 fflush(stderr); \
130 abort(); \
131 return val; \
132 }
133
134EVAS_SMART_SUBCLASS_NEW(_evas_smart_example_type, _evas_smart_example,
135 Evas_Smart_Class, Evas_Smart_Class,
136 evas_object_smart_clipped_class_get, _smart_callbacks);
137
138static void
139_on_destroy(Ecore_Evas *ee __UNUSED__)
140{
141 ecore_main_loop_quit();
142}
143
144/* here just to keep our example's window size and background image's
145 * size in synchrony */
146static void
147_canvas_resize_cb(Ecore_Evas *ee)
148{
149 int w, h;
150
151 ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
152 evas_object_resize(d.bg, w, h);
153}
154
155static void
156_on_child_del(void *data,
157 Evas *evas __UNUSED__,
158 Evas_Object *o,
159 void *einfo __UNUSED__)
160{
161 Evas_Object *example_smart = data;
162 int index;
163
164 EVAS_SMART_EXAMPLE_DATA_GET(example_smart, priv);
165
166 index = (int)evas_object_data_get(o, "index");
167 index--;
168
169 priv->children[index] = NULL;
170
171 evas_object_smart_member_del(o);
172 evas_object_smart_changed(example_smart);
173}
174
175static void
176_evas_smart_example_child_callbacks_unregister(Evas_Object *obj)
177{
178 evas_object_data_set(obj, "index", NULL);
179 evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE, _on_child_del);
180}
181
182static void
183_evas_smart_example_child_callbacks_register(Evas_Object *o,
184 Evas_Object *child,
185 int index)
186{
187 evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _on_child_del, o);
188 evas_object_data_set(child, "index", (void *)(++index));
189}
190
191/* create and setup a new example smart object's internals */
192static void
193_evas_smart_example_smart_add(Evas_Object *o)
194{
195 EVAS_SMART_DATA_ALLOC(o, Evas_Smart_Example_Data);
196
197 /* this is a border around the smart object's area, delimiting it */
198 priv->border = evas_object_image_filled_add(evas_object_evas_get(o));
199 evas_object_image_file_set(priv->border, border_img_path, NULL);
200 evas_object_image_border_set(priv->border, 3, 3, 3, 3);
201 evas_object_image_border_center_fill_set(
202 priv->border, EVAS_BORDER_FILL_NONE);
203 evas_object_smart_member_add(priv->border, o);
204
205 _evas_smart_example_parent_sc->add(o);
206}
207
208static void
209_evas_smart_example_smart_del(Evas_Object *o)
210{
211 EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
212
213 if (priv->children[0])
214 {
215 _evas_smart_example_child_callbacks_unregister(priv->children[0]);
216 priv->children[0] = NULL;
217 }
218
219 if (priv->children[1])
220 {
221 _evas_smart_example_child_callbacks_unregister(priv->children[1]);
222 priv->children[1] = NULL;
223 }
224
225 _evas_smart_example_parent_sc->del(o);
226}
227
228static void
229_evas_smart_example_smart_show(Evas_Object *o)
230{
231 EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
232
233 if (priv->children[0]) evas_object_show(priv->children[0]);
234 if (priv->children[1]) evas_object_show(priv->children[1]);
235 evas_object_show(priv->border);
236
237 _evas_smart_example_parent_sc->show(o);
238}
239
240static void
241_evas_smart_example_smart_hide(Evas_Object *o)
242{
243 EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
244
245 if (priv->children[0]) evas_object_hide(priv->children[0]);
246 if (priv->children[1]) evas_object_hide(priv->children[1]);
247 evas_object_hide(priv->border);
248
249 _evas_smart_example_parent_sc->hide(o);
250}
251
252static void
253_evas_smart_example_smart_resize(Evas_Object *o,
254 Evas_Coord w,
255 Evas_Coord h)
256{
257 Evas_Coord ow, oh;
258 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
259 if ((ow == w) && (oh == h)) return;
260
261 /* this will trigger recalculation */
262 evas_object_smart_changed(o);
263}
264
265/* act on child objects' properties, before rendering */
266static void
267_evas_smart_example_smart_calculate(Evas_Object *o)
268{
269 Evas_Coord x, y, w, h;
270
271 EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, priv);
272 evas_object_geometry_get(o, &x, &y, &w, &h);
273
274 evas_object_resize(priv->border, w, h);
275 evas_object_move(priv->border, x, y);
276
277 if (priv->children[0])
278 {
279 evas_object_move(priv->children[0], x + 3, y + 3);
280 evas_object_resize(priv->children[0], (w / 2) - 3, (h / 2) - 3);
281 }
282
283 if (priv->children[1])
284 {
285 evas_object_move(priv->children[1], x + (w / 2), y + (h / 2));
286 evas_object_resize(priv->children[1], (w / 2) - 3, (h / 2) - 3);
287 }
288}
289
290/* setting our smart interface */
291static void
292_evas_smart_example_smart_set_user(Evas_Smart_Class *sc)
293{
294 /* specializing these two */
295 sc->add = _evas_smart_example_smart_add;
296 sc->del = _evas_smart_example_smart_del;
297 sc->show = _evas_smart_example_smart_show;
298 sc->hide = _evas_smart_example_smart_hide;
299
300 /* clipped smart object has no hook on resizes or calculations */
301 sc->resize = _evas_smart_example_smart_resize;
302 sc->calculate = _evas_smart_example_smart_calculate;
303}
304
305/* BEGINS example smart object's own interface */
306
307/* add a new example smart object to a canvas */
308Evas_Object *
309evas_smart_example_add(Evas *evas)
310{
311 return evas_object_smart_add(evas, _evas_smart_example_smart_class_new());
312}
313
314static void
315_evas_smart_example_remove_do(Evas_Smart_Example_Data *priv,
316 Evas_Object *child,
317 int index)
318{
319 priv->children[index] = NULL;
320 priv->child_count--;
321 _evas_smart_example_child_callbacks_unregister(child);
322 evas_object_smart_member_del(child);
323}
324
325/* remove a child element, return its pointer (or NULL on errors) */
326Evas_Object *
327evas_smart_example_remove(Evas_Object *o,
328 Evas_Object *child)
329{
330 int index;
331
332 EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
333
334 if (priv->children[0] != child && priv->children[1] != child)
335 {
336 fprintf(stderr, "You are trying to remove something not belonging to"
337 " the example smart object!\n");
338 return NULL;
339 }
340
341 index = (int)evas_object_data_get(child, "index");
342 index--;
343
344 _evas_smart_example_remove_do(priv, child, index);
345
346 evas_object_smart_callback_call(
347 o, EVT_CHILDREN_NUMBER_CHANGED, (void *)priv->child_count);
348 evas_object_smart_changed(o);
349
350 return child;
351}
352
353/* set to return any previous object set to the left position of the
354 * smart object or NULL, if any (or on errors) */
355Evas_Object *
356evas_smart_example_set_left(Evas_Object *o,
357 Evas_Object *child)
358{
359 Evas_Object *ret = NULL;
360
361 EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
362 if (!child)
363 return NULL;
364
365 if (priv->children[1] == child)
366 {
367 fprintf(stderr, "You mustn't place a child on both slots of"
368 " the example smart object!\n");
369 return NULL;
370 }
371
372 if (priv->children[0])
373 {
374 if (priv->children[0] != child)
375 {
376 ret = priv->children[0];
377 _evas_smart_example_remove_do(priv, priv->children[0], 0);
378 }
379 else return child;
380 }
381
382 priv->children[0] = child;
383 _evas_smart_example_child_callbacks_register(o, child, 0);
384 evas_object_smart_member_add(child, o);
385 evas_object_smart_changed(o);
386
387 priv->child_count++;
388 if (!ret)
389 {
390 evas_object_smart_callback_call(
391 o, EVT_CHILDREN_NUMBER_CHANGED, (void *)priv->child_count);
392 }
393
394 return ret;
395}
396
397/* set to return any previous object set to the right position of the
398 * smart object or NULL, if any (or on errors) */
399Evas_Object *
400evas_smart_example_set_right(Evas_Object *o,
401 Evas_Object *child)
402{
403 Evas_Object *ret = NULL;
404
405 EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
406 if (!child)
407 return NULL;
408
409 if (priv->children[0] == child)
410 {
411 fprintf(stderr, "You mustn't place a child on both slots of"
412 " the example smart object!\n");
413 return NULL;
414 }
415
416 if (priv->children[1])
417 {
418 if (priv->children[1] != child)
419 {
420 ret = priv->children[1];
421 _evas_smart_example_remove_do(priv, priv->children[1], 1);
422 }
423 else return child;
424 }
425
426 priv->children[1] = child;
427 _evas_smart_example_child_callbacks_register(o, child, 1);
428 evas_object_smart_member_add(child, o);
429 evas_object_smart_changed(o);
430
431 priv->child_count++;
432 if (!ret)
433 {
434 evas_object_smart_callback_call(
435 o, EVT_CHILDREN_NUMBER_CHANGED, (void *)priv->child_count);
436 }
437
438 return ret;
439}
440
441/* END OF example smart object's own interface */
442
443static void
444_on_keydown(void *data __UNUSED__,
445 Evas *evas __UNUSED__,
446 Evas_Object *o __UNUSED__,
447 void *einfo)
448{
449 Evas_Event_Key_Down *ev = einfo;
450
451 if (strcmp(ev->keyname, "h") == 0) /* print help */
452 {
453 fprintf(stdout, commands);
454 return;
455 }
456
457 if (strcmp(ev->keyname, "w") == 0) /* clear out smart object (WRT members) */
458 {
459 if (d.rects[0])
460 {
461 evas_smart_example_remove(d.smt, d.rects[0]);
462 evas_object_del(d.rects[0]);
463 }
464 if (d.rects[1])
465 {
466 evas_smart_example_remove(d.smt, d.rects[1]);
467 evas_object_del(d.rects[1]);
468 }
469
470 memset(d.rects, 0, sizeof(d.rects));
471
472 fprintf(stdout, "Deleting all members of the smart object.\n");
473
474 return;
475 }
476
477 if (strcmp(ev->keyname, "l") == 0) /* insert random colored
478 * rectangle on the left */
479 {
480 Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
481 evas_object_color_set(
482 rect, rand() % 255, rand() % 255, rand() % 255, 255);
483 evas_object_show(rect);
484
485 prev = evas_smart_example_set_left(d.smt, rect);
486 d.rects[0] = rect;
487
488 fprintf(stdout, "Setting smart object's left spot with a new"
489 " rectangle.\n");
490 fprintf(stdout, "Checking its new smart object parent: %s\n",
491 evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
492 "Failure!");
493 if (prev)
494 {
495 int r, g, b;
496
497 evas_object_color_get(prev, &r, &g, &b, NULL);
498 fprintf(stdout, "Deleting previous left child,"
499 " which had colors (%d, %d, %d)\n", r, g, b);
500 evas_object_del(prev);
501 }
502
503 return;
504 }
505
506 if (strcmp(ev->keyname, "r") == 0) /* insert random colored
507 * rectangle on the right */
508 {
509 Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
510 evas_object_color_set(
511 rect, rand() % 255, rand() % 255, rand() % 255, 255);
512 evas_object_show(rect);
513
514 prev = evas_smart_example_set_right(d.smt, rect);
515 d.rects[1] = rect;
516
517 fprintf(stdout, "Setting smart object's right spot with a new"
518 " rectangle.\n");
519 fprintf(stdout, "Checking its new smart object parent: %s\n",
520 evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
521 "Failure!");
522 if (prev)
523 {
524 int r, g, b;
525
526 evas_object_color_get(prev, &r, &g, &b, NULL);
527 fprintf(stdout, "Deleting previous right child,"
528 " which had colors (%d, %d, %d)\n", r, g, b);
529 evas_object_del(prev);
530 }
531
532 return;
533 }
534
535 /* move smart object along the canvas */
536 if (strcmp(ev->keyname, "Right") == 0 || strcmp(ev->keyname, "Left") == 0 ||
537 strcmp(ev->keyname, "Up") == 0 || strcmp(ev->keyname, "Down") == 0)
538 {
539 Evas_Coord x, y;
540
541 evas_object_geometry_get(d.smt, &x, &y, NULL, NULL);
542
543 switch (ev->keyname[0])
544 {
545 case 'R':
546 x += 20;
547 break;
548
549 case 'L':
550 x -= 20;
551 break;
552
553 case 'U':
554 y -= 20;
555 break;
556
557 case 'D':
558 y += 20;
559 break;
560 }
561
562 evas_object_move(d.smt, x, y);
563
564 return;
565 }
566
567 /* increase smart object's size */
568 if (strcmp(ev->keyname, "i") == 0)
569 {
570 Evas_Coord w, h;
571
572 evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
573
574 w *= 1.1;
575 h *= 1.1;
576
577 evas_object_resize(d.smt, w, h);
578
579 return;
580 }
581
582 /* decrease smart object's size */
583 if (strcmp(ev->keyname, "d") == 0)
584 {
585 Evas_Coord w, h;
586
587 evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
588
589 w *= 0.9;
590 h *= 0.9;
591
592 evas_object_resize(d.smt, w, h);
593
594 return;
595 }
596
597 /* change smart object's clipper color */
598 if (strcmp(ev->keyname, "c") == 0)
599 {
600 cur_color = (cur_color + 1) % 4;
601
602 evas_object_color_set(
603 d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
604 clipper_colors[cur_color].b, clipper_colors[cur_color].a);
605
606 fprintf (stderr, "Changing clipper's color to %s\n",
607 _index_to_color(cur_color));
608
609 return;
610 }
611}
612
613static void /* callback on number of member objects changed */
614_on_example_smart_object_child_num_change(void *data __UNUSED__,
615 Evas_Object *obj __UNUSED__,
616 void *event_info)
617{
618 fprintf(stdout, "Number of child members on our example smart"
619 " object changed to %d\n", (int)event_info);
620}
621
622int
623main(void)
624{
625 const Evas_Smart_Cb_Description **descriptions;
626 unsigned int count;
627 Eina_Bool ret;
628
629 srand(time(NULL));
630
631 if (!ecore_evas_init())
632 return EXIT_FAILURE;
633
634 /* this will give you a window with an Evas canvas under the first
635 * engine available */
636 d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
637 if (!d.ee)
638 goto error;
639
640 ecore_evas_callback_destroy_set(d.ee, _on_destroy);
641 ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
642 ecore_evas_show(d.ee);
643
644 /* the canvas pointer, de facto */
645 d.evas = ecore_evas_get(d.ee);
646
647 d.bg = evas_object_rectangle_add(d.evas);
648 evas_object_color_set(d.bg, 255, 255, 255, 255);
649 evas_object_move(d.bg, 0, 0);
650 evas_object_resize(d.bg, WIDTH, HEIGHT);
651 evas_object_show(d.bg);
652
653 d.smt = evas_smart_example_add(d.evas);
654 evas_object_move(d.smt, WIDTH / 4, HEIGHT / 4);
655 evas_object_resize(d.smt, WIDTH / 2, HEIGHT / 2);
656 evas_object_show(d.smt);
657
658 ret = evas_object_smart_type_check(d.smt, _evas_smart_example_type);
659 fprintf(stdout, "Adding smart object of type \"%s\" to the canvas: %s.\n",
660 _evas_smart_example_type, ret ? "success" : "failure");
661
662 d.clipper = evas_object_smart_clipped_clipper_get(d.smt);
663 fprintf(stdout, "Checking if clipped smart object's clipper is a "
664 "\"static\" one: %s\n", evas_object_static_clip_get(
665 d.clipper) ? "yes" : "no");
666
667 evas_object_color_set(
668 d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
669 clipper_colors[cur_color].b, clipper_colors[cur_color].a);
670
671 evas_object_smart_callbacks_descriptions_get(
672 d.smt, &descriptions, &count, NULL, NULL);
673
674 for (; *descriptions; descriptions++)
675 {
676 fprintf(stdout, "We've found a smart callback on the smart object!"
677 "\n\tname: %s\n\ttype: %s\n", (*descriptions)->name,
678 (*descriptions)->type);
679
680 if (strcmp((*descriptions)->type, "i")) continue;
681 /* we know we don't have other types of smart callbacks
682 * here, just playing with it */
683
684 /* for now, we know the only one callback is the one
685 * reporting number of member objects changed on the
686 * example smart object */
687 evas_object_smart_callback_add(
688 d.smt, (*descriptions)->name,
689 _on_example_smart_object_child_num_change, NULL);
690 }
691
692 evas_object_focus_set(d.bg, EINA_TRUE);
693 evas_object_event_callback_add(
694 d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
695
696 fprintf(stdout, commands);
697 ecore_main_loop_begin();
698
699 ecore_evas_free(d.ee);
700 ecore_evas_shutdown();
701 return 0;
702
703error:
704 fprintf(stderr, "you got to have at least one evas engine built and linked"
705 " up to ecore-evas for this example to run properly.\n");
706 ecore_evas_shutdown();
707 return -1;
708}