8206c914ab0b7ac71255c46b988fb40e6a732840
[framework/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 EAPI void
128 e_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj)
129 {
130    API_ENTRY return;
131    sd->subobjs = eina_list_append(sd->subobjs, sobj);
132    if (!sd->child_can_focus)
133      {
134         if (e_widget_can_focus_get(sobj)) sd->child_can_focus = 1;
135      }
136    if (!strcmp(evas_object_type_get(sobj), SMART_NAME))
137      {
138         sd = evas_object_smart_data_get(sobj);
139         if (sd)
140           {
141              if (sd->parent_obj) e_widget_sub_object_del(sd->parent_obj, sobj);
142              sd->parent_obj = obj;
143           }
144      }
145 }
146
147 EAPI void
148 e_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj)
149 {
150    API_ENTRY return;
151    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
152    if (!sd->child_can_focus)
153      {
154         if (e_widget_can_focus_get(sobj)) sd->child_can_focus = 0;
155      }
156 }
157
158 EAPI void
159 e_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj)
160 {
161    API_ENTRY return;
162    if (sd->resize_obj) evas_object_smart_member_del(sd->resize_obj);
163    sd->resize_obj = sobj;
164    evas_object_smart_member_add(sobj, obj);
165    _e_smart_reconfigure(sd);
166 }
167
168 EAPI void
169 e_widget_can_focus_set(Evas_Object *obj, int can_focus)
170 {
171    API_ENTRY return;
172    sd->can_focus = can_focus;
173 }
174
175 EAPI int
176 e_widget_can_focus_get(Evas_Object *obj)
177 {
178    API_ENTRY return 0;
179    if (sd->can_focus) return 1;
180    if (sd->child_can_focus) return 1;
181    return 0;
182 }
183
184 EAPI int
185 e_widget_focus_get(Evas_Object *obj)
186 {
187    API_ENTRY return 0;
188    return sd->focused;
189 }
190
191 EAPI Evas_Object *
192 e_widget_focused_object_get(Evas_Object *obj)
193 {
194    Eina_List *l = NULL;
195    Evas_Object *sobj = NULL;
196
197    API_ENTRY return NULL;
198    if (!sd->focused) return NULL;
199    EINA_LIST_FOREACH(sd->subobjs, l, sobj)
200      {
201         sobj = e_widget_focused_object_get(sobj);
202         if (sobj) return sobj;
203      }
204    return obj;
205 }
206
207 EAPI int
208 e_widget_focus_jump(Evas_Object *obj, int forward)
209 {
210    API_ENTRY return 0;
211    if (!e_widget_can_focus_get(obj)) return 0;
212
213    /* if it has a focus func its an end-point widget like a button */
214    if (sd->focus_func)
215      {
216         if (!sd->focused) sd->focused = 1;
217         else sd->focused = 0;
218         sd->focus_func(obj);
219         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
220         return sd->focused;
221      }
222    /* its some container */
223    else
224      {
225         Eina_List *l = NULL;
226         Evas_Object *sobj = NULL;
227         int focus_next = 0;
228
229         if (!sd->focused)
230           {
231              e_widget_focus_set(obj, forward);
232              sd->focused = 1;
233              if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
234              return 1;
235           }
236         else
237           {
238              if (forward)
239                {
240                   EINA_LIST_FOREACH(sd->subobjs, l, sobj)
241                     {
242                        if (e_widget_can_focus_get(sobj))
243                          {
244                             if ((focus_next) &&
245                                 (!e_widget_disabled_get(sobj)))
246                               {
247                                  /* the previous focused item was unfocused - so focus
248                                   * the next one (that can be focused) */
249                                  if (e_widget_focus_jump(sobj, forward)) 
250                                    return 1;
251                                  else break;
252                               }
253                             else
254                               {
255                                  if (e_widget_focus_get(sobj))
256                                    {
257                                       /* jump to the next focused item or focus this item */
258                                       if (e_widget_focus_jump(sobj, forward)) 
259                                         return 1;
260                                       /* it returned 0 - it got to the last item and is past it */
261                                       focus_next = 1;
262                                    }
263                               }
264                          }
265                     }
266                }
267              else
268                {
269                   EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, sobj)
270                     {
271                        if (e_widget_can_focus_get(sobj))
272                          {
273                             if ((focus_next) &&
274                                 (!e_widget_disabled_get(sobj)))
275                               {
276                                  /* the previous focused item was unfocused - so focus
277                                   * the next one (that can be focused) */
278                                  if (e_widget_focus_jump(sobj, forward)) 
279                                    return 1;
280                                  else break;
281                               }
282                             else
283                               {
284                                  if (e_widget_focus_get(sobj))
285                                    {
286                                       /* jump to the next focused item or focus this item */
287                                       if (e_widget_focus_jump(sobj, forward)) 
288                                         return 1;
289                                       /* it returned 0 - it got to the last item and is past it */
290                                       focus_next = 1;
291                                    }
292                               }
293                          }
294                     }
295                }
296           }
297      }
298    /* no next item can be focused */
299    sd->focused = 0;
300    return 0;
301 }
302
303 EAPI void
304 e_widget_focus_set(Evas_Object *obj, int first)
305 {
306    API_ENTRY return;
307    if (!sd->focused)
308      {
309         sd->focused = 1;
310         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
311      }
312    if (sd->focus_func)
313      {
314         sd->focus_func(obj);
315         return;
316      }
317    else
318      {
319         Eina_List *l = NULL;
320         Evas_Object *sobj;
321
322         if (first)
323           {
324              EINA_LIST_FOREACH(sd->subobjs, l, sobj)
325                {
326                   if ((e_widget_can_focus_get(sobj)) &&
327                       (!e_widget_disabled_get(sobj)))
328                     {
329                        e_widget_focus_set(sobj, first);
330                        break;
331                     }
332                }
333           }
334         else
335           {
336              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, sobj)
337                {
338                   if ((e_widget_can_focus_get(sobj)) &&
339                       (!e_widget_disabled_get(sobj)))
340                     {
341                        e_widget_focus_set(sobj, first);
342                        break;
343                     }
344                }
345           }
346      }
347 }
348
349 EAPI Evas_Object *
350 e_widget_parent_get(Evas_Object *obj)
351 {
352    API_ENTRY return NULL;
353    return sd->parent_obj;
354 }
355
356 EAPI void
357 e_widget_focused_object_clear(Evas_Object *obj)
358 {
359    Eina_List *l = NULL;
360    Evas_Object *sobj = NULL;
361
362    API_ENTRY return;
363    if (!sd->focused) return;
364    sd->focused = 0;
365    EINA_LIST_FOREACH(sd->subobjs, l, sobj)
366      {
367         if (e_widget_focus_get(sobj))
368           {
369              e_widget_focused_object_clear(sobj);
370              break;
371           }
372      }
373    if (sd->focus_func) sd->focus_func(obj);
374 }
375
376 EAPI void
377 e_widget_focus_steal(Evas_Object *obj)
378 {
379    Evas_Object *parent = NULL, *o = NULL;
380
381    API_ENTRY return;
382    if ((sd->focused) || (sd->disabled)) return;
383    parent = obj;
384    for (;;)
385      {
386         o = e_widget_parent_get(parent);
387         if (!o) break;
388         parent = o;
389      }
390    e_widget_focused_object_clear(parent);
391    parent = obj;
392    for (;;)
393      {
394         sd = evas_object_smart_data_get(parent);
395         sd->focused = 1;
396         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, parent);
397         o = e_widget_parent_get(parent);
398         if (!o) break;
399         parent = o;
400      }
401    sd = evas_object_smart_data_get(obj);
402    if (sd->focus_func) sd->focus_func(obj);
403 }
404
405 EAPI void
406 e_widget_activate(Evas_Object *obj)
407 {
408    API_ENTRY return;
409    e_widget_change(obj);
410    if (sd->activate_func) sd->activate_func(obj);
411 }
412
413 EAPI void
414 e_widget_change(Evas_Object *obj)
415 {
416    API_ENTRY return;
417    if (sd->parent_obj) e_widget_change(sd->parent_obj);
418    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
419 }
420
421 EAPI void
422 e_widget_disabled_set(Evas_Object *obj, int disabled)
423 {
424    API_ENTRY return;
425    if (sd->disabled == disabled) return;
426    sd->disabled = disabled;
427    if (sd->focused)
428      {
429         Evas_Object *o = NULL, *parent = NULL;
430
431         parent = obj;
432         for (;;)
433           {
434              o = e_widget_parent_get(parent);
435              if (!o) break;
436              parent = o;
437           }
438         e_widget_focus_jump(parent, 1);
439      }
440    if (sd->disable_func) sd->disable_func(obj);
441 }
442
443 EAPI int
444 e_widget_disabled_get(Evas_Object *obj)
445 {
446    API_ENTRY return 0;
447    return sd->disabled;
448 }
449
450 EAPI E_Pointer *
451 e_widget_pointer_get(Evas_Object *obj)
452 {
453    E_Win *win = NULL;
454
455    API_ENTRY return NULL;
456    win = e_win_evas_object_win_get(obj);
457    if (win) return win->pointer;
458    return NULL;
459 }
460
461 EAPI void
462 e_widget_size_min_resize(Evas_Object *obj)
463 {
464    API_ENTRY return;
465    evas_object_resize(obj, sd->minw, sd->minh);
466 }
467
468 /* local subsystem functions */
469 static void
470 _e_smart_reconfigure(E_Smart_Data *sd)
471 {
472    if (sd->resize_obj)
473      {
474         evas_object_move(sd->resize_obj, sd->x, sd->y);
475         evas_object_resize(sd->resize_obj, sd->w, sd->h);
476     }
477 }
478
479 static void
480 _e_smart_add(Evas_Object *obj)
481 {
482    E_Smart_Data *sd = NULL;
483
484    sd = calloc(1, sizeof(E_Smart_Data));
485    if (!sd) return;
486    sd->x = 0;
487    sd->y = 0;
488    sd->w = 0;
489    sd->h = 0;
490    sd->can_focus = 1;
491    evas_object_smart_data_set(obj, sd);
492 }
493
494 static void
495 _e_smart_del(Evas_Object *obj)
496 {
497    INTERNAL_ENTRY;
498    if (sd->del_func) sd->del_func(obj);
499    E_FREE_LIST(sd->subobjs, evas_object_del);
500    free(sd);
501 }
502
503 static void
504 _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
505 {
506    INTERNAL_ENTRY;
507    sd->x = x;
508    sd->y = y;
509    _e_smart_reconfigure(sd);
510 }
511
512 static void
513 _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
514 {
515    INTERNAL_ENTRY;
516    sd->w = w;
517    sd->h = h;
518    _e_smart_reconfigure(sd);
519 }
520
521 static void
522 _e_smart_show(Evas_Object *obj)
523 {
524    INTERNAL_ENTRY;
525    if (sd->resize_obj)
526      evas_object_show(sd->resize_obj);
527 }
528
529 static void
530 _e_smart_hide(Evas_Object *obj)
531 {
532    INTERNAL_ENTRY;
533    if (sd->resize_obj)
534      evas_object_hide(sd->resize_obj);
535 }
536
537 static void
538 _e_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
539 {
540    INTERNAL_ENTRY;
541    if (sd->resize_obj)
542      evas_object_color_set(sd->resize_obj, r, g, b, a);
543 }
544
545 static void
546 _e_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
547 {
548    INTERNAL_ENTRY;
549    if (sd->resize_obj)
550      evas_object_clip_set(sd->resize_obj, clip);
551 }
552
553 static void
554 _e_smart_clip_unset(Evas_Object *obj)
555 {
556    INTERNAL_ENTRY;
557    if (sd->resize_obj)
558      evas_object_clip_unset(sd->resize_obj);
559 }  
560
561 /* never need to touch this */
562
563 static void
564 _e_smart_init(void)
565 {
566    if (_e_smart) return;
567      {
568         static const Evas_Smart_Class sc =
569           {
570              SMART_NAME,
571                EVAS_SMART_CLASS_VERSION,
572                _e_smart_add,
573                _e_smart_del, 
574                _e_smart_move,
575                _e_smart_resize,
576                _e_smart_show,
577                _e_smart_hide,
578                _e_smart_color_set,
579                _e_smart_clip_set,
580                _e_smart_clip_unset,
581                NULL,
582                NULL,
583                NULL,
584                NULL, 
585                NULL, 
586                NULL, 
587                NULL
588           };
589         _e_smart = evas_smart_class_new(&sc);
590      }
591 }