[accessability] Initial merge
[framework/uifw/elementary.git] / src / lib / elm_access.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Mod_Api Mod_Api;
5
6 struct _Mod_Api
7 {
8    void (*out_read) (const char *txt);
9    void (*out_read_done) (void);
10    void (*out_cancel) (void);
11    void (*out_done_callback_set) (void (*func) (void *data), const void *data);
12 };
13
14 static int initted = 0;
15 static Elm_Module *mod = NULL;
16 static Mod_Api *mapi = NULL;
17
18 static void
19 _access_init(void)
20 {
21    Elm_Module *m;
22    initted++;
23    if (initted > 1) return;
24    if (!(m = _elm_module_find_as("access/api"))) return;
25    mod = m;
26    m->api = malloc(sizeof(Mod_Api));
27    if (!m->api) return;
28    m->init_func(m);
29    ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
30       _elm_module_symbol_get(m, "out_read");
31    ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
32       _elm_module_symbol_get(m, "out_read_done");
33    ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
34       _elm_module_symbol_get(m, "out_cancel");
35    ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
36       _elm_module_symbol_get(m, "out_done_callback_set");
37    mapi = m->api;
38 }
39
40 static Elm_Access_Item *
41 _access_add_set(Elm_Access_Info *ac, int type)
42 {
43    Elm_Access_Item *ai;
44    Eina_List *l;
45
46    if (!ac) return NULL;
47    EINA_LIST_FOREACH(ac->items, l, ai)
48      {
49         if (ai->type == type)
50           {
51              if (!ai->func)
52                {
53                   if (ai->data) eina_stringshare_del(ai->data);
54                }
55              ai->func = NULL;
56              ai->data = NULL;
57              return ai;
58           }
59      }
60    ai = calloc(1, sizeof(Elm_Access_Item));
61    ai->type = type;
62    ac->items = eina_list_prepend(ac->items, ai);
63    return ai;
64 }
65 static Eina_Bool
66 _access_obj_over_timeout_cb(void *data)
67 {
68    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
69    if (!ac) return EINA_FALSE;
70    _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
71    _elm_access_read(ac, ELM_ACCESS_TYPE,   data, NULL);
72    _elm_access_read(ac, ELM_ACCESS_INFO,   data, NULL);
73    _elm_access_read(ac, ELM_ACCESS_STATE,  data, NULL);
74    _elm_access_read(ac, ELM_ACCESS_DONE,   data, NULL);
75    ac->delay_timer = NULL;
76    return EINA_FALSE;
77 }
78
79 static void
80 _access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
81 {
82    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
83    if (!ac) return;
84
85    if (ac->delay_timer)
86      {
87         ecore_timer_del(ac->delay_timer);
88         ac->delay_timer = NULL;
89      }
90    ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
91 }
92
93 static void
94 _access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
95 {
96    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
97    if (!ac) return;
98    if (ac->delay_timer)
99      {
100         ecore_timer_del(ac->delay_timer);
101         ac->delay_timer = NULL;
102      }
103 }
104
105 static void
106 _access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
107 {
108    Elm_Access_Info *ac;
109    
110    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
111                                        _access_obj_mouse_in_cb, data);
112    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
113                                        _access_obj_mouse_out_cb, data);
114    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
115                                        _access_obj_del_cb, data);
116    ac = evas_object_data_get(data, "_elm_access");
117    evas_object_data_del(data, "_elm_access");
118    if (ac)
119      {
120         _elm_access_clear(ac);
121         free(ac);
122      }
123 }
124
125 static void
126 _access_read_done(void *data __UNUSED__)
127 {
128    printf("read done\n");
129 }
130
131 //-------------------------------------------------------------------------//
132
133 EAPI void
134 _elm_access_clear(Elm_Access_Info *ac)
135 {
136    Elm_Access_Item *ai;
137
138    if (!ac) return;
139    if (ac->delay_timer)
140      {
141         ecore_timer_del(ac->delay_timer);
142         ac->delay_timer = NULL;
143      }
144    EINA_LIST_FREE(ac->items, ai)
145      {
146         if (!ai->func)
147           {
148              if (ai->data) eina_stringshare_del(ai->data);
149           }
150         free(ai);
151      }
152 }
153
154 EAPI void
155 _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
156 {
157    Elm_Access_Item *ai = _access_add_set(ac, type);
158    if (!ai) return;
159    ai->data = eina_stringshare_add(text);
160 }
161
162 EAPI void
163 _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
164 {
165    Elm_Access_Item *ai = _access_add_set(ac, type);
166    if (!ai) return;
167    ai->func = func;
168    ai->data = data;
169 }
170
171 EAPI char *
172 _elm_access_text_get(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
173 {
174    Elm_Access_Item *ai;
175    Eina_List *l;
176    
177    if (!ac) return NULL;
178    EINA_LIST_FOREACH(ac->items, l, ai)
179      {
180         if (ai->type == type)
181           {
182              if (ai->func) return ai->func(ai->data, obj, item);
183              else if (ai->data) return strdup(ai->data);
184              return NULL;
185           }
186      }
187    return NULL;
188 }
189
190 EAPI void
191 _elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
192 {
193    char *txt = _elm_access_text_get(ac, type, obj, item);
194
195    _access_init();
196    if (mapi)
197      {
198         if (mapi->out_done_callback_set)
199            mapi->out_done_callback_set(_access_read_done, NULL);
200         if (type == ELM_ACCESS_DONE)
201           {
202              if (mapi->out_read_done) mapi->out_read_done();
203           }
204         else if (type == ELM_ACCESS_CANCEL)
205           {
206              if (mapi->out_cancel) mapi->out_cancel();
207           }
208         else
209           {
210              if (txt)
211                {
212                   if (mapi->out_read) mapi->out_read(txt);
213                   if (mapi->out_read) mapi->out_read(".\n");
214                }
215           }
216      }
217    if (txt) free(txt);
218 }
219
220 EAPI Elm_Access_Info *
221 _elm_access_object_get(Evas_Object *obj)
222 {
223    return evas_object_data_get(obj, "_elm_access");
224 }
225
226 EAPI void
227 _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
228 {
229    Elm_Access_Info *ac;
230    
231    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
232                                   _access_obj_mouse_in_cb, obj);
233    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
234                                   _access_obj_mouse_out_cb, obj);
235    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
236                                   _access_obj_del_cb, obj);
237    ac = calloc(1, sizeof(Elm_Access_Info));
238    evas_object_data_set(obj, "_elm_access", ac);
239 }
240
241 // XXX special version for items
242 //EAPI void
243 //_elm_access_item_hover_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
244 //{
245 //}