Tizen 2.1 base
[framework/uifw/elementary.git] / src / lib / elm_access.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char ACCESS_SMART_NAME[] = "elm_access";
5
6 ELM_INTERNAL_SMART_SUBCLASS_NEW
7   (ACCESS_SMART_NAME, _elm_access, Elm_Widget_Smart_Class,
8   Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
9
10 static Evas_Object * _elm_access_add(Evas_Object *parent);
11
12 static void
13 _elm_access_smart_add(Evas_Object *obj)
14 {
15    EVAS_SMART_DATA_ALLOC(obj, Elm_Widget_Smart_Data);
16    ELM_WIDGET_CLASS(_elm_access_parent_sc)->base.add(obj);
17
18    elm_widget_can_focus_set(obj, EINA_TRUE);
19 }
20
21 static Eina_Bool
22 _elm_access_smart_on_focus(Evas_Object *obj)
23 {
24    evas_object_focus_set(obj, elm_widget_focus_get(obj));
25
26    return EINA_TRUE;
27 }
28
29 static Eina_Bool
30 _elm_access_smart_activate(Evas_Object *obj, Elm_Activate act)
31 {
32    if (act != ELM_ACTIVATE_DEFAULT) return EINA_FALSE;
33
34    Elm_Access_Info *ac = evas_object_data_get(obj, "_elm_access");
35    if (!ac) return EINA_FALSE;
36
37    if (ac->activate)
38      ac->activate(ac->activate_data, ac->part_object,
39                   (Elm_Object_Item *)ac->widget_item);
40
41    return EINA_TRUE;
42 }
43
44 static void
45 _elm_access_smart_set_user(Elm_Widget_Smart_Class *sc)
46 {
47    sc->base.add = _elm_access_smart_add;
48
49    /* not a 'focus chain manager' */
50    sc->focus_next = NULL;
51    sc->focus_direction = NULL;
52    sc->on_focus = _elm_access_smart_on_focus;
53    sc->activate = _elm_access_smart_activate;
54
55    return;
56 }
57
58 typedef struct _Mod_Api Mod_Api;
59
60 struct _Mod_Api
61 {
62    void (*out_read) (const char *txt);
63    void (*out_read_done) (void);
64    void (*out_cancel) (void);
65    void (*out_done_callback_set) (void (*func) (void *data), const void *data);
66 };
67
68 static int initted = 0;
69 static Mod_Api *mapi = NULL;
70
71 static void
72 _access_init(void)
73 {
74    Elm_Module *m;
75    initted++;
76    if (initted > 1) return;
77    if (!(m = _elm_module_find_as("access/api"))) return;
78    m->api = malloc(sizeof(Mod_Api));
79    if (!m->api) return;
80    m->init_func(m);
81    ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
82       _elm_module_symbol_get(m, "out_read");
83    ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
84       _elm_module_symbol_get(m, "out_read_done");
85    ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
86       _elm_module_symbol_get(m, "out_cancel");
87    ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
88       _elm_module_symbol_get(m, "out_done_callback_set");
89    mapi = m->api;
90 }
91
92 static Elm_Access_Item *
93 _access_add_set(Elm_Access_Info *ac, int type)
94 {
95    Elm_Access_Item *ai;
96    Eina_List *l;
97
98    if (!ac) return NULL;
99    EINA_LIST_FOREACH(ac->items, l, ai)
100      {
101         if (ai->type == type)
102           {
103              if (!ai->func)
104                {
105                   if (ai->data) eina_stringshare_del(ai->data);
106                }
107              ai->func = NULL;
108              ai->data = NULL;
109              return ai;
110           }
111      }
112    ai = calloc(1, sizeof(Elm_Access_Item));
113    ai->type = type;
114    ac->items = eina_list_prepend(ac->items, ai);
115    return ai;
116 }
117
118 static Eina_Bool
119 _access_obj_over_timeout_cb(void *data)
120 {
121    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
122    if (!ac) return EINA_FALSE;
123    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
124      {
125         if (ac->on_highlight) ac->on_highlight(ac->on_highlight_data);
126         _elm_access_object_hilight(data);
127         _elm_access_read(ac, ELM_ACCESS_CANCEL, data);
128         _elm_access_read(ac, ELM_ACCESS_INFO,   data);
129         _elm_access_read(ac, ELM_ACCESS_TYPE,   data);
130         _elm_access_read(ac, ELM_ACCESS_STATE,  data);
131         _elm_access_read(ac, ELM_ACCESS_CONTEXT_INFO,   data);
132         _elm_access_read(ac, ELM_ACCESS_DONE,   data);
133      }
134    ac->delay_timer = NULL;
135    return EINA_FALSE;
136 }
137
138 static void
139 _access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
140 {
141    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
142    if (!ac) return;
143
144    if (ac->delay_timer)
145      {
146         ecore_timer_del(ac->delay_timer);
147         ac->delay_timer = NULL;
148      }
149    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
150       ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
151 }
152
153 static void
154 _access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
155 {
156    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
157    if (!ac) return;
158    _elm_access_object_unhilight(data);
159    if (ac->delay_timer)
160      {
161         ecore_timer_del(ac->delay_timer);
162         ac->delay_timer = NULL;
163      }
164 }
165
166 static void
167 _access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
168 {
169    _elm_access_object_unregister(data, obj);
170
171    // _elm_access_edje_object_part_object_register(); set below object data
172    evas_object_data_del(obj, "_part_access_obj");
173 }
174
175 static void
176 _access_read_done(void *data __UNUSED__)
177 {
178    printf("read done\n");
179    // FIXME: produce event here
180 }
181
182 static void
183 _access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
184 {
185    Ecore_Timer *t;
186
187    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
188                                        _access_2nd_click_del_cb, NULL);
189    t = evas_object_data_get(obj, "_elm_2nd_timeout");
190    if (t)
191      {
192         ecore_timer_del(t);
193         evas_object_data_del(obj, "_elm_2nd_timeout");
194      }
195 }
196
197 static Eina_Bool
198 _access_2nd_click_timeout_cb(void *data)
199 {
200    evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
201                                        _access_2nd_click_del_cb, NULL);
202    evas_object_data_del(data, "_elm_2nd_timeout");
203    return EINA_FALSE;
204 }
205
206 static void
207 _access_obj_hilight_del_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
208 {
209    _elm_access_object_hilight_disable(e);
210 }
211
212 static void
213 _access_obj_hilight_hide_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
214 {
215    _elm_access_object_hilight_disable(e);
216 }
217
218 static void
219 _access_obj_hilight_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
220 {
221    Evas_Coord x, y;
222    Evas_Object *o;
223
224    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
225    if (!o) return;
226    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
227    evas_object_move(o, x, y);
228 }
229
230 static void
231 _access_obj_hilight_resize_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
232 {
233    Evas_Coord w, h;
234    Evas_Object *o;
235
236    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
237    if (!o) return;
238    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
239    evas_object_resize(o, w, h);
240 }
241
242 static Evas_Object *
243 _access_highlight_object_get(Evas_Object *obj)
244 {
245    Evas_Object *o, *ho;
246
247    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
248    if (!o) return NULL;
249
250    ho = evas_object_data_get(o, "_elm_access_target");
251
252    return ho;
253 }
254
255 //-------------------------------------------------------------------------//
256 EAPI void
257 _elm_access_highlight_set(Evas_Object* obj)
258 {
259    _access_obj_over_timeout_cb(obj);
260 }
261
262 EAPI void
263 _elm_access_clear(Elm_Access_Info *ac)
264 {
265    Elm_Access_Item *ai;
266
267    if (!ac) return;
268    if (ac->delay_timer)
269      {
270         ecore_timer_del(ac->delay_timer);
271         ac->delay_timer = NULL;
272      }
273    EINA_LIST_FREE(ac->items, ai)
274      {
275         if (!ai->func)
276           {
277              if (ai->data) eina_stringshare_del(ai->data);
278           }
279         free(ai);
280      }
281 }
282
283 EAPI void
284 _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
285 {
286    Elm_Access_Item *ai = _access_add_set(ac, type);
287    if (!ai) return;
288    ai->data = eina_stringshare_add(text);
289 }
290
291 EAPI void
292 _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
293 {
294    Elm_Access_Item *ai = _access_add_set(ac, type);
295    if (!ai) return;
296    ai->func = func;
297    ai->data = data;
298 }
299
300 EAPI void
301 _elm_access_on_highlight_hook_set(Elm_Access_Info           *ac,
302                                   Elm_Access_On_Highlight_Cb func,
303                                   void                      *data)
304 {
305     if (!ac) return;
306     ac->on_highlight = func;
307     ac->on_highlight_data = data;
308 }
309
310 EAPI void
311 _elm_access_activate_callback_set(Elm_Access_Info           *ac,
312                                   Elm_Access_Activate_Cb     func,
313                                   void                      *data)
314 {
315    if (!ac) return;
316    ac->activate = func;
317    ac->activate_data = data;
318 }
319
320 EAPI void
321 _elm_access_highlight_object_activate(Evas_Object *obj, Elm_Activate act)
322 {
323    Evas_Object *highlight;
324    Elm_Access_Info *ac;
325
326    highlight = _access_highlight_object_get(obj);
327    if (!highlight) return;
328
329    if (elm_widget_is(highlight))
330      {
331         elm_widget_activate(highlight, act);
332         return;
333      }
334
335    ac = evas_object_data_get(highlight, "_elm_access");
336    if (!ac) return;
337
338    if (ac->activate)
339      ac->activate(ac->activate_data, highlight,
340                   (Elm_Object_Item *)ac->widget_item);
341 }
342
343 EAPI void
344 _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
345 {
346    Evas_Object *highlight, *focused;
347
348    highlight = _access_highlight_object_get(obj);
349    focused = elm_widget_focused_object_get(obj);
350
351    if (highlight && (highlight != focused))
352      elm_object_focus_set(highlight, EINA_TRUE);
353
354    /* use focus cycle to read next, previous object */
355    elm_widget_focus_cycle(obj, dir);
356 }
357
358 EAPI char *
359 _elm_access_text_get(const Elm_Access_Info *ac, int type, Evas_Object *obj)
360 {
361    Elm_Access_Item *ai;
362    Eina_List *l;
363
364    if (!ac) return NULL;
365    EINA_LIST_FOREACH(ac->items, l, ai)
366      {
367         if (ai->type == type)
368           {
369              if (ai->func) return ai->func((void *)(ai->data), obj);
370              else if (ai->data) return strdup(ai->data);
371              return NULL;
372           }
373      }
374    return NULL;
375 }
376
377 EAPI void
378 _elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj)
379 {
380    char *txt = _elm_access_text_get(ac, type, obj);
381
382    _access_init();
383    if (mapi)
384      {
385         if (mapi->out_done_callback_set)
386            mapi->out_done_callback_set(_access_read_done, NULL);
387         if (type == ELM_ACCESS_DONE)
388           {
389              if (mapi->out_read_done) mapi->out_read_done();
390           }
391         else if (type == ELM_ACCESS_CANCEL)
392           {
393              if (mapi->out_cancel) mapi->out_cancel();
394           }
395         else
396           {
397              if (txt)
398                {
399                   if (mapi->out_read) mapi->out_read(txt);
400                   if (mapi->out_read) mapi->out_read(".\n");
401                }
402           }
403      }
404    if (txt) free(txt);
405 }
406
407 EAPI void
408 _elm_access_say(const char *txt)
409 {
410    _access_init();
411    if (mapi)
412      {
413         if (mapi->out_done_callback_set)
414            mapi->out_done_callback_set(_access_read_done, NULL);
415         if (mapi->out_cancel) mapi->out_cancel();
416         if (txt)
417           {
418              if (mapi->out_read) mapi->out_read(txt);
419              if (mapi->out_read) mapi->out_read(".\n");
420           }
421         if (mapi->out_read_done) mapi->out_read_done();
422      }
423 }
424
425 EAPI Elm_Access_Info *
426 _elm_access_object_get(const Evas_Object *obj)
427 {
428    return evas_object_data_get(obj, "_elm_access");
429 }
430
431 EAPI void
432 _elm_access_object_hilight(Evas_Object *obj)
433 {
434    Evas_Object *o, *parent_obj;
435    Evas_Coord x, y, w, h;
436
437    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
438    if (!o)
439      {
440         o = edje_object_add(evas_object_evas_get(obj));
441         evas_object_name_set(o, "_elm_access_disp");
442         evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
443      }
444    else
445      {
446         Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
447         if (ptarget)
448           {
449              evas_object_data_del(o, "_elm_access_target");
450              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
451                                                  _access_obj_hilight_del_cb, NULL);
452              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
453                                                  _access_obj_hilight_hide_cb, NULL);
454              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
455                                                  _access_obj_hilight_move_cb, NULL);
456              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
457                                                  _access_obj_hilight_resize_cb, NULL);
458           }
459      }
460    evas_object_data_set(o, "_elm_access_target", obj);
461
462    parent_obj = obj;
463    if (!elm_widget_is(obj))
464       parent_obj = evas_object_data_get(obj, "_elm_access_parent");
465
466    elm_widget_theme_object_set(parent_obj, o, "access", "base", "default");
467
468    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
469                                   _access_obj_hilight_del_cb, NULL);
470    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
471                                   _access_obj_hilight_hide_cb, NULL);
472    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
473                                   _access_obj_hilight_move_cb, NULL);
474    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
475                                   _access_obj_hilight_resize_cb, NULL);
476    evas_object_raise(o);
477    evas_object_geometry_get(obj, &x, &y, &w, &h);
478    evas_object_move(o, x, y);
479    evas_object_resize(o, w, h);
480    evas_object_show(o);
481 }
482
483 EAPI void
484 _elm_access_object_unhilight(Evas_Object *obj)
485 {
486    Evas_Object *o, *ptarget;
487
488    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
489    if (!o) return;
490    ptarget = evas_object_data_get(o, "_elm_access_target");
491    if (ptarget == obj)
492      {
493         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
494                                             _access_obj_hilight_del_cb, NULL);
495         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
496                                             _access_obj_hilight_hide_cb, NULL);
497         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
498                                             _access_obj_hilight_move_cb, NULL);
499         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
500                                             _access_obj_hilight_resize_cb, NULL);
501         evas_object_del(o);
502      }
503 }
504
505 static void
506 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
507                 void *event_info __UNUSED__)
508 {
509    Evas_Object *accessobj;
510    Evas_Coord w, h;
511
512    accessobj = data;
513    if (!accessobj) return;
514
515    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
516    evas_object_resize(accessobj, w, h);
517 }
518
519 static void
520 _content_move(void *data, Evas *e __UNUSED__, Evas_Object *obj,
521               void *event_info __UNUSED__)
522 {
523    Evas_Object *accessobj;
524    Evas_Coord x, y;
525
526    accessobj = data;
527    if (!accessobj) return;
528
529    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
530    evas_object_move(accessobj, x, y);
531 }
532
533 static char *
534 _part_access_info_cb(void *data, Evas_Object *obj)
535 {
536    Evas_Object *eobj = data;
537    if (!eobj) return NULL;
538
539    const char *part = evas_object_data_get(obj, "_elm_access_part");
540    const char *txt = edje_object_part_text_get(eobj, part);
541    if (txt) return strdup(txt);
542    return NULL;
543 }
544
545 static void
546 _access_obj_del(void *data __UNUSED__, Evas *e __UNUSED__,
547                 Evas_Object *obj, void *event_info __UNUSED__)
548 {
549    char *part = evas_object_data_get(obj, "_elm_access_part");
550    evas_object_data_del(obj, "_elm_access_part");
551    if (part) free(part);
552 }
553
554 EAPI Evas_Object *
555 _elm_access_edje_object_part_object_register(Evas_Object* obj,
556                                              const Evas_Object *eobj,
557                                              const char* part)
558 {
559    Evas_Object *ao;
560    Evas_Object *po = (Evas_Object *)edje_object_part_object_get(eobj, part);
561    Evas_Coord x, y, w, h;
562    Elm_Access_Info *ac;
563
564    if (!obj || !po) return NULL;
565
566    // check previous access object
567    ao = evas_object_data_get(po, "_part_access_obj");
568    if (ao)
569      _elm_access_edje_object_part_object_unregister(obj, eobj, part);
570
571    // create access object
572    ao = _elm_access_add(obj);
573    if (!ao) return NULL;
574
575    evas_object_event_callback_add(po, EVAS_CALLBACK_RESIZE,
576                                   _content_resize, ao);
577    evas_object_event_callback_add(po, EVAS_CALLBACK_MOVE,
578                                   _content_move, ao);
579
580    evas_object_geometry_get(po, &x, &y, &w, &h);
581    evas_object_move(ao, x, y);
582    evas_object_resize(ao, w, h);
583    evas_object_show(ao);
584
585    // register access object
586    _elm_access_object_register(ao, po);
587    _elm_access_text_set(_elm_access_object_get(ao),
588                         ELM_ACCESS_TYPE, evas_object_type_get(po));
589    evas_object_data_set(ao, "_elm_access_part", strdup(part));
590    evas_object_event_callback_add(ao, EVAS_CALLBACK_DEL,
591                                   _access_obj_del, NULL);
592    _elm_access_callback_set(_elm_access_object_get(ao),
593                             ELM_ACCESS_INFO,
594                             _part_access_info_cb, eobj);
595
596    // set access object
597    evas_object_data_set(po, "_part_access_obj", ao);
598
599    /* set owner part object */
600    ac = evas_object_data_get(ao, "_elm_access");
601    ac->part_object = po;
602
603    return ao;
604 }
605
606 EAPI void
607 _elm_access_edje_object_part_object_unregister(Evas_Object* obj,
608                                                const Evas_Object *eobj,
609                                                const char* part)
610 {
611    Evas_Object *ao;
612    Evas_Object *po = (Evas_Object *)edje_object_part_object_get(eobj, part);
613
614    if (!obj || !po) return;
615
616    ao = evas_object_data_get(po, "_part_access_obj");
617    if (!ao) return;
618
619    evas_object_data_del(po, "_part_access_obj");
620
621    // delete callbacks
622    evas_object_event_callback_del_full(po, EVAS_CALLBACK_RESIZE,
623                                        _content_resize, ao);
624    evas_object_event_callback_del_full(po, EVAS_CALLBACK_MOVE,
625                                        _content_move, ao);
626
627    evas_object_event_callback_del_full(po, EVAS_CALLBACK_MOUSE_IN,
628                                       _access_obj_mouse_in_cb, ao);
629    evas_object_event_callback_del_full(po, EVAS_CALLBACK_MOUSE_OUT,
630                                       _access_obj_mouse_out_cb, ao);
631    evas_object_event_callback_del_full(po, EVAS_CALLBACK_DEL,
632                                        _access_obj_del_cb, ao);
633    evas_object_del(ao);
634 }
635
636 EAPI void
637 _elm_access_object_hilight_disable(Evas *e)
638 {
639    Evas_Object *o, *ptarget;
640
641    o = evas_object_name_find(e, "_elm_access_disp");
642    if (!o) return;
643    ptarget = evas_object_data_get(o, "_elm_access_target");
644    if (ptarget)
645      {
646         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
647                                             _access_obj_hilight_del_cb, NULL);
648         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
649                                             _access_obj_hilight_hide_cb, NULL);
650         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
651                                             _access_obj_hilight_move_cb, NULL);
652         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
653                                             _access_obj_hilight_resize_cb, NULL);
654      }
655    evas_object_del(o);
656 }
657
658 EAPI void
659 _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
660 {
661    Elm_Access_Info *ac;
662
663    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
664                                   _access_obj_mouse_in_cb, obj);
665    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
666                                   _access_obj_mouse_out_cb, obj);
667    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
668                                   _access_obj_del_cb, obj);
669    ac = calloc(1, sizeof(Elm_Access_Info));
670    evas_object_data_set(obj, "_elm_access", ac);
671 }
672
673 EAPI void
674 _elm_access_object_unregister(Evas_Object *obj, Evas_Object *hoverobj)
675 {
676    Elm_Access_Info *ac;
677
678    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_IN,
679                                        _access_obj_mouse_in_cb, obj);
680    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
681                                        _access_obj_mouse_out_cb, obj);
682    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_DEL,
683                                        _access_obj_del_cb, obj);
684
685    ac = evas_object_data_get(obj, "_elm_access");
686    evas_object_data_del(obj, "_elm_access");
687    if (ac)
688      {
689         _elm_access_clear(ac);
690         free(ac);
691      }
692 }
693
694 EAPI void
695 _elm_access_widget_item_register(Elm_Widget_Item *item)
696 {
697    Evas_Object *ao, *ho;
698    Evas_Coord x, y, w, h;
699    Elm_Access_Info *ac;
700
701    if (!item) return;
702
703    /* check previous access object */
704    if (item->access_obj)
705      _elm_access_widget_item_unregister(item);
706
707    // create access object
708    ho = item->view;
709    ao = _elm_access_add(item->widget);
710    if (!ao) return;
711
712    evas_object_event_callback_add(ho, EVAS_CALLBACK_RESIZE,
713                                   _content_resize, ao);
714    evas_object_event_callback_add(ho, EVAS_CALLBACK_MOVE,
715                                   _content_move, ao);
716
717    evas_object_geometry_get(ho, &x, &y, &w, &h);
718    evas_object_move(ao, x, y);
719    evas_object_resize(ao, w, h);
720    evas_object_show(ao);
721
722    // register access object
723    _elm_access_object_register(ao, ho);
724
725    item->access_obj = ao;
726
727    /* set owner widget item */
728    ac = evas_object_data_get(ao, "_elm_access");
729    ac->widget_item = item;
730 }
731
732 EAPI void
733 _elm_access_widget_item_unregister(Elm_Widget_Item *item)
734 {
735    Evas_Object *ho;
736
737    if (!item || !item->access_obj) return;
738
739    ho = item->view;
740    evas_object_event_callback_del_full(ho, EVAS_CALLBACK_RESIZE,
741                                   _content_resize, item->access_obj);
742    evas_object_event_callback_del_full(ho, EVAS_CALLBACK_MOVE,
743                                   _content_move, item->access_obj);
744
745    _elm_access_object_unregister(item->access_obj, ho);
746
747    evas_object_del(item->access_obj);
748    item->access_obj = NULL;
749 }
750
751 EAPI Eina_Bool
752 _elm_access_2nd_click_timeout(Evas_Object *obj)
753 {
754    Ecore_Timer *t;
755
756    t = evas_object_data_get(obj, "_elm_2nd_timeout");
757    if (t)
758      {
759         ecore_timer_del(t);
760         evas_object_data_del(obj, "_elm_2nd_timeout");
761         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
762                                             _access_2nd_click_del_cb, NULL);
763         return EINA_TRUE;
764      }
765    t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
766    evas_object_data_set(obj, "_elm_2nd_timeout", t);
767    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
768                                   _access_2nd_click_del_cb, NULL);
769    return EINA_FALSE;
770 }
771
772 static Evas_Object *
773 _elm_access_add(Evas_Object *parent)
774 {
775    Evas_Object *obj;
776
777    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
778
779    obj = elm_widget_add(_elm_access_smart_class_new(), parent);
780    if (!obj) return NULL;
781
782    if (!elm_widget_sub_object_add(parent, obj))
783      ERR("could not add %p as sub object of %p", obj, parent);
784
785    return obj;
786 }
787
788 EAPI void
789 elm_access_text_set(Evas_Object *obj, int type, const char *text)
790 {
791    _elm_access_text_set(_elm_access_object_get(obj), type, text);
792 }
793
794 EAPI char *
795 elm_access_text_get(Evas_Object *obj, int type)
796 {
797    return _elm_access_text_get(_elm_access_object_get(obj), type, obj);
798 }
799
800 EAPI void
801 elm_access_object_register(Evas_Object *parent, Evas_Object *target)
802 {
803    Elm_Access_Info *ai;
804
805    if (!parent || !target) return;
806
807    evas_object_event_callback_add(target, EVAS_CALLBACK_MOUSE_IN,
808                                   _access_obj_mouse_in_cb, target);
809    evas_object_event_callback_add(target, EVAS_CALLBACK_MOUSE_OUT,
810                                   _access_obj_mouse_out_cb, target);
811    evas_object_event_callback_add(target, EVAS_CALLBACK_DEL,
812                                   _access_obj_del_cb, target);
813    ai = calloc(1, sizeof(Elm_Access_Info));
814    evas_object_data_set(target, "_elm_access", ai);
815
816    //TODO: evas_object_data_del(); parent should take care of children.
817    evas_object_data_set(target, "_elm_access_parent", parent);
818 }
819
820 EAPI void
821 elm_access_object_unregister(Evas_Object *obj)
822 {
823    Elm_Access_Info *ac;
824
825    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
826                                        _access_obj_mouse_in_cb, obj);
827    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
828                                        _access_obj_mouse_out_cb, obj);
829    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
830                                        _access_obj_del_cb, obj);
831
832    ac = evas_object_data_get(obj, "_elm_access");
833    evas_object_data_del(obj, "_elm_access");
834    if (ac)
835      {
836         _elm_access_clear(ac);
837         free(ac);
838      }
839
840    evas_object_data_del(obj, "_elm_access_parent");
841 }
842
843 EAPI void
844 elm_access_content_cb_set(Evas_Object *obj, int type,
845                           Elm_Access_Content_Cb func, const void *data)
846 {
847    _elm_access_callback_set(_elm_access_object_get(obj), type, func, data);
848 }
849
850 EAPI void
851 elm_access_activate_cb_set(Evas_Object *obj,
852                                  Elm_Access_Activate_Cb  func, void *data)
853 {
854    Elm_Access_Info *ac;
855
856    ac = _elm_access_object_get(obj);
857    if (!ac) return;
858
859    ac->activate = func;
860    ac->activate_data = data;
861 }
862
863 EAPI void
864 elm_access_external_info_set(Evas_Object *obj, const char *text)
865 {
866    _elm_access_text_set
867      (_elm_access_object_get(obj), ELM_ACCESS_CONTEXT_INFO, text);
868 }
869
870 EAPI char *
871 elm_access_external_info_get(const Evas_Object *obj)
872 {
873    Elm_Access_Info *ac;
874
875    ac = _elm_access_object_get(obj);
876    return _elm_access_text_get(ac, ELM_ACCESS_CONTEXT_INFO, (Evas_Object *)obj);
877 }