1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define ELM_WIDGET_ITEM_PROTECTED
8 #define ELM_WIDGET_PROTECTED
9 #define EFL_UI_L10N_PROTECTED
10 #define EFL_PART_PROTECTED
11
12 #include <Elementary.h>
13 #include "elm_priv.h"
14 #include "elm_naviframe_eo.h"
15 #include "elm_naviframe_item_eo.h"
16 #include "elm_widget_naviframe.h"
17 #include "elm_widget_container.h"
18
19 #include "elm_naviframe_part.eo.h"
20 #include "elm_part_helper.h"
21
22 #define MY_CLASS ELM_NAVIFRAME_CLASS
23
24 #define MY_CLASS_NAME "Elm_Naviframe"
25 #define MY_CLASS_NAME_LEGACY "elm_naviframe"
26
27 static const char CONTENT_PART[] = "elm.swallow.content";
28 static const char PREV_BTN_PART[] = "elm.swallow.prev_btn";
29 static const char NEXT_BTN_PART[] = "elm.swallow.next_btn";
30 static const char ICON_PART[] = "elm.swallow.icon";
31 static const char TITLE_PART[] = "elm.text.title";
32 static const char SUBTITLE_PART[] = "elm.text.subtitle";
33 static const char TITLE_ACCESS_PART[] = "access.title";
34
35 static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
36 static const char SIG_TITLE_TRANSITION_FINISHED[] = "title,transition,finished";
37 static const char SIG_TITLE_CLICKED[] = "title,clicked";
38 static const char SIG_ITEM_ACTIVATED[] = "item,activated";
39
40 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
41 {SIG_TRANSITION_FINISHED, ""},
42 {SIG_TITLE_TRANSITION_FINISHED, ""},
43 {SIG_TITLE_CLICKED, ""},
44 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
45 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
46 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
47 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
48 {SIG_ITEM_ACTIVATED, ""},
49 {NULL, NULL}
50 };
51
52 static void _on_item_back_btn_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED);
53
54 static Eina_Bool _key_action_top_item_get(Evas_Object *obj, const char *params);
55 static Eina_Bool _key_action_item_pop(Evas_Object *obj, const char *params);
56
57 static const Elm_Action key_actions[] = {
58 {"top_item_get", _key_action_top_item_get},
59 {"item_pop", _key_action_item_pop},
60 {NULL, NULL}
61 };
62
63 EOLIAN static void
_elm_naviframe_efl_ui_widget_resize_object_set(Eo * obj,Elm_Naviframe_Data * pd EINA_UNUSED,Efl_Canvas_Object * sobj)64 _elm_naviframe_efl_ui_widget_resize_object_set(Eo *obj, Elm_Naviframe_Data *pd EINA_UNUSED,
65 Efl_Canvas_Object *sobj)
66 {
67 if (!sobj || !efl_finalized_get(obj)) goto super;
68 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
69
70 if (wd->resize_obj == sobj) return;
71
72 // Detach the previous page as resize object to avoid any modifications to
73 // it by the widget implementation. This preserves clip, smart membership,
74 // focus, etc...
75 wd->resize_obj = NULL;
76
77 super:
78 efl_ui_widget_resize_object_set(efl_super(obj, MY_CLASS), sobj);
79 }
80
81 static void
_resize_object_reset(Evas_Object * obj,Elm_Naviframe_Item_Data * it)82 _resize_object_reset(Evas_Object *obj, Elm_Naviframe_Item_Data *it)
83 {
84 if (it)
85 {
86 elm_widget_resize_object_set(obj, VIEW(it));
87 evas_object_raise(VIEW(it));
88 }
89 }
90
91 static void
_prev_page_focus_recover(Elm_Naviframe_Item_Data * it)92 _prev_page_focus_recover(Elm_Naviframe_Item_Data *it)
93 {
94 Elm_Naviframe *n = it->base->widget;
95
96 efl_ui_focus_manager_focus_set(efl_ui_focus_object_focus_manager_get(n), n);
97 }
98
99 EOLIAN static void
_elm_naviframe_efl_ui_l10n_translation_update(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)100 _elm_naviframe_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
101 {
102 Elm_Naviframe_Item_Data *it;
103
104 EINA_INLIST_FOREACH(sd->stack, it)
105 elm_wdg_item_translate(EO_OBJ(it));
106
107 efl_ui_l10n_translation_update(efl_super(obj, MY_CLASS));
108 }
109
110 static void
_item_content_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)111 _item_content_del_cb(void *data,
112 Evas *e EINA_UNUSED,
113 Evas_Object *obj EINA_UNUSED,
114 void *event_info EINA_UNUSED)
115 {
116 Elm_Naviframe_Item_Data *it = data;
117
118 it->content = NULL;
119 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
120 }
121
122 static void
_item_title_prev_btn_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)123 _item_title_prev_btn_del_cb(void *data,
124 Evas *e EINA_UNUSED,
125 Evas_Object *obj EINA_UNUSED,
126 void *event_info EINA_UNUSED)
127 {
128 Elm_Naviframe_Item_Data *it = data;
129
130 it->title_prev_btn = NULL;
131 if (it->auto_pushed_btn) it->auto_pushed_btn = NULL;
132 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
133 }
134
135 static void
_item_title_next_btn_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)136 _item_title_next_btn_del_cb(void *data,
137 Evas *e EINA_UNUSED,
138 Evas_Object *obj EINA_UNUSED,
139 void *event_info EINA_UNUSED)
140 {
141 Elm_Naviframe_Item_Data *it = data;
142
143 it->title_next_btn = NULL;
144 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
145 }
146
147 static void
_item_title_icon_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)148 _item_title_icon_del_cb(void *data,
149 Evas *e EINA_UNUSED,
150 Evas_Object *obj EINA_UNUSED,
151 void *event_info EINA_UNUSED)
152 {
153 Elm_Naviframe_Item_Data *it = data;
154
155 it->title_icon = NULL;
156 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
157 }
158
159 static void
_title_content_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)160 _title_content_del(void *data,
161 Evas *e EINA_UNUSED,
162 Evas_Object *obj EINA_UNUSED,
163 void *event_info EINA_UNUSED)
164 {
165 char buf[1024];
166 Elm_Naviframe_Content_Item_Pair *pair = data;
167 Elm_Naviframe_Item_Data *it = pair->it;
168 snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
169 elm_object_signal_emit(VIEW(it), buf, "elm");
170 it->content_list = eina_inlist_remove(it->content_list,
171 EINA_INLIST_GET(pair));
172 eina_stringshare_del(pair->part);
173 free(pair);
174 }
175
176 static void
_item_free(Elm_Naviframe_Item_Data * it)177 _item_free(Elm_Naviframe_Item_Data *it)
178 {
179 Eina_Inlist *l;
180 Elm_Naviframe_Text_Item_Pair *text_pair;
181
182 eina_stringshare_del(it->title_label);
183 eina_stringshare_del(it->subtitle_label);
184
185
186 EINA_INLIST_FOREACH_SAFE(it->text_list, l, text_pair)
187 {
188 eina_stringshare_del(text_pair->part);
189 free(text_pair);
190 }
191 }
192
193 static void
_item_content_signals_emit(Elm_Naviframe_Item_Data * it)194 _item_content_signals_emit(Elm_Naviframe_Item_Data *it)
195 {
196 Elm_Naviframe_Content_Item_Pair *content_pair;
197 char buf[1024];
198 //content
199 if (it->content)
200 elm_object_signal_emit(VIEW(it), "elm,state,content,show", "elm");
201 else
202 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
203
204 //prev button
205 if (it->title_prev_btn)
206 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
207 else
208 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
209
210 //next button
211 if (it->title_next_btn)
212 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
213 else
214 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
215
216 if (it->title_icon)
217 elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
218 else
219 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
220
221 EINA_INLIST_FOREACH(it->content_list, content_pair)
222 {
223 if (content_pair->content)
224 snprintf(buf, sizeof(buf), "elm,state,%s,show", content_pair->part);
225 else
226 snprintf(buf, sizeof(buf), "elm,state,%s,hide", content_pair->part);
227 elm_object_signal_emit(VIEW(it), buf, "elm");
228 }
229 }
230
231 static void
_item_text_signals_emit(Elm_Naviframe_Item_Data * it)232 _item_text_signals_emit(Elm_Naviframe_Item_Data *it)
233 {
234 Elm_Naviframe_Text_Item_Pair *text_pair;
235 char buf[1024];
236
237 if ((it->title_label) && (it->title_label[0]))
238 elm_object_signal_emit(VIEW(it), "elm,state,title_label,show", "elm");
239 else
240 elm_object_signal_emit(VIEW(it), "elm,state,title_label,hide", "elm");
241
242 if ((it->subtitle_label) && (it->subtitle_label[0]))
243 elm_object_signal_emit(VIEW(it), "elm,state,subtitle,show", "elm");
244 else
245 elm_object_signal_emit(VIEW(it), "elm,state,subtitle,hide", "elm");
246
247 EINA_INLIST_FOREACH(it->text_list, text_pair)
248 {
249 if (elm_object_part_text_get(VIEW(it), text_pair->part))
250 snprintf(buf, sizeof(buf), "elm,state,%s,show", text_pair->part);
251 else
252 snprintf(buf, sizeof(buf), "elm,state,%s,hide", text_pair->part);
253 elm_object_signal_emit(VIEW(it), buf, "elm");
254 }
255 }
256
257 static Evas_Object *
_access_object_get(Elm_Naviframe_Item_Data * it,const char * part)258 _access_object_get(Elm_Naviframe_Item_Data *it, const char* part)
259 {
260 Evas_Object *po, *ao, *o;
261
262 o = elm_layout_edje_get(VIEW(it));
263 edje_object_freeze(o);
264 po = (Evas_Object *)edje_object_part_object_get(o, part);
265 edje_object_thaw(o);
266 ao = evas_object_data_get(po, "_part_access_obj");
267
268 return ao;
269 }
270
271 static Eina_Bool
_access_info_has(Evas_Object * obj,int type)272 _access_info_has(Evas_Object *obj, int type)
273 {
274 Elm_Access_Info *ac;
275 Elm_Access_Item *ai;
276 Eina_List *l;
277
278 ac = _elm_access_info_get(obj);
279 if (!ac) return EINA_FALSE;
280
281 EINA_LIST_FOREACH(ac->items, l, ai)
282 {
283 if (ai->type == type)
284 {
285 if (ai->func || ai->data) return EINA_TRUE;
286 }
287 }
288
289 return EINA_FALSE;
290 }
291
292 static void
_item_signals_emit(Elm_Naviframe_Item_Data * it)293 _item_signals_emit(Elm_Naviframe_Item_Data *it)
294 {
295 _item_text_signals_emit(it);
296 _item_content_signals_emit(it);
297 }
298
299 /* FIXME: we need to handle the case when this function is called
300 * during a transition */
301 static void
_item_style_set(Elm_Naviframe_Item_Data * it,const char * item_style)302 _item_style_set(Elm_Naviframe_Item_Data *it,
303 const char *item_style)
304 {
305 char buf[256];
306
307 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
308
309 if (!item_style)
310 {
311 strcpy(buf, "item/basic");
312 elm_wdg_item_style_set(efl_super(EO_OBJ(it), ELM_NAVIFRAME_ITEM_CLASS), "basic");
313 }
314 else
315 {
316 snprintf(buf, sizeof(buf), "item/%s", item_style);
317 elm_wdg_item_style_set(efl_super(EO_OBJ(it), ELM_NAVIFRAME_ITEM_CLASS), item_style);
318 }
319
320 if (!elm_layout_theme_set(VIEW(it), "naviframe", buf,
321 elm_widget_style_get(WIDGET(it))))
322 {
323 /* Naviframe item theme name is combined with item style name and widget
324 * style name.
325 * Therefore, if the item theme name is not found, then set "item/basic"
326 * item style name as a default item style name. */
327 if (!elm_layout_theme_set(VIEW(it), "naviframe", "item/basic",
328 elm_widget_style_get(WIDGET(it))))
329 CRI("Failed to set layout!");
330 }
331
332 if (sd->freeze_events)
333 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
334 }
335
336 static void
_on_item_title_transition_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)337 _on_item_title_transition_finished(void *data,
338 Evas_Object *obj EINA_UNUSED,
339 const char *emission EINA_UNUSED,
340 const char *source EINA_UNUSED)
341 {
342 Elm_Naviframe_Item_Data *it = data;
343
344 efl_event_callback_legacy_call
345 (WIDGET(it), ELM_NAVIFRAME_EVENT_TITLE_TRANSITION_FINISHED, EO_OBJ(it));
346 }
347
348 static void
_item_title_enabled_update(Elm_Naviframe_Item_Data * nit,Eina_Bool transition)349 _item_title_enabled_update(Elm_Naviframe_Item_Data *nit, Eina_Bool transition)
350 {
351 transition = !!transition;
352 if (transition)
353 {
354 if (nit->title_enabled)
355 elm_object_signal_emit(VIEW(nit), "elm,action,title,show", "elm");
356 else
357 elm_object_signal_emit(VIEW(nit), "elm,action,title,hide", "elm");
358 }
359 else
360 {
361 if (nit->title_enabled)
362 elm_object_signal_emit(VIEW(nit), "elm,state,title,show", "elm");
363 else
364 elm_object_signal_emit(VIEW(nit), "elm,state,title,hide", "elm");
365 }
366 edje_object_message_signal_process(elm_layout_edje_get(VIEW(nit)));
367 }
368
369 EOLIAN static Eina_Error
_elm_naviframe_efl_ui_widget_theme_apply(Eo * obj,Elm_Naviframe_Data * sd)370 _elm_naviframe_efl_ui_widget_theme_apply(Eo *obj, Elm_Naviframe_Data *sd)
371 {
372 Elm_Naviframe_Item_Data *it;
373 const char *style = NULL, *sstyle = NULL;
374
375 style = efl_ui_widget_style_get(obj);
376
377 EINA_INLIST_FOREACH(sd->stack, it)
378 {
379 sstyle = efl_ui_widget_style_get(VIEW(it));
380 if ((style && sstyle) && strcmp(style, sstyle))
381 _item_style_set(it, elm_wdg_item_style_get(EO_OBJ(it)));
382 _item_signals_emit(it);
383 _item_title_enabled_update(it, EINA_FALSE);
384 }
385
386 elm_layout_sizing_eval(obj);
387 return EFL_UI_THEME_APPLY_ERROR_NONE;
388 }
389
390 static char *
_access_info_cb(void * data,Evas_Object * obj EINA_UNUSED)391 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
392 {
393 Elm_Naviframe_Item_Data *nit;
394 Evas_Object *layout;
395 Eina_Strbuf *buf;
396 const char *info;
397 char *ret;
398
399 nit = data;
400 if (!nit->title_enabled) return NULL;
401
402 layout = VIEW(nit);
403 info = elm_object_part_text_get(layout, TITLE_PART);
404 if (!info) return NULL;
405
406 buf = eina_strbuf_new();
407 eina_strbuf_append(buf, info);
408 eina_strbuf_append_printf(buf, ", %s", N_("Title"));
409
410 info = elm_object_part_text_get(layout, SUBTITLE_PART);
411 if (!info) goto end;
412 if (!strcmp(info, "")) goto end;
413
414 eina_strbuf_append_printf(buf, ", %s", info);
415 eina_strbuf_append_printf(buf, ", %s", N_("Subtitle"));
416
417 end:
418 ret = eina_strbuf_string_steal(buf);
419 eina_strbuf_free(buf);
420 return ret;
421 }
422
423 static void
_access_obj_process(Elm_Naviframe_Item_Data * it,Eina_Bool is_access)424 _access_obj_process(Elm_Naviframe_Item_Data *it, Eina_Bool is_access)
425 {
426 Evas_Object *ao, *eo;
427
428 if (is_access && (it->title_label || it->subtitle_label))
429 {
430 if (!_access_object_get(it, TITLE_ACCESS_PART))
431 {
432 eo = elm_layout_edje_get(VIEW(it));
433 ao =_elm_access_edje_object_part_object_register(WIDGET(it), eo,
434 TITLE_ACCESS_PART);
435 _elm_access_text_set(_elm_access_info_get(ao),
436 ELM_ACCESS_TYPE, E_("Title"));
437 _elm_access_callback_set(_elm_access_info_get(ao),
438 ELM_ACCESS_INFO, _access_info_cb, it);
439 /* to access title access object, any idea? */
440 it->base->access_obj = ao;
441 }
442 }
443 else
444 {
445 /* to access title access object, any idea? */
446 ao = it->base->access_obj;
447 if (!ao) return;
448
449 if (it->title_label || it->subtitle_label)
450 _elm_access_edje_object_part_object_unregister
451 (WIDGET(it), elm_layout_edje_get(VIEW(it)), TITLE_ACCESS_PART);
452 evas_object_del(ao);
453 }
454 }
455
456 static void
_elm_naviframe_item_elm_widget_item_part_text_set(Eo * eo_it,Elm_Naviframe_Item_Data * it,const char * part,const char * label)457 _elm_naviframe_item_elm_widget_item_part_text_set(Eo *eo_it,
458 Elm_Naviframe_Item_Data *it,
459 const char *part,
460 const char *label)
461 {
462 Elm_Naviframe_Item_Data *nit = it;
463 Elm_Naviframe_Text_Item_Pair *pair = NULL;
464 char buf[1024];
465
466 if ((!part) || (!strcmp(part, "default")) ||
467 (!strcmp(part, TITLE_PART)))
468 {
469 eina_stringshare_replace(&nit->title_label, label);
470 if (label)
471 elm_object_signal_emit(VIEW(it), "elm,state,title_label,show", "elm");
472 else
473 elm_object_signal_emit(VIEW(it), "elm,state,title_label,hide", "elm");
474 elm_object_part_text_set(VIEW(it), TITLE_PART, label);
475 }
476 else if ((!strcmp(part, "subtitle")) || (!strcmp(part, SUBTITLE_PART)))
477 {
478 eina_stringshare_replace(&nit->subtitle_label, label);
479 if (label)
480 elm_object_signal_emit(VIEW(it), "elm,state,subtitle,show", "elm");
481 else
482 elm_object_signal_emit(VIEW(it), "elm,state,subtitle,hide", "elm");
483 elm_object_part_text_set(VIEW(it), SUBTITLE_PART, label);
484 }
485 else
486 {
487 EINA_INLIST_FOREACH(nit->text_list, pair)
488 if (!strcmp(part, pair->part)) break;
489
490 if (!pair)
491 {
492 pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
493 if (!pair)
494 {
495 ERR("Failed to allocate new text part of the item! : naviframe=%p",
496 WIDGET(it));
497 return;
498 }
499 eina_stringshare_replace(&pair->part, part);
500 nit->text_list = eina_inlist_append(nit->text_list,
501 EINA_INLIST_GET(pair));
502 }
503 if (label)
504 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
505 else
506 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
507 elm_object_signal_emit(VIEW(it), buf, "elm");
508 elm_object_part_text_set(VIEW(it), part, label);
509 }
510
511 /* access */
512 if (_elm_config->access_mode)
513 _access_obj_process(nit, EINA_TRUE);
514
515 buf[0] = 0;
516 if (nit->title_label)
517 strncpy(buf, nit->title_label, sizeof(buf) - 1);
518 if (nit->subtitle_label)
519 {
520 if ((nit->title_label) && (strlen(buf) < (sizeof(buf) - 2)))
521 strcat(buf, " ");
522 strncat(buf, nit->subtitle_label, sizeof(buf) - strlen(buf) - 2);
523 }
524 efl_access_object_i18n_name_set(eo_it, buf);
525
526 elm_layout_sizing_eval(WIDGET(nit));
527 }
528
529 EOLIAN static const char *
_elm_naviframe_item_elm_widget_item_part_text_get(const Eo * nit EINA_UNUSED,Elm_Naviframe_Item_Data * it,const char * part)530 _elm_naviframe_item_elm_widget_item_part_text_get(const Eo *nit EINA_UNUSED,
531 Elm_Naviframe_Item_Data *it,
532 const char *part)
533 {
534 char buf[1024];
535
536 if (!part || !strcmp(part, "default"))
537 snprintf(buf, sizeof(buf), TITLE_PART);
538 else if (!strcmp("subtitle", part))
539 snprintf(buf, sizeof(buf), SUBTITLE_PART);
540 else
541 snprintf(buf, sizeof(buf), "%s", part);
542
543 return elm_object_part_text_get(VIEW(it), buf);
544 }
545
546 EOLIAN static void
_elm_naviframe_item_efl_object_destructor(Eo * eo_item,Elm_Naviframe_Item_Data * it)547 _elm_naviframe_item_efl_object_destructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
548 {
549 Eina_List *l;
550 Elm_Naviframe_Op *nfo;
551 Elm_Naviframe_Item_Data *nit = it;
552
553 ELM_NAVIFRAME_DATA_GET(WIDGET(nit), sd);
554
555 nit->delete_me = EINA_TRUE;
556
557 // This should not happen, but just in case and by security
558 // make sure there is no more reference to this item.
559 EINA_LIST_FOREACH(sd->ops, l, nfo)
560 {
561 /* If an item is newly pushed and then deleted by elm_object_item_del()
562 * before item push transition is not started, then the item push
563 * transitions for both new item and current item should be cancelled.
564 * Otherwise, the current item becomes invisible due to the item push
565 * transition. */
566 if ((nit->pushing) && (nfo->self == nit))
567 {
568 nfo->self = NULL;
569 nfo->related = NULL;
570 }
571 else
572 {
573 if (nfo->self == nit)
574 nfo->self = NULL;
575 if (nfo->related == nit)
576 nfo->related = NULL;
577 }
578 }
579
580 _item_free(nit);
581
582 efl_destructor(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
583 }
584
585 static void
_item_content_set(Elm_Naviframe_Item_Data * it,Evas_Object * content)586 _item_content_set(Elm_Naviframe_Item_Data *it,
587 Evas_Object *content)
588 {
589 if (it->content == content) return;
590
591 evas_object_del(it->content);
592 it->content = content;
593
594 if (!content) return;
595
596 elm_object_part_content_set(VIEW(it), CONTENT_PART, content);
597 elm_object_signal_emit(VIEW(it), "elm,state,content,show", "elm");
598
599 evas_object_event_callback_add
600 (content, EVAS_CALLBACK_DEL, _item_content_del_cb, it);
601 }
602
603 static void
_item_title_prev_btn_set(Elm_Naviframe_Item_Data * it,Evas_Object * btn)604 _item_title_prev_btn_set(Elm_Naviframe_Item_Data *it,
605 Evas_Object *btn)
606 {
607 if (it->title_prev_btn == btn) return;
608 evas_object_del(it->title_prev_btn);
609 it->title_prev_btn = btn;
610 if (it->auto_pushed_btn && (it->auto_pushed_btn != btn))
611 it->auto_pushed_btn = NULL;
612 if (!btn) return;
613
614 elm_object_part_content_set(VIEW(it), PREV_BTN_PART, btn);
615 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
616 evas_object_event_callback_add
617 (btn, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb, it);
618
619 //FIXME: set back button callback here after elm 2.0
620 }
621
622 static void
_item_title_next_btn_set(Elm_Naviframe_Item_Data * it,Evas_Object * btn)623 _item_title_next_btn_set(Elm_Naviframe_Item_Data *it,
624 Evas_Object *btn)
625 {
626 if (it->title_next_btn == btn) return;
627 evas_object_del(it->title_next_btn);
628 it->title_next_btn = btn;
629 if (!btn) return;
630
631 elm_object_part_content_set(VIEW(it), NEXT_BTN_PART, btn);
632 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
633
634 evas_object_event_callback_add
635 (btn, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb, it);
636 }
637
638 static void
_item_title_icon_set(Elm_Naviframe_Item_Data * it,Evas_Object * icon)639 _item_title_icon_set(Elm_Naviframe_Item_Data *it,
640 Evas_Object *icon)
641 {
642 if (it->title_icon == icon) return;
643 evas_object_del(it->title_icon);
644 it->title_icon = icon;
645 if (!icon) return;
646
647 elm_object_part_content_set(VIEW(it), ICON_PART, icon);
648 elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
649
650 evas_object_event_callback_add
651 (icon, EVAS_CALLBACK_DEL, _item_title_icon_del_cb, it);
652 }
653
654 static Evas_Object *
_item_content_unset(Elm_Naviframe_Item_Data * it)655 _item_content_unset(Elm_Naviframe_Item_Data *it)
656 {
657 Evas_Object *content = it->content;
658
659 if (!content) return NULL;
660
661 elm_object_part_content_unset(VIEW(it), CONTENT_PART);
662 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
663
664 evas_object_event_callback_del
665 (content, EVAS_CALLBACK_DEL, _item_content_del_cb);
666
667 it->content = NULL;
668 return content;
669 }
670
671 static Evas_Object *
_item_title_prev_btn_unset(Elm_Naviframe_Item_Data * it)672 _item_title_prev_btn_unset(Elm_Naviframe_Item_Data *it)
673 {
674 Evas_Object *content = it->title_prev_btn;
675
676 if (!content) return NULL;
677
678 elm_object_part_content_unset(VIEW(it), PREV_BTN_PART);
679 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
680
681 evas_object_event_callback_del
682 (content, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb);
683 evas_object_smart_callback_del(content, "clicked", _on_item_back_btn_clicked);
684 it->title_prev_btn = NULL;
685 if (it->auto_pushed_btn) it->auto_pushed_btn = NULL;
686 return content;
687 }
688
689 static Evas_Object *
_item_title_next_btn_unset(Elm_Naviframe_Item_Data * it)690 _item_title_next_btn_unset(Elm_Naviframe_Item_Data *it)
691 {
692 Evas_Object *content = it->title_next_btn;
693
694 if (!content) return NULL;
695
696 elm_object_part_content_unset(VIEW(it), NEXT_BTN_PART);
697 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
698
699 evas_object_event_callback_del
700 (content, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb);
701
702 it->title_next_btn = NULL;
703 return content;
704 }
705
706 static Evas_Object *
_item_title_icon_unset(Elm_Naviframe_Item_Data * it)707 _item_title_icon_unset(Elm_Naviframe_Item_Data *it)
708 {
709 Evas_Object *content = it->title_icon;
710
711 if (!content) return NULL;
712
713 elm_object_part_content_unset(VIEW(it), ICON_PART);
714 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
715
716 evas_object_event_callback_del
717 (content, EVAS_CALLBACK_DEL, _item_title_icon_del_cb);
718
719 it->title_icon = NULL;
720 return content;
721 }
722
723 /* since we have each item as layout, we can't reusing the layout's
724 * aliasing, so let's do it ourselves */
725 static void
_part_aliasing_eval(const char ** part)726 _part_aliasing_eval(const char **part)
727 {
728 if (!*part || !strcmp(*part, "default"))
729 *part = CONTENT_PART;
730 else if (!strcmp(*part, "prev_btn"))
731 *part = PREV_BTN_PART;
732 else if (!strcmp(*part, "next_btn"))
733 *part = NEXT_BTN_PART;
734 else if (!strcmp(*part, "icon"))
735 *part = ICON_PART;
736 }
737
738 static void
_title_content_set(Elm_Naviframe_Item_Data * it,const char * part,Evas_Object * content)739 _title_content_set(Elm_Naviframe_Item_Data *it,
740 const char *part,
741 Evas_Object *content)
742 {
743 Elm_Naviframe_Content_Item_Pair *pair = NULL;
744 char buf[1024];
745
746 EINA_INLIST_FOREACH(it->content_list, pair)
747 if (!strcmp(part, pair->part)) break;
748 if (pair)
749 {
750 if (pair->content == content) return;
751 if (pair->content)
752 evas_object_event_callback_del(pair->content,
753 EVAS_CALLBACK_DEL,
754 _title_content_del);
755 if (content) elm_object_part_content_set(VIEW(it), part, content);
756 }
757 else
758 {
759 if (!content) return;
760
761 //Remove the pair if new content was swallowed into other part.
762 EINA_INLIST_FOREACH(it->content_list, pair)
763 {
764 if (pair->content == content)
765 {
766 eina_stringshare_del(pair->part);
767 it->content_list = eina_inlist_remove(it->content_list,
768 EINA_INLIST_GET(pair));
769 evas_object_event_callback_del(pair->content,
770 EVAS_CALLBACK_DEL,
771 _title_content_del);
772 free(pair);
773 break;
774 }
775 }
776
777 //New pair
778 pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
779 if (!pair)
780 {
781 ERR("Failed to allocate new content part of the item! : naviframe=%p",
782 WIDGET(it));
783 return;
784 }
785 pair->it = it;
786 eina_stringshare_replace(&pair->part, part);
787 it->content_list = eina_inlist_append(it->content_list,
788 EINA_INLIST_GET(pair));
789 elm_object_part_content_set(VIEW(it), part, content);
790 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
791 elm_object_signal_emit(VIEW(it), buf, "elm");
792 }
793 pair->content = content;
794 evas_object_event_callback_add(content,
795 EVAS_CALLBACK_DEL,
796 _title_content_del,
797 pair);
798 }
799
800 EOLIAN static void
_elm_naviframe_item_elm_widget_item_part_content_set(Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part,Evas_Object * content)801 _elm_naviframe_item_elm_widget_item_part_content_set(Eo *eo_nit EINA_UNUSED,
802 Elm_Naviframe_Item_Data *nit,
803 const char *part,
804 Evas_Object *content)
805 {
806 _part_aliasing_eval(&part);
807
808 //specified parts
809 if (!strcmp(part, CONTENT_PART))
810 _item_content_set(nit, content);
811 else if (!strcmp(part, PREV_BTN_PART))
812 _item_title_prev_btn_set(nit, content);
813 else if (!strcmp(part, NEXT_BTN_PART))
814 _item_title_next_btn_set(nit, content);
815 else if (!strcmp(part, ICON_PART))
816 _item_title_icon_set(nit, content);
817 else
818 _title_content_set(nit, part, content);
819
820 elm_layout_sizing_eval(WIDGET(nit));
821 }
822
823 EOLIAN static Evas_Object *
_elm_naviframe_item_elm_widget_item_part_content_get(const Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part)824 _elm_naviframe_item_elm_widget_item_part_content_get(const Eo *eo_nit EINA_UNUSED,
825 Elm_Naviframe_Item_Data *nit,
826 const char *part)
827 {
828 _part_aliasing_eval(&part);
829
830 //specified parts
831 if (!strcmp(part, CONTENT_PART))
832 return nit->content;
833 else if (!strcmp(part, PREV_BTN_PART))
834 return nit->title_prev_btn;
835 else if (!strcmp(part, NEXT_BTN_PART))
836 return nit->title_next_btn;
837 else if (!strcmp(part, ICON_PART))
838 return nit->title_icon;
839
840 //common parts
841 return elm_object_part_content_get(VIEW(nit), part);
842 }
843
844 static Evas_Object *
_title_content_unset(Elm_Naviframe_Item_Data * it,const char * part)845 _title_content_unset(Elm_Naviframe_Item_Data *it, const char *part)
846 {
847 Elm_Naviframe_Content_Item_Pair *pair = NULL;
848 char buf[1028];
849 Evas_Object *content = NULL;
850
851 EINA_INLIST_FOREACH(it->content_list, pair)
852 {
853 if (!strcmp(part, pair->part))
854 {
855 content = pair->content;
856 eina_stringshare_del(pair->part);
857 it->content_list = eina_inlist_remove(it->content_list,
858 EINA_INLIST_GET(pair));
859 free(pair);
860 break;
861 }
862 }
863
864 if (!content) return NULL;
865
866 elm_object_part_content_unset(VIEW(it), part);
867 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
868 elm_object_signal_emit(VIEW(it), buf, "elm");
869 evas_object_event_callback_del(content,
870 EVAS_CALLBACK_DEL,
871 _title_content_del);
872 return content;
873 }
874
875 EOLIAN static Evas_Object *
_elm_naviframe_item_elm_widget_item_part_content_unset(Eo * eo_nit EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * part)876 _elm_naviframe_item_elm_widget_item_part_content_unset(Eo *eo_nit EINA_UNUSED,
877 Elm_Naviframe_Item_Data *nit,
878 const char *part)
879 {
880 Evas_Object *o = NULL;
881
882 _part_aliasing_eval(&part);
883
884 //specified parts
885 if (!strcmp(part, CONTENT_PART))
886 o = _item_content_unset(nit);
887 else if (!strcmp(part, PREV_BTN_PART))
888 o = _item_title_prev_btn_unset(nit);
889 else if (!strcmp(part, NEXT_BTN_PART))
890 o = _item_title_next_btn_unset(nit);
891 else if (!strcmp(part, ICON_PART))
892 o = _item_title_icon_unset(nit);
893 else
894 o = _title_content_unset(nit, part);
895
896 elm_layout_sizing_eval(WIDGET(nit));
897
898 return o;
899 }
900
901 EOLIAN static void
_elm_naviframe_item_elm_widget_item_signal_emit(Eo * eo_it EINA_UNUSED,Elm_Naviframe_Item_Data * it,const char * emission,const char * source)902 _elm_naviframe_item_elm_widget_item_signal_emit(Eo *eo_it EINA_UNUSED,
903 Elm_Naviframe_Item_Data *it,
904 const char *emission,
905 const char *source)
906 {
907 elm_object_signal_emit(VIEW(it), emission, source);
908 }
909
910 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_calculate(Eo * obj,Elm_Naviframe_Data * sd)911 _elm_naviframe_efl_canvas_group_group_calculate(Eo *obj, Elm_Naviframe_Data *sd)
912 {
913 Evas_Coord minw = 0, minh = 0;
914 Elm_Naviframe_Item_Data *it, *top;
915 Evas_Coord x, y, w, h;
916
917 if (sd->on_deletion) return;
918 if (!sd->stack) return;
919
920 top = (EINA_INLIST_CONTAINER_GET(sd->stack->last, Elm_Naviframe_Item_Data));
921 evas_object_geometry_get(obj, &x, &y, &w, &h);
922 EINA_INLIST_FOREACH(sd->stack, it)
923 {
924 evas_object_geometry_set(VIEW(it), x, y, w, h);
925
926 if (it == top)
927 {
928 edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
929 &it->minw, &it->minh);
930 minw = it->minw;
931 minh = it->minh;
932 }
933 }
934
935 evas_object_size_hint_min_set(obj, minw, minh);
936 evas_object_size_hint_max_set(obj, -1, -1);
937 }
938
939 static void
_on_item_back_btn_clicked(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)940 _on_item_back_btn_clicked(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
941 {
942 /* Since edje has the event queue, clicked event could be happened
943 multiple times on some heavy environment. This callback del will
944 prevent those scenario and guarantee only one clicked for it's own
945 page. */
946 evas_object_smart_callback_del(obj, "clicked", _on_item_back_btn_clicked);
947 elm_naviframe_item_pop(data);
948 }
949
950 static Evas_Object *
_back_btn_new(Evas_Object * obj,const char * title_label)951 _back_btn_new(Evas_Object *obj, const char *title_label)
952 {
953 Evas_Object *btn, *ed;
954 char buf[1024];
955
956 btn = elm_button_add(obj);
957
958 if (!btn) return NULL;
959 evas_object_smart_callback_add(btn, "clicked", _on_item_back_btn_clicked, obj);
960 snprintf
961 (buf, sizeof(buf), "naviframe/back_btn/%s", elm_widget_style_get(obj));
962 elm_object_style_set(btn, buf);
963 if (title_label)
964 elm_layout_text_set(btn, NULL, title_label);
965 else
966 elm_object_domain_translatable_text_set(btn, PACKAGE, N_("Back"));
967
968 /* HACK NOTE: this explicit check only exists to avoid an ERR()
969 * message from elm_layout_content_set().
970 *
971 * The button was ALWAYS supposed to support an elm.swallow.content, but
972 * default naviframe/back_btn/default theme did not provide such, then
973 * old themes would emit such error message.
974 *
975 * Once we can break the theme API, remove this check and always
976 * set an icon.
977 */
978 ed = elm_layout_edje_get(btn);
979 if (edje_object_part_exists(ed, CONTENT_PART))
980 {
981 Evas_Object *ico = elm_icon_add(btn);
982 elm_icon_standard_set(ico, "go-previous");
983 elm_layout_content_set(btn, CONTENT_PART, ico);
984 }
985
986 return btn;
987 }
988
989 EOLIAN static void
_elm_naviframe_efl_layout_signal_signal_emit(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * emission,const char * source)990 _elm_naviframe_efl_layout_signal_signal_emit(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *emission, const char *source)
991 {
992 Elm_Object_Item *eo_top_it;
993
994 eo_top_it = elm_naviframe_top_item_get(obj);
995 if (!eo_top_it) return;
996 ELM_NAVIFRAME_ITEM_DATA_GET(eo_top_it, top_it);
997
998 efl_layout_signal_emit(VIEW(top_it), emission, source);
999 }
1000
1001 /* content/text smart functions proxying things to the top item, which
1002 * is the resize object of the layout */
1003 static Eina_Bool
_elm_naviframe_text_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part,const char * label)1004 _elm_naviframe_text_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part, const char *label)
1005 {
1006 Elm_Object_Item *it;
1007 const char *text = NULL;
1008
1009 it = elm_naviframe_top_item_get(obj);
1010 if (!it) return EINA_FALSE;
1011
1012 elm_object_item_part_text_set(it, part, label);
1013 text = elm_object_item_part_text_get(it, part);
1014 if ((text) && !strcmp(text, label))
1015 return EINA_TRUE;
1016 return EINA_FALSE;
1017 }
1018
1019 static const char *
_elm_naviframe_text_get(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1020 _elm_naviframe_text_get(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1021 {
1022 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1023 if (!it) return NULL;
1024
1025 return elm_object_item_part_text_get(it, part);
1026 }
1027
1028 /* we have to keep a "manual" set here because of the callbacks on the
1029 * children */
1030 static Eina_Bool
_elm_naviframe_content_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part,Evas_Object * content)1031 _elm_naviframe_content_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part, Evas_Object *content)
1032 {
1033 Elm_Object_Item *it;
1034
1035 it = elm_naviframe_top_item_get(obj);
1036 if (!it) return EINA_FALSE;
1037
1038 elm_object_item_part_content_set(it, part, content);
1039
1040 if (content == elm_object_item_part_content_get(it, part))
1041 return EINA_TRUE;
1042
1043 return EINA_FALSE;
1044 }
1045
1046 static Evas_Object*
_elm_naviframe_content_get(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1047 _elm_naviframe_content_get(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1048 {
1049 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1050
1051 if (!it) return NULL;
1052
1053 return elm_object_item_part_content_get(it, part);
1054 }
1055
1056 static Evas_Object*
_elm_naviframe_content_unset(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * part)1057 _elm_naviframe_content_unset(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *part)
1058 {
1059 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
1060
1061 if (!it) return NULL;
1062
1063 return elm_object_item_part_content_unset(it, part);
1064 }
1065
1066 static void
_on_item_title_clicked(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1067 _on_item_title_clicked(void *data,
1068 Evas_Object *obj EINA_UNUSED,
1069 const char *emission EINA_UNUSED,
1070 const char *source EINA_UNUSED)
1071 {
1072 Elm_Naviframe_Item_Data *it = data;
1073
1074 efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_TITLE_CLICKED, EO_OBJ(it));
1075 }
1076
1077 /* "elm,state,cur,pushed"
1078 */
1079 static void
_on_item_push_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1080 _on_item_push_finished(void *data,
1081 Evas_Object *obj EINA_UNUSED,
1082 const char *emission EINA_UNUSED,
1083 const char *source EINA_UNUSED)
1084 {
1085 Elm_Naviframe_Item_Data *it = data;
1086
1087 if (!it) return;
1088
1089 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1090
1091 /* If pushed item becomes top item, then do not hide pushed item view.
1092 * If top item is deleted in "transition,finished" smart callback by user
1093 * before this function is called, then pushed item becomes top item.
1094 */
1095 if (EO_OBJ(it) == elm_naviframe_top_item_get(WIDGET(it)))
1096 return;
1097
1098 evas_object_hide(VIEW(it));
1099
1100 elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1101
1102 if (sd->freeze_events)
1103 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
1104 }
1105
1106 /* "elm,state,cur,popped"
1107 */
1108 static void
_on_item_pop_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1109 _on_item_pop_finished(void *data,
1110 Evas_Object *obj EINA_UNUSED,
1111 const char *emission EINA_UNUSED,
1112 const char *source EINA_UNUSED)
1113 {
1114 Elm_Naviframe_Item_Data *it = data;
1115 Elm_Object_Item *eo_prev_it = NULL;
1116
1117 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1118
1119 eo_prev_it = elm_naviframe_top_item_get(WIDGET(it));
1120 if (eo_prev_it)
1121 {
1122 ELM_NAVIFRAME_ITEM_DATA_GET(eo_prev_it, prev_it);
1123
1124 evas_object_raise(VIEW(prev_it));
1125 }
1126
1127 if (sd->preserve)
1128 elm_widget_tree_unfocusable_set(VIEW(it), EINA_FALSE);
1129 sd->popping = eina_list_remove(sd->popping, it);
1130
1131 efl_del(EO_OBJ(it));
1132 }
1133
1134 /* "elm,state,new,pushed",
1135 * "elm,state,prev,popped
1136 */
1137 static void
_on_item_show_finished(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)1138 _on_item_show_finished(void *data,
1139 Evas_Object *obj EINA_UNUSED,
1140 const char *emission EINA_UNUSED,
1141 const char *source EINA_UNUSED)
1142 {
1143 Elm_Naviframe_Item_Data *it = data;
1144
1145 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1146
1147 elm_object_signal_emit(VIEW(it), "elm,state,visible", "elm");
1148
1149 elm_widget_tree_unfocusable_set(VIEW(it), EINA_FALSE);
1150 _prev_page_focus_recover(it);
1151
1152 if (sd->freeze_events)
1153 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
1154
1155 it->pushing = EINA_FALSE;
1156
1157 efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_TRANSITION_FINISHED, EO_OBJ(it));
1158
1159 if (EO_OBJ(it) == elm_naviframe_top_item_get(WIDGET(it)))
1160 efl_event_callback_legacy_call(WIDGET(it), ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(it));
1161 }
1162
1163 static void
_on_item_size_hints_changed(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1164 _on_item_size_hints_changed(void *data,
1165 Evas *e EINA_UNUSED,
1166 Evas_Object *obj EINA_UNUSED,
1167 void *event_info EINA_UNUSED)
1168 {
1169 elm_layout_sizing_eval(data);
1170 }
1171
1172 static void
_item_dispmode_set(Elm_Naviframe_Item_Data * it,Evas_Display_Mode dispmode)1173 _item_dispmode_set(Elm_Naviframe_Item_Data *it, Evas_Display_Mode dispmode)
1174 {
1175 if (it->dispmode == dispmode) return;
1176 switch (dispmode)
1177 {
1178 case EVAS_DISPLAY_MODE_COMPRESS:
1179 elm_object_signal_emit(VIEW(it), "elm,state,display,compress", "elm");
1180 break;
1181 default:
1182 elm_object_signal_emit(VIEW(it), "elm,state,display,default", "elm");
1183 break;
1184 }
1185 it->dispmode = dispmode;
1186 }
1187
1188 static char *
_access_prev_btn_info_cb(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED)1189 _access_prev_btn_info_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED)
1190 {
1191 return strdup(E_("Back"));
1192 }
1193
1194 EOLIAN static void
_elm_naviframe_item_efl_object_invalidate(Eo * eo_item,Elm_Naviframe_Item_Data * it)1195 _elm_naviframe_item_efl_object_invalidate(Eo *eo_item, Elm_Naviframe_Item_Data *it)
1196 {
1197 Elm_Naviframe_Item_Data *prev_it = NULL;
1198 Elm_Naviframe_Content_Item_Pair *content_pair;
1199 Eina_Inlist *l;
1200 Eina_Bool top;
1201
1202 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1203 if (it->title_prev_btn)
1204 evas_object_event_callback_del(it->title_prev_btn, EVAS_CALLBACK_DEL, _item_title_prev_btn_del_cb);
1205 if (it->title_next_btn)
1206 evas_object_event_callback_del(it->title_next_btn, EVAS_CALLBACK_DEL, _item_title_next_btn_del_cb);
1207 if (it->title_icon)
1208 evas_object_event_callback_del(it->title_icon, EVAS_CALLBACK_DEL, _item_title_icon_del_cb);
1209 EINA_INLIST_FOREACH_SAFE(it->content_list, l, content_pair)
1210 {
1211 if (content_pair->content)
1212 {
1213 /* content object will be destroyed naturally */
1214 evas_object_event_callback_del(content_pair->content,
1215 EVAS_CALLBACK_DEL,
1216 _title_content_del);
1217 evas_object_del(content_pair->content);
1218 }
1219 eina_stringshare_del(content_pair->part);
1220 free(content_pair);
1221 }
1222 if (it->content)
1223 {
1224 evas_object_event_callback_del(it->content, EVAS_CALLBACK_DEL, _item_content_del_cb);
1225 if ((sd->preserve) && (!sd->on_deletion))
1226 {
1227 /* so that elm does not delete the contents with the item's
1228 * view after the destructor */
1229 elm_object_part_content_unset(VIEW(it), CONTENT_PART);
1230 evas_object_hide(it->content);
1231 }
1232 }
1233 if (evas_object_data_get(VIEW(it), "out_of_list"))
1234 goto end;
1235
1236 top = (eo_item == elm_naviframe_top_item_get(WIDGET(it)));
1237 sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(it));
1238
1239 if (top && !sd->on_deletion) /* must raise another one */
1240 {
1241 if (sd->stack && sd->stack->last)
1242 prev_it = EINA_INLIST_CONTAINER_GET(sd->stack->last,
1243 Elm_Naviframe_Item_Data);
1244 if (!prev_it)
1245 {
1246 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1247 goto end;
1248 }
1249
1250 elm_widget_tree_unfocusable_set(VIEW(prev_it), EINA_FALSE);
1251 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1252
1253 if (sd->freeze_events)
1254 evas_object_freeze_events_set(VIEW(prev_it), EINA_FALSE);
1255 _resize_object_reset(WIDGET(prev_it), prev_it);
1256 evas_object_show(VIEW(prev_it));
1257
1258 _prev_page_focus_recover(prev_it);
1259
1260 elm_object_signal_emit(VIEW(prev_it), "elm,state,visible", "elm");
1261
1262 efl_event_callback_legacy_call(WIDGET(prev_it), ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(prev_it));
1263 }
1264 end:
1265 efl_invalidate(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
1266 }
1267
1268 EOLIAN static Eo *
_elm_naviframe_item_efl_object_constructor(Eo * eo_item,Elm_Naviframe_Item_Data * it)1269 _elm_naviframe_item_efl_object_constructor(Eo *eo_item, Elm_Naviframe_Item_Data *it)
1270 {
1271 eo_item = efl_constructor(efl_super(eo_item, ELM_NAVIFRAME_ITEM_CLASS));
1272 it->base = efl_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
1273
1274 return eo_item;
1275 }
1276
1277 static Elm_Object_Item *
_item_new(Evas_Object * obj,const Elm_Object_Item * eo_prev_it,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1278 _item_new(Evas_Object *obj,
1279 const Elm_Object_Item *eo_prev_it,
1280 const char *title_label,
1281 Evas_Object *prev_btn,
1282 Evas_Object *next_btn,
1283 Evas_Object *content,
1284 const char *item_style)
1285 {
1286 Eo *eo_item;
1287
1288 ELM_NAVIFRAME_DATA_GET(obj, sd);
1289
1290 eo_item = efl_add(ELM_NAVIFRAME_ITEM_CLASS, obj);
1291
1292 if (!eo_item)
1293 {
1294 ERR("Failed to allocate new item! : naviframe=%p", obj);
1295 return NULL;
1296 }
1297
1298 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1299
1300 //item base layout
1301 Eo *elem = elm_layout_add(obj);
1302 VIEW_SET(it, elem);
1303 evas_object_smart_member_add(VIEW(it), obj);
1304
1305 efl_access_object_role_set(elem, EFL_ACCESS_ROLE_PAGE_TAB);
1306 efl_access_object_i18n_name_set(elem, (char*)title_label);
1307
1308 if (!elm_widget_sub_object_add(obj, VIEW(it)))
1309 ERR("could not add %p as sub object of %p", VIEW(it), obj);
1310
1311 evas_object_event_callback_add
1312 (VIEW(it), EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1313 _on_item_size_hints_changed, obj);
1314
1315 elm_object_signal_callback_add
1316 (VIEW(it), "elm,action,show,finished", "*", _on_item_show_finished, it);
1317 elm_object_signal_callback_add
1318 (VIEW(it), "elm,action,pushed,finished", "*", _on_item_push_finished, it);
1319 elm_object_signal_callback_add
1320 (VIEW(it), "elm,action,popped,finished", "*", _on_item_pop_finished, it);
1321 elm_object_signal_callback_add
1322 (VIEW(it), "elm,action,title,transition,finished", "*", _on_item_title_transition_finished, it);
1323 elm_object_signal_callback_add
1324 (VIEW(it), "elm,action,title,clicked", "*", _on_item_title_clicked, it);
1325
1326 _item_style_set(it, item_style);
1327
1328 if (title_label)
1329 elm_wdg_item_part_text_set(eo_item, TITLE_PART, title_label);
1330
1331 //title buttons
1332 if ((!prev_btn) && sd->auto_pushed && eo_prev_it)
1333 {
1334 ELM_NAVIFRAME_ITEM_DATA_GET(eo_prev_it, prev_it);
1335 const char *prev_title = prev_it->title_label;
1336 prev_btn = _back_btn_new(obj, prev_title);
1337 it->auto_pushed_btn = prev_btn;
1338 }
1339
1340 if (prev_btn)
1341 {
1342 elm_wdg_item_part_content_set(eo_item, PREV_BTN_PART, prev_btn);
1343 if (!elm_layout_text_get(prev_btn, NULL))
1344 {
1345 if (!_access_info_has(prev_btn, ELM_ACCESS_INFO))
1346 {
1347 /* set access info */
1348 _elm_access_callback_set
1349 (_elm_access_info_get(prev_btn), ELM_ACCESS_INFO,
1350 _access_prev_btn_info_cb, it);
1351 }
1352 }
1353 }
1354
1355 if (next_btn)
1356 {
1357 elm_wdg_item_part_content_set(eo_item, NEXT_BTN_PART, next_btn);
1358
1359 if (!elm_layout_text_get(next_btn, NULL))
1360 {
1361 if (!_access_info_has(next_btn, ELM_ACCESS_INFO))
1362 {
1363 /* set access info */
1364 _elm_access_text_set
1365 (_elm_access_info_get(next_btn), ELM_ACCESS_INFO, E_("Next"));
1366 }
1367 }
1368 }
1369
1370 _item_content_set(it, content);
1371 _item_dispmode_set(it, sd->dispmode);
1372
1373 it->title_enabled = EINA_TRUE;
1374
1375 return EO_OBJ(it);
1376 }
1377
1378 static void
_on_obj_size_hints_changed(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1379 _on_obj_size_hints_changed(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
1380 Evas_Object *obj, void *event_info EINA_UNUSED)
1381 {
1382 Elm_Naviframe_Item_Data *it;
1383 Evas_Display_Mode dispmode;
1384
1385 ELM_NAVIFRAME_DATA_GET(obj, sd);
1386
1387 dispmode = evas_object_size_hint_display_mode_get(obj);
1388 if (sd->dispmode == dispmode) return;
1389
1390 sd->dispmode = dispmode;
1391
1392 EINA_INLIST_FOREACH(sd->stack, it)
1393 _item_dispmode_set(it, dispmode);
1394 }
1395
1396 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_add(Eo * obj,Elm_Naviframe_Data * priv)1397 _elm_naviframe_efl_canvas_group_group_add(Eo *obj, Elm_Naviframe_Data *priv)
1398 {
1399 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1400
1401 efl_canvas_group_add(efl_super(obj, MY_CLASS));
1402
1403 priv->dummy_edje = wd->resize_obj;
1404 evas_object_smart_member_add(priv->dummy_edje, obj);
1405
1406 priv->auto_pushed = _elm_config->naviframe_prev_btn_auto_pushed;
1407 priv->freeze_events = EINA_TRUE;
1408
1409 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1410 _on_obj_size_hints_changed, obj);
1411 elm_widget_can_focus_set(obj, EINA_FALSE);
1412 }
1413
1414 static void
_send_signal(Elm_Naviframe_Item_Data * it,const char * sig)1415 _send_signal(Elm_Naviframe_Item_Data *it, const char *sig)
1416 {
1417 if (!it) return ;
1418 elm_object_signal_emit(VIEW(it), sig, "elm");
1419 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1420 }
1421
1422 static void
_deferred(void * data,const Efl_Event * event EINA_UNUSED)1423 _deferred(void *data, const Efl_Event *event EINA_UNUSED)
1424 {
1425 Elm_Naviframe_Data *nfd = data;
1426 Elm_Naviframe_Op *nfo;
1427
1428 EINA_LIST_FREE(nfd->ops, nfo)
1429 {
1430 const char *signals_cur[] = {
1431 "elm,state,cur,popped,deferred",
1432 "elm,state,cur,pushed,deferred"
1433 };
1434 const char *signals_prev = "elm,state,prev,popped,deferred";
1435 const char *signals_new = "elm,state,new,pushed,deferred";
1436 Elm_Naviframe_Item_Data *cur;
1437 Elm_Naviframe_Item_Data *other;
1438
1439 cur = nfo->push ? nfo->related : nfo->self;
1440 other = nfo->push ? nfo->self : nfo->related;
1441
1442 _send_signal(cur, signals_cur[nfo->push]);
1443 _send_signal(other, nfo->push ? signals_new : signals_prev);
1444
1445 free(nfo);
1446 }
1447
1448 efl_event_callback_del(nfd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _deferred, nfd);
1449 }
1450
1451 EOLIAN static void
_elm_naviframe_efl_canvas_group_group_del(Eo * obj,Elm_Naviframe_Data * sd)1452 _elm_naviframe_efl_canvas_group_group_del(Eo *obj, Elm_Naviframe_Data *sd)
1453 {
1454 Elm_Naviframe_Item_Data *it;
1455 Elm_Naviframe_Op *nfo;
1456 Eina_Inlist *l = NULL;
1457
1458 sd->on_deletion = EINA_TRUE;
1459 if (sd->stack) l = sd->stack->last;
1460
1461 while (l)
1462 {
1463 it = EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item_Data);
1464 l = l->prev;
1465 efl_del(EO_OBJ(it));
1466 }
1467
1468 // No need to cleanup animator as it is an event on myself
1469 EINA_LIST_FREE(sd->ops, nfo)
1470 free(nfo);
1471 EINA_LIST_FREE(sd->popping, it)
1472 efl_del(EO_OBJ(it));
1473
1474 evas_object_del(sd->dummy_edje);
1475
1476 efl_canvas_group_del(efl_super(obj, MY_CLASS));
1477 }
1478
1479 //Show only the top item view
1480 EOLIAN static void
_elm_naviframe_efl_gfx_entity_visible_set(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,Eina_Bool vis)1481 _elm_naviframe_efl_gfx_entity_visible_set(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, Eina_Bool vis)
1482 {
1483 Elm_Object_Item *eo_top;
1484
1485 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
1486 return;
1487
1488 efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
1489 if (!vis) return;
1490
1491 eo_top = elm_naviframe_top_item_get(obj);
1492 ELM_NAVIFRAME_ITEM_DATA_GET(eo_top, top);
1493
1494 if (top && !top->delete_me)
1495 evas_object_show(VIEW(top));
1496 }
1497
1498 static Eina_Bool
_key_action_top_item_get(Evas_Object * obj,const char * params EINA_UNUSED)1499 _key_action_top_item_get(Evas_Object *obj, const char *params EINA_UNUSED)
1500 {
1501 Elm_Object_Item *eo_item = NULL;
1502 eo_item = elm_obj_naviframe_top_item_get(obj);
1503 if (!eo_item) return EINA_FALSE;
1504
1505 //FIXME: Replace this below code to elm_naviframe_item_pop() at elm 2.0.
1506 ///Leave for compatibility.
1507 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1508 if (it->title_prev_btn)
1509 efl_event_callback_legacy_call(it->title_prev_btn, EFL_INPUT_EVENT_CLICKED, NULL);
1510
1511 return EINA_TRUE;
1512 }
1513
1514 static Eina_Bool
_key_action_item_pop(Evas_Object * obj,const char * params EINA_UNUSED)1515 _key_action_item_pop(Evas_Object *obj, const char *params EINA_UNUSED)
1516 {
1517 Elm_Object_Item *eo_item = NULL;
1518 eo_item = elm_naviframe_top_item_get(obj);
1519 if (!eo_item) return EINA_FALSE;
1520
1521 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1522
1523 if (it->pushing || it->popping) return EINA_FALSE;
1524
1525 elm_naviframe_item_pop(obj);
1526
1527 return EINA_TRUE;
1528 }
1529
1530 EOLIAN static void
_elm_naviframe_efl_ui_widget_on_access_update(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool is_access)1531 _elm_naviframe_efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool is_access)
1532 {
1533 Elm_Naviframe_Item_Data *it;
1534
1535 EINA_INLIST_FOREACH(sd->stack, it)
1536 _access_obj_process(it, is_access);
1537 }
1538
1539 static void
_schedule_deferred(Elm_Naviframe_Op * nfo,Elm_Naviframe_Data * sd)1540 _schedule_deferred(Elm_Naviframe_Op *nfo, Elm_Naviframe_Data *sd)
1541 {
1542 if (!sd->ops)
1543 efl_event_callback_add(sd->obj, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _deferred, sd);
1544
1545 sd->ops = eina_list_append(sd->ops, nfo);
1546 }
1547
1548 static void
_item_push_helper(Elm_Naviframe_Item_Data * item)1549 _item_push_helper(Elm_Naviframe_Item_Data *item)
1550 {
1551 Elm_Object_Item *eo_top_item;
1552 Evas_Object *obj = WIDGET(item);
1553 ELM_NAVIFRAME_DATA_GET(obj, sd);
1554 eo_top_item = elm_naviframe_top_item_get(obj);
1555 evas_object_show(VIEW(item));
1556
1557 ELM_NAVIFRAME_ITEM_DATA_GET(eo_top_item, top_item);
1558 _resize_object_reset(obj, item);
1559 if (top_item)
1560 {
1561 Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1562
1563 elm_widget_tree_unfocusable_set(VIEW(item), EINA_TRUE);
1564 elm_widget_tree_unfocusable_set(VIEW(top_item), EINA_TRUE);
1565
1566 if (sd->freeze_events)
1567 {
1568 evas_object_freeze_events_set(VIEW(item), EINA_TRUE);
1569 evas_object_freeze_events_set(VIEW(top_item), EINA_TRUE);
1570 }
1571 elm_object_signal_emit(VIEW(top_item), "elm,state,cur,pushed", "elm");
1572 elm_object_signal_emit(VIEW(item), "elm,state,new,pushed", "elm");
1573 edje_object_message_signal_process(elm_layout_edje_get(VIEW(top_item)));
1574 edje_object_message_signal_process(elm_layout_edje_get(VIEW(item)));
1575
1576 nfo->self = item;
1577 nfo->related = top_item;
1578 nfo->push = EINA_TRUE;
1579
1580 _schedule_deferred(nfo, sd);
1581
1582 if (top_item) top_item->pushing = EINA_FALSE;
1583 item->pushing = EINA_TRUE;
1584 }
1585 else
1586 {
1587 if (elm_object_focus_allow_get(VIEW(item)))
1588 elm_object_focus_set(VIEW(item), EINA_TRUE);
1589 else
1590 elm_object_focus_set(WIDGET(item), EINA_TRUE);
1591 }
1592
1593 sd->stack = eina_inlist_append(sd->stack, EINA_INLIST_GET(item));
1594
1595 if (!top_item)
1596 elm_object_signal_emit(VIEW(item), "elm,state,visible", "elm");
1597
1598 elm_layout_sizing_eval(obj);
1599
1600 if (!top_item)
1601 efl_event_callback_legacy_call(obj, ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, EO_OBJ(item));
1602 }
1603
1604 EAPI Evas_Object *
elm_naviframe_add(Evas_Object * parent)1605 elm_naviframe_add(Evas_Object *parent)
1606 {
1607 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1608 return elm_legacy_add(MY_CLASS, parent);
1609 }
1610
1611 EOLIAN static Eo *
_elm_naviframe_efl_object_constructor(Eo * obj,Elm_Naviframe_Data * sd)1612 _elm_naviframe_efl_object_constructor(Eo *obj, Elm_Naviframe_Data *sd)
1613 {
1614 obj = efl_constructor(efl_super(obj, MY_CLASS));
1615 sd->obj = obj;
1616 legacy_child_focus_handle(obj);
1617 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
1618 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
1619 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PAGE_TAB_LIST);
1620
1621 return obj;
1622 }
1623
1624 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_push(Eo * obj,Elm_Naviframe_Data * sd EINA_UNUSED,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1625 _elm_naviframe_item_push(Eo *obj, Elm_Naviframe_Data *sd EINA_UNUSED, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1626 {
1627 Elm_Object_Item *top_item, *eo_item;
1628
1629 top_item = elm_naviframe_top_item_get(obj);
1630 eo_item = _item_new(obj, top_item,
1631 title_label, prev_btn, next_btn, content, item_style);
1632 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, item);
1633 if (!item) return NULL;
1634 _item_push_helper(item);
1635 return eo_item;
1636 }
1637
1638 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_insert_before(Eo * obj,Elm_Naviframe_Data * sd,Elm_Object_Item * eo_before,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1639 _elm_naviframe_item_insert_before(Eo *obj, Elm_Naviframe_Data *sd, Elm_Object_Item *eo_before, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1640 {
1641 Elm_Object_Item *eo_it;
1642 Elm_Naviframe_Item_Data *prev_it = NULL;
1643
1644 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_before, NULL);
1645 ELM_NAVIFRAME_ITEM_DATA_GET(eo_before, before);
1646
1647 ELM_NAVIFRAME_ITEM_CHECK_OR_RETURN(before, NULL);
1648
1649 eo_it = eo_before;
1650 ELM_NAVIFRAME_ITEM_DATA_GET(eo_it, it);
1651 if (EINA_INLIST_GET(it)->prev)
1652 prev_it = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(it)->prev,
1653 Elm_Naviframe_Item_Data);
1654 eo_it = _item_new(obj, EO_OBJ(prev_it),
1655 title_label, prev_btn, next_btn, content, item_style);
1656 if (!eo_it) return NULL;
1657
1658 it = efl_data_scope_get(eo_it, ELM_NAVIFRAME_ITEM_CLASS);
1659
1660 sd->stack = eina_inlist_prepend_relative
1661 (sd->stack, EINA_INLIST_GET(it),
1662 EINA_INLIST_GET(before));
1663
1664 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1665 evas_object_hide(VIEW(it));
1666 elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1667
1668 elm_layout_sizing_eval(obj);
1669
1670 return eo_it;
1671 }
1672
1673 EOLIAN static Elm_Object_Item*
_elm_naviframe_item_insert_after(Eo * obj,Elm_Naviframe_Data * sd,Elm_Object_Item * eo_after,const char * title_label,Evas_Object * prev_btn,Evas_Object * next_btn,Evas_Object * content,const char * item_style)1674 _elm_naviframe_item_insert_after(Eo *obj, Elm_Naviframe_Data *sd, Elm_Object_Item *eo_after, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style)
1675 {
1676 Elm_Object_Item *eo_item;
1677 Eina_Bool top_inserted = EINA_FALSE;
1678
1679 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_after, NULL);
1680 ELM_NAVIFRAME_ITEM_DATA_GET(eo_after, after);
1681
1682 ELM_NAVIFRAME_ITEM_CHECK_OR_RETURN(after, NULL);
1683
1684 eo_item = _item_new(obj, eo_after,
1685 title_label, prev_btn, next_btn, content, item_style);
1686 if (!eo_item) return NULL;
1687
1688 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1689
1690 if (elm_naviframe_top_item_get(obj) == eo_after) top_inserted = EINA_TRUE;
1691
1692 sd->stack = eina_inlist_append_relative
1693 (sd->stack, EINA_INLIST_GET(it),
1694 EINA_INLIST_GET(after));
1695
1696
1697 if (top_inserted)
1698 {
1699 elm_widget_tree_unfocusable_set(VIEW(after), EINA_TRUE);
1700 _resize_object_reset(obj, it);
1701 evas_object_show(VIEW(it));
1702 evas_object_hide(VIEW(after));
1703 if (elm_object_focus_allow_get(VIEW(it)))
1704 elm_object_focus_set(VIEW(it), EINA_TRUE);
1705 else
1706 elm_object_focus_set(WIDGET(it), EINA_TRUE);
1707 elm_object_signal_emit(VIEW(it), "elm,state,visible", "elm");
1708 elm_object_signal_emit(VIEW(after), "elm,state,invisible", "elm");
1709 }
1710 else
1711 elm_object_signal_emit(VIEW(it), "elm,state,invisible", "elm");
1712
1713 elm_layout_sizing_eval(obj);
1714
1715 if (top_inserted)
1716 efl_event_callback_legacy_call(obj, ELM_NAVIFRAME_EVENT_ITEM_ACTIVATED, eo_item);
1717
1718 return eo_item;
1719 }
1720
1721 EOLIAN static Evas_Object*
_elm_naviframe_item_pop(Eo * obj,Elm_Naviframe_Data * sd)1722 _elm_naviframe_item_pop(Eo *obj, Elm_Naviframe_Data *sd)
1723 {
1724 Elm_Object_Item *eo_item;
1725 Elm_Naviframe_Item_Data *prev_it = NULL;
1726 Evas_Object *content = NULL;
1727
1728 eo_item = elm_naviframe_top_item_get(obj);
1729 if (!eo_item) return NULL;
1730
1731 ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
1732
1733 if (it->pushing || it->popping) return NULL;
1734 it->popping = EINA_TRUE;
1735
1736 evas_object_ref(obj);
1737 if (it->pop_cb)
1738 {
1739 efl_ref(eo_item);
1740 if (!it->pop_cb(it->pop_data, eo_item))
1741 {
1742 efl_unref(eo_item);
1743 if (!it->delete_me)
1744 {
1745 /* To avoid multiple item pops, the auto pushed button deletes
1746 its clicked callback once it is called.
1747 Since the item is not popped or deleted here, the deleted
1748 callback of the auto pushed button should be restored. */
1749 if (it->auto_pushed_btn)
1750 evas_object_smart_callback_add(it->auto_pushed_btn, "clicked", _on_item_back_btn_clicked, obj);
1751 it->popping = EINA_FALSE;
1752 }
1753 evas_object_unref(obj);
1754 return NULL;
1755 }
1756 efl_unref(eo_item);
1757 }
1758 evas_object_unref(obj);
1759
1760 if (sd->preserve)
1761 content = it->content;
1762
1763 evas_object_data_set(VIEW(it), "out_of_list", (void *)1);
1764
1765 if (sd->stack->last->prev)
1766 prev_it = EINA_INLIST_CONTAINER_GET
1767 (sd->stack->last->prev, Elm_Naviframe_Item_Data);
1768
1769 sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(it));
1770
1771 if (prev_it)
1772 {
1773 Elm_Naviframe_Op *nfo = calloc(1, sizeof (Elm_Naviframe_Op));
1774
1775 elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
1776
1777 if (sd->freeze_events)
1778 {
1779 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1780 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1781 }
1782
1783 elm_widget_resize_object_set(obj, VIEW(prev_it));
1784
1785 /* these 2 signals MUST take place simultaneously */
1786 elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1787 elm_object_signal_emit(VIEW(prev_it), "elm,state,prev,popped", "elm");
1788 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1789 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1790
1791 //Show hidden previous view when pop transition begins.
1792 evas_object_show(VIEW(prev_it));
1793
1794 if (!nfo) goto on_error;
1795
1796 nfo->self = it;
1797 nfo->related = prev_it;
1798 nfo->push = EINA_FALSE;
1799
1800 sd->popping = eina_list_append(sd->popping, it);
1801
1802 _schedule_deferred(nfo, sd);
1803 }
1804 else
1805 efl_del(eo_item);
1806
1807 on_error:
1808 return content;
1809 }
1810
1811 EOLIAN static void
_elm_naviframe_item_pop_to(Eo * eo_it,Elm_Naviframe_Item_Data * it)1812 _elm_naviframe_item_pop_to(Eo *eo_it, Elm_Naviframe_Item_Data *it)
1813 {
1814 Eina_Inlist *l;
1815
1816 ELM_NAVIFRAME_DATA_GET(WIDGET(it), sd);
1817
1818 if (eo_it == elm_naviframe_top_item_get(WIDGET(it))) return;
1819
1820 l = sd->stack->last->prev;
1821
1822 sd->on_deletion = EINA_TRUE;
1823
1824 while (l)
1825 {
1826 Elm_Naviframe_Item_Data *iit = EINA_INLIST_CONTAINER_GET
1827 (l, Elm_Naviframe_Item_Data);
1828
1829 if (iit == it) break;
1830
1831 l = l->prev;
1832
1833 efl_del(EO_OBJ(iit));
1834 }
1835
1836 sd->on_deletion = EINA_FALSE;
1837
1838 elm_naviframe_item_pop(WIDGET(it));
1839 }
1840
1841 EOLIAN static void
_elm_naviframe_item_promote(Eo * eo_it,Elm_Naviframe_Item_Data * it)1842 _elm_naviframe_item_promote(Eo *eo_it, Elm_Naviframe_Item_Data *it)
1843 {
1844 Elm_Object_Item *eo_prev_top;
1845 Elm_Naviframe_Item_Data *nit = it;
1846
1847 ELM_NAVIFRAME_DATA_GET(WIDGET(nit), sd);
1848
1849 eo_prev_top = elm_naviframe_top_item_get(WIDGET(nit));
1850 if (eo_it == eo_prev_top) return;
1851
1852 sd->stack = eina_inlist_remove(sd->stack, EINA_INLIST_GET(nit));
1853 _item_push_helper(nit);
1854 }
1855
1856 EOLIAN static void
_elm_naviframe_item_simple_promote(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Evas_Object * content)1857 _elm_naviframe_item_simple_promote(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Evas_Object *content)
1858 {
1859 Elm_Naviframe_Item_Data *itr;
1860
1861 EINA_INLIST_FOREACH(sd->stack, itr)
1862 {
1863 if (elm_object_item_content_get(EO_OBJ(itr)) == content)
1864 {
1865 elm_naviframe_item_promote(EO_OBJ(itr));
1866 break;
1867 }
1868 }
1869 }
1870
1871 EOLIAN static void
_elm_naviframe_content_preserve_on_pop_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool preserve)1872 _elm_naviframe_content_preserve_on_pop_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool preserve)
1873 {
1874 sd->preserve = !!preserve;
1875 }
1876
1877 EOLIAN static Eina_Bool
_elm_naviframe_content_preserve_on_pop_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1878 _elm_naviframe_content_preserve_on_pop_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1879 {
1880 return sd->preserve;
1881 }
1882
1883 EOLIAN static Elm_Object_Item*
_elm_naviframe_top_item_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1884 _elm_naviframe_top_item_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1885 {
1886 if (!sd->stack) return NULL;
1887 Elm_Naviframe_Item_Data *ret_it = EINA_INLIST_CONTAINER_GET
1888 (sd->stack->last, Elm_Naviframe_Item_Data);
1889 return EO_OBJ(ret_it);
1890 }
1891
1892 EOLIAN static Elm_Object_Item*
_elm_naviframe_bottom_item_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1893 _elm_naviframe_bottom_item_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1894 {
1895 if (!sd->stack) return NULL;
1896 Elm_Naviframe_Item_Data *ret_it = EINA_INLIST_CONTAINER_GET
1897 (sd->stack, Elm_Naviframe_Item_Data);
1898 return EO_OBJ(ret_it);
1899 }
1900
1901 EOLIAN static void
_elm_naviframe_item_elm_widget_item_style_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,const char * item_style)1902 _elm_naviframe_item_elm_widget_item_style_set(Eo *eo_item EINA_UNUSED,
1903 Elm_Naviframe_Item_Data *nit,
1904 const char *item_style)
1905 {
1906 if (item_style && eina_streq(item_style, elm_wdg_item_style_get(EO_OBJ(nit)))) return;
1907
1908 if (!item_style)
1909 if (eina_streq("basic", elm_wdg_item_style_get(EO_OBJ(nit)))) return;
1910
1911 _item_style_set(nit, item_style);
1912 _item_signals_emit(nit);
1913 _item_title_enabled_update(nit, EINA_FALSE);
1914 }
1915
1916 EAPI void
elm_naviframe_item_style_set(Elm_Object_Item * obj,const char * style)1917 elm_naviframe_item_style_set(Elm_Object_Item *obj, const char *style)
1918 {
1919 elm_wdg_item_style_set(obj, style);
1920 }
1921
1922 EAPI const char *
elm_naviframe_item_style_get(const Elm_Object_Item * obj)1923 elm_naviframe_item_style_get(const Elm_Object_Item *obj)
1924 {
1925 return elm_wdg_item_style_get(obj);
1926 }
1927
1928 EINA_DEPRECATED EAPI void
elm_naviframe_item_title_visible_set(Elm_Object_Item * it,Eina_Bool visible)1929 elm_naviframe_item_title_visible_set(Elm_Object_Item *it,
1930 Eina_Bool visible)
1931 {
1932 elm_naviframe_item_title_enabled_set(it, visible, EINA_FALSE);
1933 }
1934
1935 EINA_DEPRECATED EAPI Eina_Bool
elm_naviframe_item_title_visible_get(const Elm_Object_Item * it)1936 elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1937 {
1938 return elm_naviframe_item_title_enabled_get(it);
1939 }
1940
1941 EOLIAN static void
_elm_naviframe_item_title_enabled_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,Eina_Bool enabled,Eina_Bool transition)1942 _elm_naviframe_item_title_enabled_set(Eo *eo_item EINA_UNUSED,
1943 Elm_Naviframe_Item_Data *nit,
1944 Eina_Bool enabled,
1945 Eina_Bool transition)
1946 {
1947 enabled = !!enabled;
1948 if (nit->title_enabled == enabled) return;
1949
1950 nit->title_enabled = enabled;
1951
1952 transition = !!transition;
1953 _item_title_enabled_update(nit, transition);
1954 }
1955
1956 EOLIAN static Eina_Bool
_elm_naviframe_item_title_enabled_get(const Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit)1957 _elm_naviframe_item_title_enabled_get(const Eo *eo_item EINA_UNUSED, Elm_Naviframe_Item_Data *nit)
1958 {
1959 return nit->title_enabled;
1960 }
1961
1962 EOLIAN static void
_elm_naviframe_item_pop_cb_set(Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit,Elm_Naviframe_Item_Pop_Cb func,void * data)1963 _elm_naviframe_item_pop_cb_set(Eo *eo_item EINA_UNUSED,
1964 Elm_Naviframe_Item_Data *nit,
1965 Elm_Naviframe_Item_Pop_Cb func,
1966 void *data)
1967 {
1968 nit->pop_cb = func;
1969 nit->pop_data = data;
1970 }
1971
1972 EOLIAN static Eina_List*
_elm_naviframe_item_efl_access_object_access_children_get(const Eo * eo_item EINA_UNUSED,Elm_Naviframe_Item_Data * nit)1973 _elm_naviframe_item_efl_access_object_access_children_get(const Eo *eo_item EINA_UNUSED, Elm_Naviframe_Item_Data *nit)
1974 {
1975 Eina_List *ret = NULL;
1976
1977 ret = eina_list_append(ret, VIEW(nit));
1978 return ret;
1979 }
1980
1981 EOLIAN static void
_elm_naviframe_prev_btn_auto_pushed_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool auto_pushed)1982 _elm_naviframe_prev_btn_auto_pushed_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool auto_pushed)
1983 {
1984 sd->auto_pushed = !!auto_pushed;
1985 }
1986
1987 EOLIAN static Eina_Bool
_elm_naviframe_prev_btn_auto_pushed_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1988 _elm_naviframe_prev_btn_auto_pushed_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1989 {
1990 return sd->auto_pushed;
1991 }
1992
1993 EOLIAN static Eina_List*
_elm_naviframe_items_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)1994 _elm_naviframe_items_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
1995 {
1996 Eina_List *ret = NULL;
1997 Elm_Naviframe_Item_Data *itr;
1998
1999 EINA_INLIST_FOREACH(sd->stack, itr)
2000 ret = eina_list_append(ret, EO_OBJ(itr));
2001
2002 return ret;
2003 }
2004
2005 EOLIAN static void
_elm_naviframe_event_enabled_set(Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd,Eina_Bool enabled)2006 _elm_naviframe_event_enabled_set(Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd, Eina_Bool enabled)
2007 {
2008 enabled = !!enabled;
2009 if (sd->freeze_events == !enabled) return;
2010 sd->freeze_events = !enabled;
2011 }
2012
2013 EOLIAN static Eina_Bool
_elm_naviframe_event_enabled_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * sd)2014 _elm_naviframe_event_enabled_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *sd)
2015 {
2016 return !sd->freeze_events;
2017 }
2018
2019 static void
_elm_naviframe_class_constructor(Efl_Class * klass)2020 _elm_naviframe_class_constructor(Efl_Class *klass)
2021 {
2022 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
2023 }
2024
2025 EOLIAN const Efl_Access_Action_Data *
_elm_naviframe_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Naviframe_Data * pd EINA_UNUSED)2026 _elm_naviframe_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Naviframe_Data *pd EINA_UNUSED)
2027 {
2028 static Efl_Access_Action_Data atspi_actions[] = {
2029 { "top_item_get", "top_item_get", NULL, _key_action_top_item_get },
2030 { "item_pop", "item_pop", NULL, _key_action_item_pop },
2031 { NULL, NULL, NULL, NULL }
2032 };
2033 return &atspi_actions[0];
2034 }
2035
2036 /* Standard widget overrides */
2037
2038 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_naviframe, Elm_Naviframe_Data)
2039
2040 /* Efl.Part begin */
2041
2042 ELM_PART_OVERRIDE(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2043 ELM_PART_OVERRIDE_CONTENT_SET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2044 ELM_PART_OVERRIDE_CONTENT_GET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2045 ELM_PART_OVERRIDE_CONTENT_UNSET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2046 ELM_PART_OVERRIDE_TEXT_SET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2047 ELM_PART_OVERRIDE_TEXT_GET(elm_naviframe, ELM_NAVIFRAME, Elm_Naviframe_Data)
2048 #include "elm_naviframe_part.eo.c"
2049
2050 /* Efl.Part end */
2051
2052 /* Internal EO APIs and hidden overrides */
2053
2054 #define ELM_NAVIFRAME_EXTRA_OPS \
2055 EFL_CANVAS_GROUP_CALC_OPS(elm_naviframe), \
2056 EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_naviframe)
2057
2058 #include "elm_naviframe_item_eo.c"
2059 #include "elm_naviframe_eo.c"
2060