controller: allowed the focus even though bar is hided
[profile/tv/apps/native/air_mediahub.git] / src / util / controller.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdbool.h>
18 #include <Elementary.h>
19 #include <app_debug.h>
20 #include <inputmgr.h>
21
22 #include "define.h"
23 #include "util/controller.h"
24
25 struct _event_cb {
26         void (*func)(void *data, const char *ev);
27         void *data;
28 };
29
30 struct _control {
31         Evas_Object *obj;
32         char *part;
33 };
34
35 struct _priv {
36         Evas_Object *base;
37         Eina_List *list;
38         struct _event_cb cb;
39 };
40
41 static void _btn_cb(void *data, Evas_Object *obj,
42                 const char *emission, const char *source)
43 {
44         struct _priv *p;
45
46         if (!data) {
47                 _ERR("invalid parameter");
48                 return;
49         }
50
51         p = data;
52
53         if (p->cb.func)
54                 p->cb.func(p->cb.data, source);
55 }
56
57 static void _mouse_move_cb(int id, void *data, Evas *e,
58                         Evas_Object *obj, Evas_Event_Mouse_Move *ev)
59 {
60         if (!elm_object_focus_get(obj))
61                 elm_object_focus_set(obj, EINA_TRUE);
62 }
63
64 static void _clicked_cb(int id, void *data, Evas_Object *obj)
65 {
66         elm_object_signal_emit(obj, SIG_BTN_CLICKED, "");
67 }
68
69 static input_handler _handler = {
70         .mouse_move = _mouse_move_cb,
71         .clicked = _clicked_cb,
72 };
73
74 static Evas_Object *_add_btn(Evas_Object *base, const char *style)
75 {
76         Evas_Object *btn;
77
78         btn = elm_button_add(base);
79         if (!btn)
80                 return NULL;
81
82         elm_object_style_set(btn, style);
83
84         return btn;
85 }
86
87 static bool _add_control(void *handle, const char *name, int loc,
88                 const char *style, const char *part)
89 {
90         struct _priv *p;
91         struct _control *ctl;
92         Evas_Object *btn;
93         char buf[32];
94
95         if (!handle || !name || !style || !part) {
96                 _ERR("invalid parameter");
97                 return false;
98         }
99
100         p = handle;
101
102         snprintf(buf, sizeof(buf), "%s_%s", style, name);
103         btn = _add_btn(p->base, buf);
104         if (!btn) {
105                 _ERR("failed to add button");
106                 return false;
107         }
108
109         snprintf(buf, sizeof(buf), "%s%d", part, loc);
110
111         ctl = calloc(1, sizeof(*ctl));
112         if (!ctl) {
113                 _ERR("failed to allocate");
114                 return false;
115         }
116
117         ctl->obj = btn;
118         ctl->part = strdup(buf);
119
120         p->list = eina_list_append(p->list, ctl);
121
122         inputmgr_add_callback(btn, 0, &_handler, p);
123         elm_object_signal_callback_add(btn, SIG_BTN_CALLBACK, name, _btn_cb, p);
124
125         return true;
126 }
127
128 static void _add_callback(void *handle,
129                 void (*func)(void *, const char *), void *data)
130 {
131         struct _priv *p;
132
133         if (!handle) {
134                 _ERR("invalid parameter");
135                 return;
136         }
137
138         p = handle;
139         p->cb.func = func;
140         p->cb.data = data;
141 }
142
143 static void _focus(void *handle, int loc, bool foc)
144 {
145         struct _priv *p;
146         struct _control *ctl;
147
148         if (!handle) {
149                 _ERR("invalid parameter");
150                 return;
151         }
152
153         p = handle;
154         ctl = eina_list_nth(p->list, loc);
155
156         if (ctl && ctl->obj)
157                 elm_object_focus_set(ctl->obj, foc);
158 }
159
160 static void _signal(void *handle, int loc, const char *signal)
161 {
162         struct _priv *p;
163         struct _control *ctl;
164
165         if (!handle) {
166                 _ERR("invalid parameter");
167                 return;
168         }
169
170         p = handle;
171         ctl = eina_list_nth(p->list, loc);
172
173         if (ctl && ctl->obj)
174                 elm_object_signal_emit(ctl->obj, signal, "");
175 }
176
177 static void _enable(void *handle)
178 {
179         struct _priv *p;
180         struct _control *ctl;
181         Eina_List *l;
182
183         if (!handle) {
184                 _ERR("invalid parameter");
185                 return;
186         }
187
188         p = handle;
189
190         EINA_LIST_FOREACH(p->list, l, ctl) {
191                 if (!ctl->obj)
192                         continue;
193
194                 evas_object_freeze_events_set(ctl->obj, EINA_FALSE);
195         }
196 }
197
198 static void _disable(void *handle)
199 {
200         struct _priv *p;
201         struct _control *ctl;
202         Eina_List *l;
203
204         if (!handle) {
205                 _ERR("invalid parameter");
206                 return;
207         }
208
209         p = handle;
210
211         EINA_LIST_FOREACH(p->list, l, ctl) {
212                 if (!ctl->obj)
213                         continue;
214
215                 evas_object_freeze_events_set(ctl->obj, EINA_TRUE);
216         }
217 }
218
219 static void _show(void *handle)
220 {
221         struct _priv *p;
222         struct _control *ctl;
223         Eina_List *l;
224
225         if (!handle) {
226                 _ERR("invalid parameter");
227                 return;
228         }
229
230         p = handle;
231
232         EINA_LIST_FOREACH(p->list, l, ctl) {
233                 if (!ctl->obj)
234                         continue;
235
236                 evas_object_show(ctl->obj);
237                 elm_object_part_content_set(p->base, ctl->part, ctl->obj);
238         }
239
240         _enable(handle);
241 }
242
243 static void _hide(void *handle)
244 {
245         struct _priv *p;
246         struct _control *ctl;
247         Eina_List *l;
248
249         if (!handle) {
250                 _ERR("invalid parameter");
251                 return;
252         }
253
254         p = handle;
255
256         EINA_LIST_FOREACH(p->list, l, ctl) {
257                 if (!ctl->obj)
258                         continue;
259
260                 elm_object_focus_set(ctl->obj, false);
261
262                 evas_object_hide(ctl->obj);
263                 elm_object_part_content_unset(p->base, ctl->part);
264         }
265
266         _disable(handle);
267 }
268
269 static Evas_Object *_get_object(void *handle, int loc)
270 {
271         struct _priv *p;
272         struct _control *ctl;
273
274         if (!handle) {
275                 _ERR("invalid parameter");
276                 return NULL;
277         }
278
279         p = handle;
280
281         ctl = eina_list_nth(p->list, loc);
282         if (!ctl)
283                 return NULL;
284
285         return ctl->obj;
286 }
287
288 static int _get_count(void *handle)
289 {
290         struct _priv *p;
291
292         if (!handle) {
293                 _ERR("invalid parameter");
294                 return 0;
295         }
296
297         p = handle;
298
299         return eina_list_count(p->list);
300 }
301
302 static struct controller_ops _operations = {
303         .add_control = _add_control,
304         .add_callback = _add_callback,
305         .focus = _focus,
306         .signal = _signal,
307         .enable = _enable,
308         .disable = _disable,
309         .show = _show,
310         .hide = _hide,
311         .get_object = _get_object,
312         .get_count = _get_count,
313 };
314
315 struct controller *controller_create(Evas_Object *base)
316 {
317         struct controller *m;
318         struct _priv *p;
319
320         if (!base) {
321                 _ERR("invalid parameter");
322                 return NULL;
323         }
324
325         m = calloc(1, sizeof(*m));
326         if (!m) {
327                 _ERR("failed to allocate");
328                 return NULL;
329         }
330
331         p = calloc(1, sizeof(*p));
332         if (!p) {
333                 _ERR("failed to allocate");
334                 free(m);
335                 return NULL;
336         }
337
338         p->base = base;
339
340         m->handle = (void *)p;
341         m->ops = &_operations;
342
343         return m;
344 }
345
346 void controller_destroy(struct controller *m)
347 {
348         struct _priv *p;
349         struct _control *ctl;
350
351         if (!m)
352                 return;
353
354         p = m->handle;
355         if (!p)
356                 goto out;
357
358         EINA_LIST_FREE(p->list, ctl) {
359                 if (ctl->obj)
360                         inputmgr_remove_callback(ctl->obj, &_handler);
361                 free(ctl->part);
362                 free(ctl);
363         }
364
365         free(p);
366
367 out:
368         free(m);
369 }