apply uifw requeste related new back key concept
[framework/appfw/ui-gadget-1.git] / ug-efl-engine / ug-efl-engine.c
1 /*
2  *  UI Gadget
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <glib.h>
23 #include <Elementary.h>
24 #include <ui-gadget-engine.h>
25
26 #include "ug.h"
27 #include "ug-efl-engine.h"
28 #include "ug-dbg.h"
29
30 #ifndef UG_ENGINE_API
31 #define UG_ENGINE_API __attribute__ ((visibility("default")))
32 #endif
33
34 static Evas_Object *navi = NULL;
35 static Evas_Object *conform = NULL;
36 static void on_show_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
37 static void (*show_end_cb)(void* data) = NULL;
38 static void (*hide_end_cb)(void* data) = NULL;
39
40 static void _layout_del_cb(void *data, Evas_Object *obj, void *event_info)
41 {
42         ui_gadget_h ug = (ui_gadget_h)data;
43         if (!ug)
44                 return;
45
46         _WRN("ug(%p) layout is deleted by abnormal path", ug);
47
48         evas_object_event_callback_del(ug->layout, EVAS_CALLBACK_DEL, _layout_del_cb);
49
50         ug->layout_state = UG_LAYOUT_DESTROY;
51         ug->layout = NULL;
52 }
53
54 static Eina_Bool __destroy_end_cb(void *data)
55 {
56         GSList *child;
57         ui_gadget_h ug = (ui_gadget_h)data;
58
59         _DBG("\t __destroy_end_cb ug=%p", ug);
60
61         if (ug->children) {
62                 child = ug->children;
63                 //_DBG("\t ug(%p) has children(%p)", ug, child);
64                 while (child) {
65                         if(!child->data) {
66                                 _ERR("child->data is null");
67                                 return ECORE_CALLBACK_CANCEL;
68                         }
69
70                         //_DBG("\t child(%p) layout_state(%d)", child, ((ui_gadget_h)child->data)->layout_state);
71
72                         if( ((ui_gadget_h)child->data)->layout_state == UG_LAYOUT_HIDEEFFECT) {
73                                 //_DBG("\t wait hideeffect child(%p)", ug);
74                                 return ECORE_CALLBACK_RENEW;
75                         }
76                         child = g_slist_next(child);
77                 }
78         }
79
80         hide_end_cb(ug);
81         return ECORE_CALLBACK_CANCEL;
82 }
83
84 static void __del_effect_end(ui_gadget_h ug)
85 {
86         if (navi) {
87                 Elm_Object_Item *t = elm_naviframe_top_item_get(navi);
88                 Elm_Object_Item *b = elm_naviframe_bottom_item_get(navi);
89                 if (t == b) {
90                         _DBG("\t unset navi");
91                         elm_object_part_content_unset(conform, "elm.swallow.ug");
92                         evas_object_hide(navi);
93                 }
94         }
95         if (ug->layout) {
96                 evas_object_hide(ug->layout);
97                 evas_object_event_callback_del(ug->layout, EVAS_CALLBACK_DEL, _layout_del_cb);
98         }
99
100         ecore_idler_add((Ecore_Task_Cb)__destroy_end_cb, (void *)ug);
101
102         ug->layout_state = UG_LAYOUT_DESTROY;
103 }
104
105 static void __del_finished(void *data, Evas_Object *obj, void *event_info)
106 {
107         ui_gadget_h ug = (ui_gadget_h)data;
108         if (!ug)
109                 return;
110
111         _DBG("\t obj=%p ug=%p", obj, ug);
112
113         evas_object_smart_callback_del(obj, "transition,finished",
114                                         __del_finished);
115
116         if(ug->layout_state == UG_LAYOUT_HIDEEFFECT)
117                 __del_effect_end(ug);
118         else
119                 _ERR("wrong ug(%p) state(%d)", ug, ug->layout_state);
120 }
121
122 static void __del_effect_top_layout(ui_gadget_h ug)
123 {
124         _DBG("\t cb transition add ug=%p", ug);
125         evas_object_smart_callback_add(navi, "transition,finished",
126                                 __del_finished, ug);
127         elm_naviframe_item_pop(navi);
128         ug->effect_layout = NULL;
129         ug->layout_state = UG_LAYOUT_HIDEEFFECT;
130 }
131
132 static void __del_effect_layout(ui_gadget_h ug, ui_gadget_h t_ug)
133 {
134         GSList *child;
135
136         if (!ug)
137                 return;
138
139         _DBG("\t ug=%p state=%d , t_ug=%p", ug, ug->layout_state, t_ug);
140
141         if (ug->children) {
142                 child = ug->children;
143                 _DBG("\t ug(%p) has children(%p)", ug, child);
144                 while (child) {
145                         __del_effect_layout(child->data, t_ug);
146                         child = g_slist_next(child);
147                 }
148         }
149
150         if((ug == t_ug)&&(ug->layout_state != UG_LAYOUT_NOEFFECT)){
151                 if (ug->layout_state != UG_LAYOUT_HIDEEFFECT) {
152                         __del_effect_top_layout(ug);
153                 } else {
154                         _ERR("\t top ug(%p) state is hideeffect.");
155                         return;
156                 }
157         } else {
158                 _DBG("\t remove navi item: ug=%p state=%d", ug, ug->layout_state);
159                 elm_object_item_del(ug->effect_layout);
160                 ug->effect_layout = NULL;
161         }
162
163         __del_effect_end(ug);
164 }
165
166 static void __hide_effect_end(ui_gadget_h ug)
167 {
168         if (navi) {
169                 Elm_Object_Item *t = elm_naviframe_top_item_get(navi);
170                 Elm_Object_Item *b = elm_naviframe_bottom_item_get(navi);
171                 if (t == b) {
172                         _DBG("\t unset navi");
173                         elm_object_part_content_unset(conform, "elm.swallow.ug");
174                         evas_object_hide(navi);
175                 }
176         }
177
178         if (ug->layout) {
179                 evas_object_hide(ug->layout);
180         }
181
182         ug->layout_state = UG_LAYOUT_HIDE;
183 }
184
185 static void __hide_finished(void *data, Evas_Object *obj, void *event_info)
186 {
187         ui_gadget_h ug = (ui_gadget_h)data;
188         if (!ug)
189                 return;
190
191         _DBG("\t obj=%p ug=%p", obj, ug);
192
193         evas_object_smart_callback_del(obj, "transition,finished",
194                                         __hide_finished);
195
196         if(ug->layout_state == UG_LAYOUT_HIDEEFFECT)
197                 __hide_effect_end(ug);
198         else
199                 _ERR("wrong ug(%p) state(%d)", ug, ug->layout_state);
200 }
201
202 static void __on_hideonly_cb(void *data, Evas_Object *obj)
203 {
204         ui_gadget_h ug = (ui_gadget_h)data;
205
206         if (!ug)
207                 return;
208
209         _DBG("\t obj=%p ug=%p layout_state=%d state=%d", obj, ug, ug->layout_state, ug->state);
210
211         evas_object_intercept_hide_callback_del(ug->layout, __on_hideonly_cb);
212         evas_object_event_callback_add(ug->layout, EVAS_CALLBACK_SHOW, on_show_cb, ug);
213
214         if (ug->layout_state == UG_LAYOUT_SHOW) {
215                 ug->layout_state = UG_LAYOUT_HIDE;
216         } else if (ug->layout_state == UG_LAYOUT_NOEFFECT) {
217                 ;
218         } else {
219                 _ERR("wrong ug(%p) state(%d)", ug, ug->layout_state);
220                 return;
221         }
222
223         if (elm_naviframe_top_item_get(navi) == ug->effect_layout) {
224                 _DBG("\t cb transition add ug=%p", ug);
225                 evas_object_smart_callback_add(navi, "transition,finished",
226                                 __hide_finished, ug);
227                 elm_naviframe_item_pop(navi);
228                 ug->layout_state = UG_LAYOUT_HIDEEFFECT;
229         } else {
230                 elm_object_item_del(ug->effect_layout);
231                 __hide_effect_end(ug);
232         }
233
234         ug->effect_layout = NULL;
235 }
236
237 static void on_destroy(ui_gadget_h ug, ui_gadget_h t_ug,
238                        void (*hide_cb)(void* data))
239 {
240         if (!ug)
241                 return;
242         _DBG("\t ug=%p tug=%p state=%d", ug, t_ug, ug->layout_state);
243
244         evas_object_intercept_hide_callback_del(ug->layout,
245                                                 __on_hideonly_cb);
246
247         if(hide_cb == NULL) {
248                 /* ug_destroy_all case */
249                 evas_object_event_callback_del(ug->layout, EVAS_CALLBACK_DEL, _layout_del_cb);
250                 return;
251         }
252
253         if(!hide_end_cb)
254                 hide_end_cb = hide_cb;
255
256         if (ug != t_ug) {
257                 _DBG("requested ug(%p) is not top ug(%p)", ug, t_ug);
258                 __del_effect_layout(ug, t_ug);
259                 return;
260         }
261
262         if(ug->layout_state == UG_LAYOUT_SHOW) {
263                 __del_effect_top_layout(ug);
264         } else if (ug->layout_state == UG_LAYOUT_HIDE
265                 || ug->layout_state == UG_LAYOUT_NOEFFECT
266                 || ug->layout_state == UG_LAYOUT_SHOWEFFECT) {
267                 __del_effect_layout(ug, t_ug);
268         } else if (ug->layout_state == UG_LAYOUT_HIDEEFFECT) {
269                 ;
270         } else {
271                 _WRN("[UG Effect Plug-in] : layout state error!!");
272                 __del_effect_end(ug);
273         }
274 }
275
276 static void __update_indicator_overlap(int opt)
277 {
278         if (GET_OPT_OVERLAP_VAL(opt)) {
279                 _DBG("\t this is Overlap UG. Send overlap sig on_show_cb");
280                 elm_object_signal_emit(conform, "elm,state,indicator,overlap", "");
281         }  else {
282                 _DBG("\t this is no overlap UG. Send no overlap sig on_show_cb");
283                 elm_object_signal_emit(conform, "elm,state,indicator,nooverlap", "");
284         }
285 }
286
287 static void __show_finished(void *data, Evas_Object *obj, void *event_info)
288 {
289         ui_gadget_h ug = (ui_gadget_h)data;
290         if (!ug)
291                 return;
292
293         _DBG("\tobj=%p ug=%p", obj, ug);
294
295         evas_object_smart_callback_del(obj, "transition,finished",
296                                         __show_finished);
297
298         if (ug->layout_state == UG_LAYOUT_DESTROY) {
299                 _DBG("ug(%p) already destroyed", ug);
300         } else if (ug->layout_state == UG_LAYOUT_SHOWEFFECT) {
301                 ug->layout_state = UG_LAYOUT_SHOW;
302                 if((show_end_cb)&&(ug->state == UG_STATE_CREATED))
303                         show_end_cb(ug);
304         } else {
305                 _ERR("wrong state(%d)", ug->layout_state);
306         }
307
308         return;
309 }
310
311 static void on_show_cb(void *data, Evas *e, Evas_Object *obj,
312                        void *event_info)
313 {
314         ui_gadget_h ug = (ui_gadget_h)data;
315         if (!ug)
316                 return;
317         _DBG("\tobj=%p ug=%p layout=%p state=%d", obj, ug, ug->layout, ug->layout_state);
318
319         evas_object_event_callback_del(ug->layout, EVAS_CALLBACK_SHOW, on_show_cb);
320
321         evas_object_intercept_hide_callback_add(ug->layout,
322                                                 __on_hideonly_cb, ug);
323
324         //if 'elm.swallow.ug' string is changed, msg team have to apply this changes.
325         elm_object_part_content_set(conform, "elm.swallow.ug", navi);
326
327         if (ug->layout_state == UG_LAYOUT_HIDEEFFECT
328                 || ug->layout_state == UG_LAYOUT_HIDE
329             || ug->layout_state == UG_LAYOUT_INIT) {
330                 _DBG("\t UG_LAYOUT_Init(%d) obj=%p", ug->layout_state, obj);
331                 ug->layout_state = UG_LAYOUT_SHOWEFFECT;
332
333                 __update_indicator_overlap(ug->opt);
334
335                 evas_object_smart_callback_add(navi, "transition,finished",
336                                                 __show_finished, ug);
337                 ug->effect_layout = elm_naviframe_item_push(navi, NULL, NULL, NULL,
338                                                     ug->layout, NULL);
339         } else if (ug->layout_state == UG_LAYOUT_NOEFFECT) {
340                 _DBG("\t UG_LAYOUT_NOEFFECT obj=%p", obj);
341
342                 __update_indicator_overlap(ug->opt);
343
344                 Elm_Object_Item *navi_top = elm_naviframe_top_item_get(navi);
345                 ug->effect_layout = elm_naviframe_item_insert_after(navi,
346                                 navi_top, NULL, NULL, NULL, ug->layout, NULL);
347                 //ug start cb
348                 if(show_end_cb)
349                         show_end_cb(ug);
350         } else {
351                 _ERR("\tlayout state error!! state=%d\n", ug->layout_state);
352         }
353
354         _DBG("\ton_show_cb end ug=%p", ug);
355 }
356
357 static void *on_create(void *win, ui_gadget_h ug,
358                                         void (*show_cb)(void* data))
359 {
360         Evas_Object *navi_bg;
361         Evas_Object *con = NULL;
362
363         if (!ug)
364                 return NULL;
365         _DBG("\t ug=%p state=%d", ug, ug->layout_state);
366
367         con = evas_object_data_get(win, "\377 elm,conformant");
368         if (con) {
369                 conform = con;
370                 _DBG("\t There is conformant");
371         }
372         else
373                 _DBG("\t There is NO conformant");
374
375         if (!navi) {
376                 navi = elm_naviframe_add(conform);
377                 elm_object_focus_allow_set(navi, EINA_FALSE);
378                 elm_object_style_set(navi, "uglib");
379                 elm_naviframe_content_preserve_on_pop_set(navi, EINA_TRUE);
380                 _DBG("\t new navi first navi=%p", navi);
381                 elm_naviframe_prev_btn_auto_pushed_set(navi, EINA_FALSE);
382
383                 navi_bg = evas_object_rectangle_add(evas_object_evas_get(navi));
384                 evas_object_size_hint_fill_set(navi_bg, EVAS_HINT_FILL,
385                                                 EVAS_HINT_FILL);
386                 evas_object_color_set(navi_bg, 0, 0, 0, 0);
387                 elm_naviframe_item_push(navi, NULL, NULL, NULL, navi_bg, NULL);
388         }
389
390         if(!show_end_cb)
391                 show_end_cb = show_cb;
392
393         evas_object_hide(ug->layout);
394         evas_object_event_callback_add(ug->layout, EVAS_CALLBACK_SHOW, on_show_cb, ug);
395         evas_object_event_callback_add(ug->layout, EVAS_CALLBACK_DEL, _layout_del_cb, ug);
396
397         ug->layout_state = UG_LAYOUT_INIT;
398
399         return conform;
400 }
401
402 UG_ENGINE_API int UG_ENGINE_INIT(struct ug_engine_ops *ops)
403 {
404         if (!ops)
405                 return -1;
406
407         ops->create = on_create;
408         ops->destroy = on_destroy;
409
410         return 0;
411 }
412
413 UG_ENGINE_API void UG_ENGINE_EXIT(struct ug_engine_ops *ops)
414 {
415 }