elm: Removed trailing whitespaces.
[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
66 static Eina_Bool
67 _access_obj_over_timeout_cb(void *data)
68 {
69    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
70    if (!ac) return EINA_FALSE;
71    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
72      {
73         _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
74         _elm_access_read(ac, ELM_ACCESS_TYPE,   data, NULL);
75         _elm_access_read(ac, ELM_ACCESS_INFO,   data, NULL);
76         _elm_access_read(ac, ELM_ACCESS_STATE,  data, NULL);
77         _elm_access_read(ac, ELM_ACCESS_DONE,   data, NULL);
78      }
79    ac->delay_timer = NULL;
80    return EINA_FALSE;
81 }
82
83 static void
84 _access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
85 {
86    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
87    if (!ac) return;
88
89    if (ac->delay_timer)
90      {
91         ecore_timer_del(ac->delay_timer);
92         ac->delay_timer = NULL;
93      }
94    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
95       ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
96 }
97
98 static void
99 _access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
100 {
101    Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
102    if (!ac) return;
103    if (ac->delay_timer)
104      {
105         ecore_timer_del(ac->delay_timer);
106         ac->delay_timer = NULL;
107      }
108 }
109
110 static void
111 _access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
112 {
113    Elm_Access_Info *ac;
114
115    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
116                                        _access_obj_mouse_in_cb, data);
117    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
118                                        _access_obj_mouse_out_cb, data);
119    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
120                                        _access_obj_del_cb, data);
121    ac = evas_object_data_get(data, "_elm_access");
122    evas_object_data_del(data, "_elm_access");
123    if (ac)
124      {
125         _elm_access_clear(ac);
126         free(ac);
127      }
128 }
129
130 static void
131 _access_read_done(void *data __UNUSED__)
132 {
133    printf("read done\n");
134 }
135
136 //-------------------------------------------------------------------------//
137
138 EAPI void
139 _elm_access_clear(Elm_Access_Info *ac)
140 {
141    Elm_Access_Item *ai;
142
143    if (!ac) return;
144    if (ac->delay_timer)
145      {
146         ecore_timer_del(ac->delay_timer);
147         ac->delay_timer = NULL;
148      }
149    EINA_LIST_FREE(ac->items, ai)
150      {
151         if (!ai->func)
152           {
153              if (ai->data) eina_stringshare_del(ai->data);
154           }
155         free(ai);
156      }
157 }
158
159 EAPI void
160 _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
161 {
162    Elm_Access_Item *ai = _access_add_set(ac, type);
163    if (!ai) return;
164    ai->data = eina_stringshare_add(text);
165 }
166
167 EAPI void
168 _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
169 {
170    Elm_Access_Item *ai = _access_add_set(ac, type);
171    if (!ai) return;
172    ai->func = func;
173    ai->data = data;
174 }
175
176 EAPI char *
177 _elm_access_text_get(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
178 {
179    Elm_Access_Item *ai;
180    Eina_List *l;
181
182    if (!ac) return NULL;
183    EINA_LIST_FOREACH(ac->items, l, ai)
184      {
185         if (ai->type == type)
186           {
187              if (ai->func) return ai->func(ai->data, obj, item);
188              else if (ai->data) return strdup(ai->data);
189              return NULL;
190           }
191      }
192    return NULL;
193 }
194
195 EAPI void
196 _elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
197 {
198    char *txt = _elm_access_text_get(ac, type, obj, item);
199
200    _access_init();
201    if (mapi)
202      {
203         if (mapi->out_done_callback_set)
204            mapi->out_done_callback_set(_access_read_done, NULL);
205         if (type == ELM_ACCESS_DONE)
206           {
207              if (mapi->out_read_done) mapi->out_read_done();
208           }
209         else if (type == ELM_ACCESS_CANCEL)
210           {
211              if (mapi->out_cancel) mapi->out_cancel();
212           }
213         else
214           {
215              if (txt)
216                {
217                   if (mapi->out_read) mapi->out_read(txt);
218                   if (mapi->out_read) mapi->out_read(".\n");
219                }
220           }
221      }
222    if (txt) free(txt);
223 }
224
225 EAPI void
226 _elm_access_say(const char *txt)
227 {
228    _access_init();
229    if (mapi)
230      {
231         if (mapi->out_done_callback_set)
232            mapi->out_done_callback_set(_access_read_done, NULL);
233         if (mapi->out_cancel) mapi->out_cancel();
234         if (txt)
235           {
236              if (mapi->out_read) mapi->out_read(txt);
237              if (mapi->out_read) mapi->out_read(".\n");
238           }
239         if (mapi->out_read_done) mapi->out_read_done();
240      }
241 }
242
243 EAPI Elm_Access_Info *
244 _elm_access_object_get(Evas_Object *obj)
245 {
246    return evas_object_data_get(obj, "_elm_access");
247 }
248
249 EAPI void
250 _elm_access_object_hilight(Evas_Object *win, Evas_Object *obj)
251 {
252    // if hilight obj doens exist - create and attach to window
253    // make sure its on a high layer
254    // show it and emit signal
255    // if exists, move and resize to obj object location
256    // ** try use dragables to specify pos+size??
257 }
258
259 EAPI void
260 _elm_access_object_unhilight(Evas_Object *win)
261 {
262    // hide highlight obj is there, emit hide and then del when done
263 }
264
265 EAPI void
266 _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
267 {
268    Elm_Access_Info *ac;
269
270    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
271                                   _access_obj_mouse_in_cb, obj);
272    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
273                                   _access_obj_mouse_out_cb, obj);
274    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
275                                   _access_obj_del_cb, obj);
276    ac = calloc(1, sizeof(Elm_Access_Info));
277    evas_object_data_set(obj, "_elm_access", ac);
278 }
279
280 static void
281 _access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
282 {
283    Ecore_Timer *t;
284
285    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
286                                        _access_2nd_click_del_cb, NULL);
287    t = evas_object_data_get(obj, "_elm_2nd_timeout");
288    if (t)
289      {
290         ecore_timer_del(t);
291         evas_object_data_del(obj, "_elm_2nd_timeout");
292      }
293 }
294
295 static Eina_Bool
296 _access_2nd_click_timeout_cb(void *data)
297 {
298    evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
299                                        _access_2nd_click_del_cb, NULL);
300    evas_object_data_del(data, "_elm_2nd_timeout");
301    return EINA_FALSE;
302 }
303
304 EAPI Eina_Bool
305 _elm_access_2nd_click_timeout(Evas_Object *obj)
306 {
307    Ecore_Timer *t;
308
309    t = evas_object_data_get(obj, "_elm_2nd_timeout");
310    if (t)
311      {
312         ecore_timer_del(t);
313         evas_object_data_del(obj, "_elm_2nd_timeout");
314         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
315                                             _access_2nd_click_del_cb, NULL);
316         return EINA_TRUE;
317      }
318    t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
319    evas_object_data_set(obj, "_elm_2nd_timeout", t);
320    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
321                                   _access_2nd_click_del_cb, NULL);
322    return EINA_FALSE;
323 }
324
325 // XXX special version for items
326 //EAPI void
327 //_elm_access_item_hover_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
328 //{
329 //}