create rotation job and EAPI e_border_rotation_set
[platform/core/uifw/e17.git] / src / bin / e_widget.c
1 #include "e.h"
2
3 #define SMART_NAME     "e_widget"
4 #define API_ENTRY      E_Smart_Data * sd; sd = evas_object_smart_data_get(obj); if ((!obj) || (!sd) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), SMART_NAME)))
5 #define INTERNAL_ENTRY E_Smart_Data * sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
6 typedef struct _E_Smart_Data E_Smart_Data;
7
8 struct _E_Smart_Data
9 {
10    Evas_Object  *parent_obj;
11    Evas_Coord    x, y, w, h, minw, minh;
12    Eina_List    *subobjs;
13    Evas_Object  *resize_obj;
14    void          (*del_func)(Evas_Object *obj);
15    void          (*focus_func)(Evas_Object *obj);
16    void          (*activate_func)(Evas_Object *obj);
17    void          (*disable_func)(Evas_Object *obj);
18    void          (*on_focus_func)(void *data, Evas_Object *obj);
19    void         *on_focus_data;
20    void          (*on_change_func)(void *data, Evas_Object *obj);
21    void         *on_change_data;
22    void         *data;
23    unsigned char can_focus : 1;
24    unsigned char child_can_focus : 1;
25    unsigned char focused : 1;
26    unsigned char disabled : 1;
27 };
28
29 /* local subsystem functions */
30 static void _e_smart_reconfigure(E_Smart_Data *sd);
31 static void _e_smart_add(Evas_Object *obj);
32 static void _e_smart_del(Evas_Object *obj);
33 static void _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
34 static void _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
35 static void _e_smart_show(Evas_Object *obj);
36 static void _e_smart_hide(Evas_Object *obj);
37 static void _e_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
38 static void _e_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
39 static void _e_smart_clip_unset(Evas_Object *obj);
40 static void _e_smart_init(void);
41
42 /* local subsystem globals */
43 static Evas_Smart *_e_smart = NULL;
44
45 /* externally accessible functions */
46 EAPI Evas_Object *
47 e_widget_add(Evas *evas)
48 {
49    _e_smart_init();
50    return evas_object_smart_add(evas, _e_smart);
51 }
52
53 EAPI void
54 e_widget_del_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj))
55 {
56    API_ENTRY return;
57    sd->del_func = func;
58 }
59
60 EAPI void
61 e_widget_focus_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj))
62 {
63    API_ENTRY return;
64    sd->focus_func = func;
65 }
66
67 EAPI void
68 e_widget_activate_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj))
69 {
70    API_ENTRY return;
71    sd->activate_func = func;
72 }
73
74 EAPI void
75 e_widget_disable_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj))
76 {
77    API_ENTRY return;
78    sd->disable_func = func;
79 }
80
81 EAPI void
82 e_widget_on_focus_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data)
83 {
84    API_ENTRY return;
85    sd->on_focus_func = func;
86    sd->on_focus_data = data;
87 }
88
89 EAPI void
90 e_widget_on_change_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data)
91 {
92    API_ENTRY return;
93    sd->on_change_func = func;
94    sd->on_change_data = data;
95 }
96
97 EAPI void
98 e_widget_data_set(Evas_Object *obj, void *data)
99 {
100    API_ENTRY return;
101    sd->data = data;
102 }
103
104 EAPI void *
105 e_widget_data_get(Evas_Object *obj)
106 {
107    API_ENTRY return NULL;
108    return sd->data;
109 }
110
111 EAPI void
112 e_widget_size_min_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh)
113 {
114    API_ENTRY return;
115    if (minw >= 0) sd->minw = minw;
116    if (minh >= 0) sd->minh = minh;
117 }
118
119 EAPI void
120 e_widget_size_min_get(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
121 {
122    API_ENTRY return;
123    if (minw) *minw = sd->minw;
124    if (minh) *minh = sd->minh;
125 }
126
127 static void
128 _sub_obj_del(void *data,
129              Evas *e __UNUSED__,
130              Evas_Object *obj,
131              void *event_info __UNUSED__)
132 {
133    E_Smart_Data *sd = data;
134
135    sd->subobjs = eina_list_remove(sd->subobjs, obj);
136    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _sub_obj_del);
137 }
138
139 EAPI void
140 e_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj)
141 {
142    API_ENTRY return;
143
144    if (eina_list_data_find(sd->subobjs, sobj)) return;
145
146    sd->subobjs = eina_list_append(sd->subobjs, sobj);
147    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
148    if (!sd->child_can_focus)
149      {
150         if (e_widget_can_focus_get(sobj)) sd->child_can_focus = 1;
151      }
152    if (strcmp(evas_object_type_get(sobj), SMART_NAME)) return;
153
154    sd = evas_object_smart_data_get(sobj);
155    if (sd)
156      {
157         if (sd->parent_obj) e_widget_sub_object_del(sd->parent_obj, sobj);
158         sd->parent_obj = obj;
159      }
160    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
161 }
162
163 EAPI void
164 e_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj)
165 {
166    API_ENTRY return;
167    evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL, _sub_obj_del);
168    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
169    if (!sd->child_can_focus)
170      {
171         if (e_widget_can_focus_get(sobj)) sd->child_can_focus = 0;
172      }
173 }
174
175 EAPI void
176 e_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj)
177 {
178    API_ENTRY return;
179    if (sd->resize_obj) evas_object_smart_member_del(sd->resize_obj);
180    sd->resize_obj = sobj;
181    evas_object_smart_member_add(sobj, obj);
182    _e_smart_reconfigure(sd);
183 }
184
185 EAPI void
186 e_widget_can_focus_set(Evas_Object *obj, int can_focus)
187 {
188    API_ENTRY return;
189    sd->can_focus = can_focus;
190 }
191
192 EAPI int
193 e_widget_can_focus_get(Evas_Object *obj)
194 {
195    API_ENTRY return 0;
196    if (sd->disabled) return 0;
197    if (sd->can_focus) return 1;
198    if (sd->child_can_focus) return 1;
199    return 0;
200 }
201
202 EAPI int
203 e_widget_focus_get(Evas_Object *obj)
204 {
205    API_ENTRY return 0;
206    return sd->focused;
207 }
208
209 EAPI Evas_Object *
210 e_widget_focused_object_get(Evas_Object *obj)
211 {
212    Eina_List *l = NULL;
213    Evas_Object *sobj = NULL;
214
215    API_ENTRY return NULL;
216    if (!sd->focused) return NULL;
217    EINA_LIST_FOREACH(sd->subobjs, l, sobj)
218      {
219         sobj = e_widget_focused_object_get(sobj);
220         if (sobj) return sobj;
221      }
222    return obj;
223 }
224
225 EAPI int
226 e_widget_focus_jump(Evas_Object *obj, int forward)
227 {
228    API_ENTRY return 0;
229    if (!e_widget_can_focus_get(obj)) return 0;
230
231    /* if it has a focus func its an end-point widget like a button */
232    if (sd->focus_func)
233      {
234         if (!sd->focused) sd->focused = 1;
235         else sd->focused = 0;
236         sd->focus_func(obj);
237         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
238         return sd->focused;
239      }
240    /* its some container */
241    else
242      {
243         Eina_List *l = NULL;
244         Evas_Object *sobj = NULL;
245         int focus_next = 0;
246
247         if (!sd->focused)
248           {
249              e_widget_focus_set(obj, forward);
250              sd->focused = 1;
251              if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
252              return 1;
253           }
254         else
255           {
256              if (forward)
257                {
258                   EINA_LIST_FOREACH(sd->subobjs, l, sobj)
259                     {
260                        if (!e_widget_can_focus_get(sobj)) continue;
261                        if ((focus_next) && (!e_widget_disabled_get(sobj)))
262                          {
263                             /* the previous focused item was unfocused - so focus
264                              * the next one (that can be focused) */
265                             if (e_widget_focus_jump(sobj, forward))
266                               return 1;
267                             break;
268                          }
269                        else
270                          {
271                             if (e_widget_focus_get(sobj))
272                               {
273                                  /* jump to the next focused item or focus this item */
274                                  if (e_widget_focus_jump(sobj, forward))
275                                    return 1;
276                                  /* it returned 0 - it got to the last item and is past it */
277                                  focus_next = 1;
278                               }
279                          }
280                     }
281                }
282              else
283                {
284                   EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, sobj)
285                     {
286                        if (e_widget_can_focus_get(sobj))
287                          {
288                             if ((focus_next) &&
289                                 (!e_widget_disabled_get(sobj)))
290                               {
291                                  /* the previous focused item was unfocused - so focus
292                                   * the next one (that can be focused) */
293                                  if (e_widget_focus_jump(sobj, forward))
294                                    return 1;
295                                  else break;
296                               }
297                             else
298                               {
299                                  if (e_widget_focus_get(sobj))
300                                    {
301                                       /* jump to the next focused item or focus this item */
302                                       if (e_widget_focus_jump(sobj, forward))
303                                         return 1;
304                                       /* it returned 0 - it got to the last item and is past it */
305                                       focus_next = 1;
306                                    }
307                               }
308                          }
309                     }
310                }
311           }
312      }
313    /* no next item can be focused */
314    sd->focused = 0;
315    return 0;
316 }
317
318 EAPI void
319 e_widget_focus_set(Evas_Object *obj, int first)
320 {
321    API_ENTRY return;
322    if (!sd->focused)
323      {
324         sd->focused = 1;
325         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
326      }
327    if (sd->focus_func)
328      {
329         sd->focus_func(obj);
330         return;
331      }
332    else
333      {
334         Eina_List *l = NULL;
335         Evas_Object *sobj;
336
337         if (first)
338           {
339              EINA_LIST_FOREACH(sd->subobjs, l, sobj)
340                {
341                   if ((e_widget_can_focus_get(sobj)) &&
342                       (!e_widget_disabled_get(sobj)))
343                     {
344                        e_widget_focus_set(sobj, first);
345                        break;
346                     }
347                }
348           }
349         else
350           {
351              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, sobj)
352                {
353                   if ((e_widget_can_focus_get(sobj)) &&
354                       (!e_widget_disabled_get(sobj)))
355                     {
356                        e_widget_focus_set(sobj, first);
357                        break;
358                     }
359                }
360           }
361      }
362 }
363
364 EAPI Evas_Object *
365 e_widget_parent_get(Evas_Object *obj)
366 {
367    API_ENTRY return NULL;
368    return sd->parent_obj;
369 }
370
371 EAPI void
372 e_widget_focused_object_clear(Evas_Object *obj)
373 {
374    Eina_List *l = NULL;
375    Evas_Object *sobj = NULL;
376
377    API_ENTRY return;
378    if (!sd->focused) return;
379    sd->focused = 0;
380    EINA_LIST_FOREACH(sd->subobjs, l, sobj)
381      {
382         if (e_widget_focus_get(sobj))
383           {
384              e_widget_focused_object_clear(sobj);
385              break;
386           }
387      }
388    if (sd->focus_func) sd->focus_func(obj);
389 }
390
391 EAPI void
392 e_widget_focus_steal(Evas_Object *obj)
393 {
394    Evas_Object *parent = NULL, *o = NULL;
395
396    API_ENTRY return;
397    if ((sd->focused) || (sd->disabled) || (!sd->can_focus)) return;
398    parent = obj;
399    for (;; )
400      {
401         o = e_widget_parent_get(parent);
402         if (!o) break;
403         parent = o;
404      }
405    e_widget_focused_object_clear(parent);
406    parent = obj;
407    for (;; )
408      {
409         sd = evas_object_smart_data_get(parent);
410         sd->focused = 1;
411         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, parent);
412         o = e_widget_parent_get(parent);
413         if (!o) break;
414         parent = o;
415      }
416    sd = evas_object_smart_data_get(obj);
417    if (sd->focus_func) sd->focus_func(obj);
418 }
419
420 EAPI void
421 e_widget_activate(Evas_Object *obj)
422 {
423    API_ENTRY return;
424    e_widget_change(obj);
425    if (sd->activate_func) sd->activate_func(obj);
426 }
427
428 EAPI void
429 e_widget_change(Evas_Object *obj)
430 {
431    API_ENTRY return;
432    if (sd->parent_obj) e_widget_change(sd->parent_obj);
433    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
434 }
435
436 EAPI void
437 e_widget_disabled_set(Evas_Object *obj, int disabled)
438 {
439    API_ENTRY return;
440    if (sd->disabled == disabled) return;
441    sd->disabled = disabled;
442    if (sd->focused)
443      {
444         Evas_Object *o = NULL, *parent = NULL;
445
446         parent = obj;
447         for (;; )
448           {
449              o = e_widget_parent_get(parent);
450              if (!o) break;
451              parent = o;
452           }
453         e_widget_focus_jump(parent, 1);
454      }
455    if (sd->disable_func) sd->disable_func(obj);
456 }
457
458 EAPI int
459 e_widget_disabled_get(Evas_Object *obj)
460 {
461    API_ENTRY return 0;
462    return sd->disabled;
463 }
464
465 EAPI E_Pointer *
466 e_widget_pointer_get(Evas_Object *obj)
467 {
468    E_Win *win = NULL;
469
470    API_ENTRY return NULL;
471    win = e_win_evas_object_win_get(obj);
472    if (win) return win->pointer;
473    return NULL;
474 }
475
476 EAPI void
477 e_widget_size_min_resize(Evas_Object *obj)
478 {
479    API_ENTRY return;
480    evas_object_resize(obj, sd->minw, sd->minh);
481 }
482
483 /* local subsystem functions */
484 static void
485 _e_smart_reconfigure(E_Smart_Data *sd)
486 {
487    if (sd->resize_obj)
488      {
489         evas_object_move(sd->resize_obj, sd->x, sd->y);
490         evas_object_resize(sd->resize_obj, sd->w, sd->h);
491      }
492 }
493
494 static void
495 _e_smart_add(Evas_Object *obj)
496 {
497    E_Smart_Data *sd = NULL;
498
499    sd = calloc(1, sizeof(E_Smart_Data));
500    if (!sd) return;
501    sd->x = 0;
502    sd->y = 0;
503    sd->w = 0;
504    sd->h = 0;
505    sd->can_focus = 1;
506    evas_object_smart_data_set(obj, sd);
507 }
508
509 static void
510 _e_smart_del(Evas_Object *obj)
511 {
512    INTERNAL_ENTRY;
513
514    if (sd->del_func) sd->del_func(obj);
515    while (sd->subobjs)
516      {
517         Evas_Object *sobj = sd->subobjs->data;
518         /* DO NOT MACRO THIS!
519          * list gets reshuffled during object delete callback chain
520          * and breaks the world.
521          * BORKER CERTIFICATION: GOLD
522          * -discomfitor, 7/4/2012
523          */
524         sd->subobjs = eina_list_remove_list(sd->subobjs, sd->subobjs);
525         evas_object_del(sobj);
526      }
527    free(sd);
528 }
529
530 static void
531 _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
532 {
533    INTERNAL_ENTRY;
534    sd->x = x;
535    sd->y = y;
536    _e_smart_reconfigure(sd);
537 }
538
539 static void
540 _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
541 {
542    INTERNAL_ENTRY;
543    sd->w = w;
544    sd->h = h;
545    _e_smart_reconfigure(sd);
546 }
547
548 static void
549 _e_smart_show(Evas_Object *obj)
550 {
551    INTERNAL_ENTRY;
552    if (sd->resize_obj)
553      evas_object_show(sd->resize_obj);
554 }
555
556 static void
557 _e_smart_hide(Evas_Object *obj)
558 {
559    INTERNAL_ENTRY;
560    if (sd->resize_obj)
561      evas_object_hide(sd->resize_obj);
562 }
563
564 static void
565 _e_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
566 {
567    INTERNAL_ENTRY;
568    if (sd->resize_obj)
569      evas_object_color_set(sd->resize_obj, r, g, b, a);
570 }
571
572 static void
573 _e_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
574 {
575    INTERNAL_ENTRY;
576    if (sd->resize_obj)
577      evas_object_clip_set(sd->resize_obj, clip);
578 }
579
580 static void
581 _e_smart_clip_unset(Evas_Object *obj)
582 {
583    INTERNAL_ENTRY;
584    if (sd->resize_obj)
585      evas_object_clip_unset(sd->resize_obj);
586 }
587
588 /* never need to touch this */
589
590 static void
591 _e_smart_init(void)
592 {
593    if (_e_smart) return;
594    {
595       static const Evas_Smart_Class sc =
596       {
597          SMART_NAME,
598          EVAS_SMART_CLASS_VERSION,
599          _e_smart_add,
600          _e_smart_del,
601          _e_smart_move,
602          _e_smart_resize,
603          _e_smart_show,
604          _e_smart_hide,
605          _e_smart_color_set,
606          _e_smart_clip_set,
607          _e_smart_clip_unset,
608          NULL,
609          NULL,
610          NULL,
611          NULL,
612          NULL,
613          NULL,
614          NULL
615       };
616       _e_smart = evas_smart_class_new(&sc);
617    }
618 }
619