diff options
Diffstat (limited to 'libraries/elementary/src/lib/elc_naviframe.c')
-rw-r--r-- | libraries/elementary/src/lib/elc_naviframe.c | 1530 |
1 files changed, 1530 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elc_naviframe.c b/libraries/elementary/src/lib/elc_naviframe.c new file mode 100644 index 0000000..49e838e --- /dev/null +++ b/libraries/elementary/src/lib/elc_naviframe.c | |||
@@ -0,0 +1,1530 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | |||
4 | typedef struct _Widget_Data Widget_Data; | ||
5 | typedef struct _Elm_Naviframe_Item Elm_Naviframe_Item; | ||
6 | typedef struct _Elm_Naviframe_Content_Item_Pair Elm_Naviframe_Content_Item_Pair; | ||
7 | typedef struct _Elm_Naviframe_Text_Item_Pair Elm_Naviframe_Text_Item_Pair; | ||
8 | |||
9 | struct _Widget_Data | ||
10 | { | ||
11 | Eina_Inlist *stack; | ||
12 | Evas_Object *base; | ||
13 | Eina_Bool preserve: 1; | ||
14 | Eina_Bool auto_pushed: 1; | ||
15 | Eina_Bool freeze_events: 1; | ||
16 | }; | ||
17 | |||
18 | struct _Elm_Naviframe_Content_Item_Pair | ||
19 | { | ||
20 | EINA_INLIST; | ||
21 | const char *part; | ||
22 | Elm_Naviframe_Item *it; | ||
23 | }; | ||
24 | |||
25 | struct _Elm_Naviframe_Text_Item_Pair | ||
26 | { | ||
27 | EINA_INLIST; | ||
28 | const char *part; | ||
29 | }; | ||
30 | |||
31 | struct _Elm_Naviframe_Item | ||
32 | { | ||
33 | ELM_WIDGET_ITEM; | ||
34 | EINA_INLIST; | ||
35 | Eina_Inlist *content_list; | ||
36 | Eina_Inlist *text_list; | ||
37 | Evas_Object *content; | ||
38 | Evas_Object *title_prev_btn; | ||
39 | Evas_Object *title_next_btn; | ||
40 | Evas_Object *title_icon; | ||
41 | const char *style; | ||
42 | Evas_Coord minw; | ||
43 | Evas_Coord minh; | ||
44 | Eina_Bool back_btn: 1; | ||
45 | Eina_Bool title_visible: 1; | ||
46 | Eina_Bool content_unfocusable : 1; | ||
47 | }; | ||
48 | |||
49 | static const char *widtype = NULL; | ||
50 | |||
51 | //widget signals | ||
52 | static const char SIG_TRANSITION_FINISHED[] = "transition,finished"; | ||
53 | static const char SIG_TITLE_CLICKED[] = "title,clicked"; | ||
54 | |||
55 | static const Evas_Smart_Cb_Description _signals[] = { | ||
56 | {SIG_TRANSITION_FINISHED, ""}, | ||
57 | {SIG_TITLE_CLICKED, ""}, | ||
58 | {NULL, NULL} | ||
59 | }; | ||
60 | |||
61 | static void _text_set_hook(Evas_Object *obj, | ||
62 | const char *part, | ||
63 | const char *label); | ||
64 | static const char *_text_get_hook(const Evas_Object *obj, const char *part); | ||
65 | static void _content_set_hook(Evas_Object *obj, | ||
66 | const char *part, | ||
67 | Evas_Object *content); | ||
68 | static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part); | ||
69 | static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part); | ||
70 | static void _del_hook(Evas_Object *obj); | ||
71 | static void _theme_hook(Evas_Object *obj); | ||
72 | static void _emit_hook(Evas_Object *obj, | ||
73 | const char *emission, | ||
74 | const char *source); | ||
75 | static void _disable_hook(Evas_Object *obj); | ||
76 | static void _item_text_set_hook(Elm_Object_Item *it, | ||
77 | const char *part, | ||
78 | const char *label); | ||
79 | static const char *_item_text_get_hook(const Elm_Object_Item *it, | ||
80 | const char *part); | ||
81 | static void _item_content_set_hook(Elm_Object_Item *it, | ||
82 | const char *part, | ||
83 | Evas_Object *content); | ||
84 | static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it, | ||
85 | const char *part); | ||
86 | static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it, | ||
87 | const char *part); | ||
88 | static void _item_signal_emit_hook(Elm_Object_Item *it, | ||
89 | const char *emission, | ||
90 | const char *source); | ||
91 | static void _item_title_visible_update(Elm_Naviframe_Item *navi_it); | ||
92 | static void _sizing_eval(Evas_Object *obj); | ||
93 | static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info); | ||
94 | static void _resize(void *data, | ||
95 | Evas *e, | ||
96 | Evas_Object *obj, | ||
97 | void *event_info); | ||
98 | static void _title_clicked(void *data, Evas_Object *obj, | ||
99 | const char *emission, | ||
100 | const char *source); | ||
101 | static void _back_btn_clicked(void *data, | ||
102 | Evas_Object *obj, | ||
103 | void *event_info); | ||
104 | static Evas_Object *_back_btn_new(Evas_Object *obj); | ||
105 | static void _item_content_del(void *data, | ||
106 | Evas *e, | ||
107 | Evas_Object *obj, | ||
108 | void *event_info); | ||
109 | static void _title_content_del(void *data, | ||
110 | Evas *e, | ||
111 | Evas_Object *obj, | ||
112 | void *event_info); | ||
113 | static void _title_prev_btn_del(void *data, | ||
114 | Evas *e, | ||
115 | Evas_Object *obj, | ||
116 | void *event_info); | ||
117 | static void _title_next_btn_del(void *data, | ||
118 | Evas *e, | ||
119 | Evas_Object *obj, | ||
120 | void *event_info); | ||
121 | static void _title_icon_del(void *data, | ||
122 | Evas *e, | ||
123 | Evas_Object *obj, | ||
124 | void *event_info); | ||
125 | static void _title_content_set(Elm_Naviframe_Item *it, | ||
126 | const char *part, | ||
127 | Evas_Object *content); | ||
128 | static void _title_prev_btn_set(Elm_Naviframe_Item *it, | ||
129 | Evas_Object *btn, | ||
130 | Eina_Bool back_btn); | ||
131 | static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn); | ||
132 | static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon); | ||
133 | static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it); | ||
134 | static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it); | ||
135 | static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it); | ||
136 | static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it); | ||
137 | static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it, | ||
138 | const char *part); | ||
139 | static void _item_del(Elm_Naviframe_Item *it); | ||
140 | static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it); | ||
141 | static void _pushed_finished(void *data, | ||
142 | Evas_Object *obj, | ||
143 | const char *emission, | ||
144 | const char *source); | ||
145 | static void _popped_finished(void *data, | ||
146 | Evas_Object *obj, | ||
147 | const char *emission, | ||
148 | const char *source); | ||
149 | static void _show_finished(void *data, | ||
150 | Evas_Object *obj, | ||
151 | const char *emission, | ||
152 | const char *source); | ||
153 | static void _changed_size_hints(void *data, | ||
154 | Evas *e, | ||
155 | Evas_Object *obj, | ||
156 | void *event_info); | ||
157 | static void _item_content_set(Elm_Naviframe_Item *navi_it, | ||
158 | Evas_Object *content); | ||
159 | static void _item_style_set(Elm_Naviframe_Item *navi_it, | ||
160 | const char *item_style); | ||
161 | static Elm_Naviframe_Item * _item_new(Evas_Object *obj, | ||
162 | const char *title_label, | ||
163 | Evas_Object *prev_btn, | ||
164 | Evas_Object *next_btn, | ||
165 | Evas_Object *content, | ||
166 | const char *item_style); | ||
167 | static Eina_Bool _focus_next_hook(const Evas_Object *obj, | ||
168 | Elm_Focus_Direction dir, | ||
169 | Evas_Object **next); | ||
170 | |||
171 | static void | ||
172 | _del_hook(Evas_Object *obj) | ||
173 | { | ||
174 | Widget_Data *wd; | ||
175 | Elm_Naviframe_Item *it; | ||
176 | |||
177 | wd = elm_widget_data_get(obj); | ||
178 | if (!wd) return; | ||
179 | |||
180 | if (wd->stack) | ||
181 | { | ||
182 | while (wd->stack->last) | ||
183 | { | ||
184 | it = EINA_INLIST_CONTAINER_GET(wd->stack->last, | ||
185 | Elm_Naviframe_Item); | ||
186 | wd->stack = eina_inlist_remove(wd->stack, wd->stack->last); | ||
187 | _item_del(it); | ||
188 | elm_widget_item_free(it); | ||
189 | if (!wd->stack) break; | ||
190 | } | ||
191 | } | ||
192 | free(wd); | ||
193 | } | ||
194 | |||
195 | static void | ||
196 | _theme_hook(Evas_Object *obj) | ||
197 | { | ||
198 | Widget_Data *wd; | ||
199 | Elm_Naviframe_Item *it; | ||
200 | |||
201 | wd = elm_widget_data_get(obj); | ||
202 | if (!wd) return; | ||
203 | |||
204 | _elm_theme_object_set(obj, | ||
205 | wd->base, | ||
206 | "naviframe", | ||
207 | "base", | ||
208 | elm_widget_style_get(obj)); | ||
209 | |||
210 | EINA_INLIST_FOREACH(wd->stack, it) | ||
211 | { | ||
212 | _item_style_set(it, it->style); | ||
213 | _item_title_visible_update(it); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | static void _emit_hook(Evas_Object *obj, | ||
218 | const char *emission, | ||
219 | const char *source) | ||
220 | { | ||
221 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
222 | if (!it) return; | ||
223 | return elm_object_item_signal_emit(it, emission, source); | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | _disable_hook(Evas_Object *obj __UNUSED__) | ||
228 | { | ||
229 | //FIXME: | ||
230 | } | ||
231 | |||
232 | static void | ||
233 | _item_text_set_hook(Elm_Object_Item *it, | ||
234 | const char *part, | ||
235 | const char *label) | ||
236 | { | ||
237 | Elm_Naviframe_Text_Item_Pair *pair = NULL; | ||
238 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
239 | char buf[1024]; | ||
240 | |||
241 | if (!part || !strcmp(part, "default")) | ||
242 | snprintf(buf, sizeof(buf), "elm.text.title"); | ||
243 | else if (!strcmp("subtitle", part)) | ||
244 | snprintf(buf, sizeof(buf), "elm.text.subtitle"); | ||
245 | else | ||
246 | snprintf(buf, sizeof(buf), "%s", part); | ||
247 | |||
248 | EINA_INLIST_FOREACH(navi_it->text_list, pair) | ||
249 | if (!strcmp(buf, pair->part)) break; | ||
250 | |||
251 | if (!pair) | ||
252 | { | ||
253 | pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair); | ||
254 | if (!pair) | ||
255 | { | ||
256 | ERR("Failed to allocate new text part of the item! : naviframe=%p", | ||
257 | WIDGET(navi_it)); | ||
258 | return; | ||
259 | } | ||
260 | eina_stringshare_replace(&pair->part, buf); | ||
261 | navi_it->text_list = eina_inlist_append(navi_it->text_list, | ||
262 | EINA_INLIST_GET(pair)); | ||
263 | } | ||
264 | elm_object_part_text_set(VIEW(navi_it), buf, label); | ||
265 | |||
266 | if (label) | ||
267 | { | ||
268 | snprintf(buf, sizeof(buf), "elm,state,%s,show", buf); | ||
269 | elm_object_signal_emit(VIEW(navi_it), buf, "elm"); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf); | ||
274 | elm_object_signal_emit(VIEW(navi_it), buf, "elm"); | ||
275 | } | ||
276 | |||
277 | _sizing_eval(WIDGET(navi_it)); | ||
278 | } | ||
279 | |||
280 | static const char * | ||
281 | _item_text_get_hook(const Elm_Object_Item *it, const char *part) | ||
282 | { | ||
283 | char buf[1024]; | ||
284 | |||
285 | if (!part || !strcmp(part, "default")) | ||
286 | snprintf(buf, sizeof(buf), "elm.text.title"); | ||
287 | else if (!strcmp("subtitle", part)) | ||
288 | snprintf(buf, sizeof(buf), "elm.text.subtitle"); | ||
289 | else | ||
290 | snprintf(buf, sizeof(buf), "%s", part); | ||
291 | |||
292 | return elm_object_part_text_get(VIEW(it), buf); | ||
293 | } | ||
294 | |||
295 | static void | ||
296 | _item_content_set_hook(Elm_Object_Item *it, | ||
297 | const char *part, | ||
298 | Evas_Object *content) | ||
299 | { | ||
300 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
301 | |||
302 | //specified parts | ||
303 | if (!part || !strcmp("default", part)) | ||
304 | { | ||
305 | _item_content_set(navi_it, content); | ||
306 | return; | ||
307 | } | ||
308 | else if (!strcmp(part, "prev_btn")) | ||
309 | { | ||
310 | _title_prev_btn_set(navi_it, content, EINA_FALSE); | ||
311 | return; | ||
312 | } | ||
313 | else if (!strcmp(part, "next_btn")) | ||
314 | { | ||
315 | _title_next_btn_set(navi_it, content); | ||
316 | return; | ||
317 | } | ||
318 | else if (!strcmp(part, "icon")) | ||
319 | { | ||
320 | _title_icon_set(navi_it, content); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | //common part | ||
325 | _title_content_set(navi_it, part, content); | ||
326 | } | ||
327 | |||
328 | static Evas_Object * | ||
329 | _item_content_get_hook(const Elm_Object_Item *it, const char *part) | ||
330 | { | ||
331 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
332 | |||
333 | //specified parts | ||
334 | if (!part || !strcmp("default", part)) | ||
335 | return navi_it->content; | ||
336 | else if (!strcmp(part, "prev_btn")) | ||
337 | return navi_it->title_prev_btn; | ||
338 | else if (!strcmp(part, "next_btn")) | ||
339 | return navi_it->title_next_btn; | ||
340 | else if (!strcmp(part, "icon")) | ||
341 | return navi_it->title_icon; | ||
342 | |||
343 | //common parts | ||
344 | return elm_object_part_content_get(VIEW(navi_it), part); | ||
345 | } | ||
346 | |||
347 | static Evas_Object * | ||
348 | _item_content_unset_hook(Elm_Object_Item *it, const char *part) | ||
349 | { | ||
350 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
351 | |||
352 | //specified parts | ||
353 | if (!part || !strcmp("default", part)) | ||
354 | return _item_content_unset(navi_it); | ||
355 | else if (!strcmp(part, "prev_btn")) | ||
356 | return _title_prev_btn_unset(navi_it); | ||
357 | else if (!strcmp(part, "next_btn")) | ||
358 | return _title_next_btn_unset(navi_it); | ||
359 | else if (!strcmp(part, "icon")) | ||
360 | return _title_icon_unset(navi_it); | ||
361 | |||
362 | return _title_content_unset(navi_it, part); | ||
363 | } | ||
364 | |||
365 | static void | ||
366 | _item_signal_emit_hook(Elm_Object_Item *it, | ||
367 | const char *emission, | ||
368 | const char *source) | ||
369 | { | ||
370 | elm_object_signal_emit(VIEW(it), emission, source); | ||
371 | } | ||
372 | |||
373 | static void | ||
374 | _item_title_visible_update(Elm_Naviframe_Item *navi_it) | ||
375 | { | ||
376 | if (navi_it->title_visible) | ||
377 | elm_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm"); | ||
378 | else | ||
379 | elm_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm"); | ||
380 | } | ||
381 | |||
382 | static void | ||
383 | _sizing_eval(Evas_Object *obj) | ||
384 | { | ||
385 | Widget_Data *wd; | ||
386 | Elm_Naviframe_Item *it; | ||
387 | Evas_Coord x, y, w, h; | ||
388 | Evas_Coord minw = -1, minh = -1; | ||
389 | |||
390 | wd = elm_widget_data_get(obj); | ||
391 | if (!wd) return; | ||
392 | |||
393 | evas_object_geometry_get(obj, &x, &y, &w, &h); | ||
394 | |||
395 | EINA_INLIST_FOREACH(wd->stack, it) | ||
396 | { | ||
397 | evas_object_move(VIEW(it), x, y); | ||
398 | evas_object_resize(VIEW(it), w, h); | ||
399 | edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)), | ||
400 | &it->minw, | ||
401 | &it->minh); | ||
402 | if (it->minw > minw) minw = it->minw; | ||
403 | if (it->minh > minh) minh = it->minh; | ||
404 | } | ||
405 | evas_object_size_hint_min_set(obj, minw, minh); | ||
406 | evas_object_size_hint_max_set(obj, -1, -1); | ||
407 | } | ||
408 | |||
409 | static void | ||
410 | _move(void *data __UNUSED__, | ||
411 | Evas *e __UNUSED__, | ||
412 | Evas_Object *obj, | ||
413 | void *event_info __UNUSED__) | ||
414 | { | ||
415 | _sizing_eval(obj); | ||
416 | } | ||
417 | |||
418 | static void | ||
419 | _resize(void *data __UNUSED__, | ||
420 | Evas *e __UNUSED__, | ||
421 | Evas_Object *obj, | ||
422 | void *event_info __UNUSED__) | ||
423 | { | ||
424 | _sizing_eval(obj); | ||
425 | } | ||
426 | |||
427 | static void | ||
428 | _title_clicked(void *data, | ||
429 | Evas_Object *obj __UNUSED__, | ||
430 | const char *emission __UNUSED__, | ||
431 | const char *source __UNUSED__) | ||
432 | { | ||
433 | Elm_Naviframe_Item *it = data; | ||
434 | evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it); | ||
435 | } | ||
436 | |||
437 | static void | ||
438 | _back_btn_clicked(void *data, | ||
439 | Evas_Object *obj, | ||
440 | void *event_info __UNUSED__) | ||
441 | { | ||
442 | /* Since edje has the event queue, clicked event could be happend multiple times | ||
443 | on some heavy environment. This callback del will prevent those scenario and | ||
444 | guarantee only one clicked for it's own page. */ | ||
445 | evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked); | ||
446 | elm_naviframe_item_pop(data); | ||
447 | } | ||
448 | |||
449 | static Evas_Object * | ||
450 | _back_btn_new(Evas_Object *obj) | ||
451 | { | ||
452 | Evas_Object *btn; | ||
453 | char buf[1024]; | ||
454 | btn = elm_button_add(obj); | ||
455 | if (!btn) return NULL; | ||
456 | evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj); | ||
457 | snprintf(buf, sizeof(buf), "naviframe/back_btn/%s", | ||
458 | elm_widget_style_get(obj)); | ||
459 | elm_object_style_set(btn, buf); | ||
460 | return btn; | ||
461 | } | ||
462 | |||
463 | static void _text_set_hook(Evas_Object *obj, | ||
464 | const char *part, | ||
465 | const char *label) | ||
466 | { | ||
467 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
468 | if (!it) return; | ||
469 | elm_object_item_part_text_set(it, part, label); | ||
470 | } | ||
471 | |||
472 | static const char *_text_get_hook(const Evas_Object *obj, const char *part) | ||
473 | { | ||
474 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
475 | if (!it) return NULL; | ||
476 | return elm_object_item_part_text_get(it, part); | ||
477 | } | ||
478 | |||
479 | static void | ||
480 | _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) | ||
481 | { | ||
482 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
483 | if (!it) return; | ||
484 | elm_object_item_part_content_set(it, part, content); | ||
485 | } | ||
486 | |||
487 | static Evas_Object * | ||
488 | _content_unset_hook(Evas_Object *obj, const char *part) | ||
489 | { | ||
490 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
491 | if (!it) return NULL; | ||
492 | return elm_object_item_part_content_unset(it, part); | ||
493 | } | ||
494 | |||
495 | static Evas_Object * | ||
496 | _content_get_hook(const Evas_Object *obj, const char *part) | ||
497 | { | ||
498 | Elm_Object_Item *it = elm_naviframe_top_item_get(obj); | ||
499 | if (!it) return NULL; | ||
500 | return elm_object_item_part_content_get(it, part); | ||
501 | } | ||
502 | |||
503 | static void | ||
504 | _title_content_del(void *data, | ||
505 | Evas *e __UNUSED__, | ||
506 | Evas_Object *obj __UNUSED__, | ||
507 | void *event_info __UNUSED__) | ||
508 | { | ||
509 | char buf[1024]; | ||
510 | Elm_Naviframe_Content_Item_Pair *pair = data; | ||
511 | Elm_Naviframe_Item *it = pair->it; | ||
512 | snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part); | ||
513 | elm_object_signal_emit(VIEW(it), buf, "elm"); | ||
514 | it->content_list = eina_inlist_remove(it->content_list, | ||
515 | EINA_INLIST_GET(pair)); | ||
516 | eina_stringshare_del(pair->part); | ||
517 | free(pair); | ||
518 | } | ||
519 | |||
520 | static void | ||
521 | _title_prev_btn_del(void *data, | ||
522 | Evas *e __UNUSED__, | ||
523 | Evas_Object *obj __UNUSED__, | ||
524 | void *event_info __UNUSED__) | ||
525 | { | ||
526 | Elm_Naviframe_Item *it = data; | ||
527 | it->back_btn = EINA_FALSE; | ||
528 | it->title_prev_btn = NULL; | ||
529 | elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm"); | ||
530 | } | ||
531 | |||
532 | static void | ||
533 | _title_next_btn_del(void *data, | ||
534 | Evas *e __UNUSED__, | ||
535 | Evas_Object *obj __UNUSED__, | ||
536 | void *event_info __UNUSED__) | ||
537 | { | ||
538 | Elm_Naviframe_Item *it = data; | ||
539 | it->title_next_btn = NULL; | ||
540 | elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm"); | ||
541 | } | ||
542 | |||
543 | static void | ||
544 | _title_icon_del(void *data, | ||
545 | Evas *e __UNUSED__, | ||
546 | Evas_Object *obj __UNUSED__, | ||
547 | void *event_info __UNUSED__) | ||
548 | { | ||
549 | Elm_Naviframe_Item *it = data; | ||
550 | it->title_icon = NULL; | ||
551 | elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm"); | ||
552 | } | ||
553 | |||
554 | static void | ||
555 | _item_content_del(void *data, | ||
556 | Evas *e __UNUSED__, | ||
557 | Evas_Object *obj __UNUSED__, | ||
558 | void *event_info __UNUSED__) | ||
559 | { | ||
560 | Elm_Naviframe_Item *it = data; | ||
561 | it->content = NULL; | ||
562 | elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm"); | ||
563 | } | ||
564 | |||
565 | static void | ||
566 | _title_content_set(Elm_Naviframe_Item *it, | ||
567 | const char *part, | ||
568 | Evas_Object *content) | ||
569 | { | ||
570 | char buf[1024]; | ||
571 | Elm_Naviframe_Content_Item_Pair *pair = NULL; | ||
572 | Evas_Object *prev_content = NULL; | ||
573 | |||
574 | EINA_INLIST_FOREACH(it->content_list, pair) | ||
575 | if (!strcmp(part, pair->part)) break; | ||
576 | |||
577 | if (pair) | ||
578 | { | ||
579 | prev_content = elm_object_part_content_get(VIEW(it), part); | ||
580 | if (prev_content != content) | ||
581 | { | ||
582 | if (content) | ||
583 | { | ||
584 | evas_object_event_callback_del(prev_content, | ||
585 | EVAS_CALLBACK_DEL, | ||
586 | _title_content_del); | ||
587 | snprintf(buf, sizeof(buf), "elm,state,%s,hide", part); | ||
588 | elm_object_signal_emit(VIEW(it), buf, "elm"); | ||
589 | } | ||
590 | evas_object_del(prev_content); | ||
591 | if (!content) return; | ||
592 | } | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | if (!content) return; | ||
597 | pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair); | ||
598 | if (!pair) | ||
599 | { | ||
600 | ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it)); | ||
601 | return; | ||
602 | } | ||
603 | pair->it = it; | ||
604 | eina_stringshare_replace(&pair->part, part); | ||
605 | it->content_list = eina_inlist_append(it->content_list, | ||
606 | EINA_INLIST_GET(pair)); | ||
607 | } | ||
608 | if (prev_content != content) | ||
609 | { | ||
610 | evas_object_event_callback_add(content, | ||
611 | EVAS_CALLBACK_DEL, | ||
612 | _title_content_del, | ||
613 | pair); | ||
614 | } | ||
615 | elm_object_part_content_set(VIEW(it), part, content); | ||
616 | snprintf(buf, sizeof(buf), "elm,state,%s,show", part); | ||
617 | elm_object_signal_emit(VIEW(it), buf, "elm"); | ||
618 | |||
619 | _sizing_eval(WIDGET(it)); | ||
620 | } | ||
621 | |||
622 | static void | ||
623 | _title_prev_btn_set(Elm_Naviframe_Item *it, | ||
624 | Evas_Object *btn, | ||
625 | Eina_Bool back_btn) | ||
626 | { | ||
627 | if (it->title_prev_btn == btn) return; | ||
628 | if (it->title_prev_btn) evas_object_del(it->title_prev_btn); | ||
629 | it->title_prev_btn = btn; | ||
630 | if (!btn) return; | ||
631 | |||
632 | evas_object_event_callback_add(btn, | ||
633 | EVAS_CALLBACK_DEL, | ||
634 | _title_prev_btn_del, | ||
635 | it); | ||
636 | elm_object_part_content_set(VIEW(it), "elm.swallow.prev_btn", btn); | ||
637 | elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm"); | ||
638 | it->back_btn = back_btn; | ||
639 | |||
640 | _sizing_eval(WIDGET(it)); | ||
641 | } | ||
642 | |||
643 | static void | ||
644 | _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn) | ||
645 | { | ||
646 | if (it->title_next_btn == btn) return; | ||
647 | if (it->title_next_btn) evas_object_del(it->title_next_btn); | ||
648 | it->title_next_btn = btn; | ||
649 | if (!btn) return; | ||
650 | |||
651 | evas_object_event_callback_add(btn, | ||
652 | EVAS_CALLBACK_DEL, | ||
653 | _title_next_btn_del, | ||
654 | it); | ||
655 | elm_object_part_content_set(VIEW(it), "elm.swallow.next_btn", btn); | ||
656 | elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm"); | ||
657 | |||
658 | _sizing_eval(WIDGET(it)); | ||
659 | } | ||
660 | |||
661 | static void | ||
662 | _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon) | ||
663 | { | ||
664 | if (it->title_icon == icon) return; | ||
665 | if (it->title_icon) evas_object_del(it->title_icon); | ||
666 | it->title_icon = icon; | ||
667 | if (!icon) return; | ||
668 | |||
669 | evas_object_event_callback_add(icon, | ||
670 | EVAS_CALLBACK_DEL, | ||
671 | _title_icon_del, | ||
672 | it); | ||
673 | elm_object_part_content_set(VIEW(it), "elm.swallow.icon", icon); | ||
674 | elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm"); | ||
675 | |||
676 | _sizing_eval(WIDGET(it)); | ||
677 | } | ||
678 | |||
679 | static Evas_Object * | ||
680 | _item_content_unset(Elm_Naviframe_Item *it) | ||
681 | { | ||
682 | Evas_Object *content = it->content; | ||
683 | if (!content) return NULL; | ||
684 | |||
685 | elm_object_part_content_unset(VIEW(it), "elm.swallow.content"); | ||
686 | elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm"); | ||
687 | evas_object_event_callback_del(content, | ||
688 | EVAS_CALLBACK_DEL, | ||
689 | _item_content_del); | ||
690 | _sizing_eval(WIDGET(it)); | ||
691 | |||
692 | it->content = NULL; | ||
693 | return content; | ||
694 | } | ||
695 | |||
696 | static Evas_Object * | ||
697 | _title_prev_btn_unset(Elm_Naviframe_Item *it) | ||
698 | { | ||
699 | Evas_Object *content = it->title_prev_btn; | ||
700 | if (!content) return NULL; | ||
701 | |||
702 | elm_object_part_content_unset(VIEW(it), "elm.swallow.prev_btn"); | ||
703 | elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm"); | ||
704 | evas_object_event_callback_del(content, | ||
705 | EVAS_CALLBACK_DEL, | ||
706 | _title_prev_btn_del); | ||
707 | _sizing_eval(WIDGET(it)); | ||
708 | |||
709 | it->title_prev_btn = NULL; | ||
710 | return content; | ||
711 | } | ||
712 | |||
713 | static Evas_Object * | ||
714 | _title_next_btn_unset(Elm_Naviframe_Item *it) | ||
715 | { | ||
716 | Evas_Object *content = it->title_next_btn; | ||
717 | if (!content) return NULL; | ||
718 | |||
719 | elm_object_part_content_unset(VIEW(it), "elm.swallow.next_btn"); | ||
720 | elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm"); | ||
721 | evas_object_event_callback_del(content, | ||
722 | EVAS_CALLBACK_DEL, | ||
723 | _title_next_btn_del); | ||
724 | _sizing_eval(WIDGET(it)); | ||
725 | |||
726 | it->title_next_btn = NULL; | ||
727 | return content; | ||
728 | } | ||
729 | |||
730 | static Evas_Object * | ||
731 | _title_icon_unset(Elm_Naviframe_Item *it) | ||
732 | { | ||
733 | Evas_Object *content = it->title_icon; | ||
734 | if (!content) return NULL; | ||
735 | |||
736 | elm_object_part_content_unset(VIEW(it), "elm.swallow.icon"); | ||
737 | elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm"); | ||
738 | evas_object_event_callback_del(content, | ||
739 | EVAS_CALLBACK_DEL, | ||
740 | _title_icon_del); | ||
741 | _sizing_eval(WIDGET(it)); | ||
742 | it->title_icon = NULL; | ||
743 | |||
744 | return content; | ||
745 | } | ||
746 | |||
747 | static Evas_Object * | ||
748 | _title_content_unset(Elm_Naviframe_Item *it, const char *part) | ||
749 | { | ||
750 | Elm_Naviframe_Content_Item_Pair *pair = NULL; | ||
751 | char buf[1028]; | ||
752 | Evas_Object *content = NULL; | ||
753 | |||
754 | EINA_INLIST_FOREACH(it->content_list, pair) | ||
755 | { | ||
756 | if (!strcmp(part, pair->part)) | ||
757 | { | ||
758 | content = elm_object_part_content_get(VIEW(it), part); | ||
759 | eina_stringshare_del(pair->part); | ||
760 | it->content_list = eina_inlist_remove(it->content_list, | ||
761 | EINA_INLIST_GET(pair)); | ||
762 | free(pair); | ||
763 | break; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | if (!content) return NULL; | ||
768 | |||
769 | elm_object_part_content_unset(VIEW(it), part); | ||
770 | snprintf(buf, sizeof(buf), "elm,state,%s,hide", part); | ||
771 | elm_object_signal_emit(VIEW(it), buf, "elm"); | ||
772 | evas_object_event_callback_del(content, | ||
773 | EVAS_CALLBACK_DEL, | ||
774 | _title_content_del); | ||
775 | _sizing_eval(WIDGET(it)); | ||
776 | |||
777 | return content; | ||
778 | } | ||
779 | |||
780 | static void | ||
781 | _item_del(Elm_Naviframe_Item *it) | ||
782 | { | ||
783 | Widget_Data *wd; | ||
784 | Elm_Naviframe_Content_Item_Pair *content_pair; | ||
785 | Elm_Naviframe_Text_Item_Pair *text_pair; | ||
786 | Evas_Object *content; | ||
787 | |||
788 | if (!it) return; | ||
789 | |||
790 | wd = elm_widget_data_get(WIDGET(it)); | ||
791 | if (!wd) return; | ||
792 | |||
793 | while (it->content_list) | ||
794 | { | ||
795 | content_pair = | ||
796 | EINA_INLIST_CONTAINER_GET(it->content_list, | ||
797 | Elm_Naviframe_Content_Item_Pair); | ||
798 | content = elm_object_part_content_get(VIEW(it), content_pair->part); | ||
799 | evas_object_event_callback_del(content, | ||
800 | EVAS_CALLBACK_DEL, | ||
801 | _title_content_del); | ||
802 | eina_stringshare_del(content_pair->part); | ||
803 | it->content_list = eina_inlist_remove(it->content_list, | ||
804 | it->content_list); | ||
805 | free(content_pair); | ||
806 | } | ||
807 | |||
808 | while (it->text_list) | ||
809 | { | ||
810 | text_pair = EINA_INLIST_CONTAINER_GET(it->text_list, | ||
811 | Elm_Naviframe_Text_Item_Pair); | ||
812 | eina_stringshare_del(text_pair->part); | ||
813 | it->text_list = eina_inlist_remove(it->text_list, | ||
814 | it->text_list); | ||
815 | free(text_pair); | ||
816 | } | ||
817 | |||
818 | eina_stringshare_del(it->style); | ||
819 | |||
820 | if (wd->preserve && it->content) | ||
821 | { | ||
822 | elm_object_part_content_unset(VIEW(it), "elm.swallow.content"); | ||
823 | evas_object_event_callback_del(it->content, | ||
824 | EVAS_CALLBACK_DEL, | ||
825 | _item_content_del); | ||
826 | } | ||
827 | } | ||
828 | |||
829 | static Eina_Bool | ||
830 | _item_del_pre_hook(Elm_Object_Item *it) | ||
831 | { | ||
832 | Elm_Naviframe_Item *navi_it; | ||
833 | Widget_Data *wd; | ||
834 | |||
835 | navi_it =(Elm_Naviframe_Item *)it; | ||
836 | wd = elm_widget_data_get(WIDGET(navi_it)); | ||
837 | if (!wd) return EINA_FALSE; | ||
838 | |||
839 | if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) | ||
840 | { | ||
841 | wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it)); | ||
842 | _item_del(navi_it); | ||
843 | //If the item is only one, the stack will be empty | ||
844 | if (!wd->stack) return EINA_TRUE; | ||
845 | navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last, | ||
846 | Elm_Naviframe_Item); | ||
847 | evas_object_show(VIEW(navi_it)); | ||
848 | evas_object_raise(VIEW(navi_it)); | ||
849 | elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm"); | ||
850 | } | ||
851 | else | ||
852 | { | ||
853 | wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it)); | ||
854 | _item_del(navi_it); | ||
855 | } | ||
856 | |||
857 | return EINA_TRUE; | ||
858 | } | ||
859 | |||
860 | static void | ||
861 | _pushed_finished(void *data, | ||
862 | Evas_Object *obj __UNUSED__, | ||
863 | const char *emission __UNUSED__, | ||
864 | const char *source __UNUSED__) | ||
865 | { | ||
866 | Widget_Data *wd; | ||
867 | Elm_Naviframe_Item *it = data; | ||
868 | if (!it) return; | ||
869 | |||
870 | wd = elm_widget_data_get(WIDGET(it)); | ||
871 | if (!wd) return; | ||
872 | |||
873 | evas_object_hide(VIEW(it)); | ||
874 | |||
875 | if (it->content) | ||
876 | elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable); | ||
877 | |||
878 | if (wd->freeze_events) | ||
879 | evas_object_freeze_events_set(VIEW(it), EINA_FALSE); | ||
880 | } | ||
881 | |||
882 | static void | ||
883 | _popped_finished(void *data, | ||
884 | Evas_Object *obj __UNUSED__, | ||
885 | const char *emission __UNUSED__, | ||
886 | const char *source __UNUSED__) | ||
887 | { | ||
888 | Widget_Data *wd; | ||
889 | Elm_Naviframe_Item *it = data; | ||
890 | if (!it) return; | ||
891 | |||
892 | wd = elm_widget_data_get(WIDGET(it)); | ||
893 | if (!wd) return; | ||
894 | |||
895 | if (wd->preserve && it->content) | ||
896 | elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable); | ||
897 | |||
898 | _item_del(data); | ||
899 | |||
900 | elm_widget_item_free(data); | ||
901 | } | ||
902 | |||
903 | static void | ||
904 | _show_finished(void *data, | ||
905 | Evas_Object *obj __UNUSED__, | ||
906 | const char *emission __UNUSED__, | ||
907 | const char *source __UNUSED__) | ||
908 | { | ||
909 | Elm_Naviframe_Item *it; | ||
910 | Widget_Data *wd; | ||
911 | |||
912 | it = data; | ||
913 | if (!it) return; | ||
914 | wd = elm_widget_data_get(WIDGET(it)); | ||
915 | if (!wd) return; | ||
916 | |||
917 | elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable); | ||
918 | |||
919 | evas_object_smart_callback_call(WIDGET(it), | ||
920 | SIG_TRANSITION_FINISHED, | ||
921 | data); | ||
922 | if (wd->freeze_events) | ||
923 | evas_object_freeze_events_set(VIEW(it), EINA_FALSE); | ||
924 | } | ||
925 | |||
926 | static void | ||
927 | _changed_size_hints(void *data, | ||
928 | Evas *e __UNUSED__, | ||
929 | Evas_Object *obj __UNUSED__, | ||
930 | void *event_info __UNUSED__) | ||
931 | { | ||
932 | _sizing_eval(data); | ||
933 | } | ||
934 | |||
935 | static void | ||
936 | _item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content) | ||
937 | { | ||
938 | if (navi_it->content == content) return; | ||
939 | if (navi_it->content) evas_object_del(navi_it->content); | ||
940 | elm_object_part_content_set(VIEW(navi_it), "elm.swallow.content", content); | ||
941 | |||
942 | if (content) | ||
943 | elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm"); | ||
944 | else | ||
945 | elm_object_signal_emit(VIEW(navi_it), "elm,state,content,hide", "elm"); | ||
946 | |||
947 | evas_object_event_callback_add(content, | ||
948 | EVAS_CALLBACK_DEL, | ||
949 | _item_content_del, | ||
950 | navi_it); | ||
951 | navi_it->content = content; | ||
952 | _sizing_eval(WIDGET(navi_it)); | ||
953 | } | ||
954 | |||
955 | //FIXME: need to handle if this function is called while transition | ||
956 | static void | ||
957 | _item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style) | ||
958 | { | ||
959 | Elm_Naviframe_Content_Item_Pair *content_pair; | ||
960 | Elm_Naviframe_Text_Item_Pair *text_pair; | ||
961 | Widget_Data *wd; | ||
962 | |||
963 | char buf[256]; | ||
964 | |||
965 | if (!item_style) | ||
966 | { | ||
967 | strcpy(buf, "item/basic"); | ||
968 | eina_stringshare_replace(&navi_it->style, "basic"); | ||
969 | } | ||
970 | else | ||
971 | { | ||
972 | snprintf(buf, sizeof(buf), "item/%s", item_style); | ||
973 | eina_stringshare_replace(&navi_it->style, item_style); | ||
974 | } | ||
975 | elm_layout_theme_set(VIEW(navi_it), | ||
976 | "naviframe", | ||
977 | buf, | ||
978 | elm_widget_style_get(WIDGET(navi_it))); | ||
979 | //recover item | ||
980 | EINA_INLIST_FOREACH(navi_it->text_list, text_pair) | ||
981 | _item_text_set_hook((Elm_Object_Item *) navi_it, | ||
982 | text_pair->part, | ||
983 | elm_object_part_text_get(VIEW(navi_it), | ||
984 | text_pair->part)); | ||
985 | |||
986 | EINA_INLIST_FOREACH(navi_it->content_list, content_pair) | ||
987 | _item_content_set_hook((Elm_Object_Item *) navi_it, | ||
988 | content_pair->part, | ||
989 | elm_object_part_content_get(VIEW(navi_it), | ||
990 | content_pair->part)); | ||
991 | //content | ||
992 | if (navi_it->content) | ||
993 | elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm"); | ||
994 | |||
995 | //prev button | ||
996 | if (navi_it->title_prev_btn) | ||
997 | elm_object_signal_emit(VIEW(navi_it), "elm,state,prev_btn,show", "elm"); | ||
998 | |||
999 | //next button | ||
1000 | if (navi_it->title_next_btn) | ||
1001 | elm_object_signal_emit(VIEW(navi_it), "elm,state,next_btn,show", "elm"); | ||
1002 | |||
1003 | _sizing_eval(WIDGET(navi_it)); | ||
1004 | |||
1005 | wd = elm_widget_data_get(WIDGET(navi_it)); | ||
1006 | if (!wd) return; | ||
1007 | |||
1008 | if (wd->freeze_events) | ||
1009 | evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE); | ||
1010 | } | ||
1011 | |||
1012 | static Elm_Naviframe_Item * | ||
1013 | _item_new(Evas_Object *obj, | ||
1014 | const char *title_label, | ||
1015 | Evas_Object *prev_btn, | ||
1016 | Evas_Object *next_btn, | ||
1017 | Evas_Object *content, | ||
1018 | const char *item_style) | ||
1019 | { | ||
1020 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1021 | |||
1022 | //create item | ||
1023 | Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item); | ||
1024 | if (!it) | ||
1025 | { | ||
1026 | ERR("Failed to allocate new item! : naviframe=%p", obj); | ||
1027 | return NULL; | ||
1028 | } | ||
1029 | |||
1030 | elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook); | ||
1031 | elm_widget_item_text_set_hook_set(it, _item_text_set_hook); | ||
1032 | elm_widget_item_text_get_hook_set(it, _item_text_get_hook); | ||
1033 | elm_widget_item_content_set_hook_set(it, _item_content_set_hook); | ||
1034 | elm_widget_item_content_get_hook_set(it, _item_content_get_hook); | ||
1035 | elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook); | ||
1036 | elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook); | ||
1037 | |||
1038 | //item base layout | ||
1039 | VIEW(it) = elm_layout_add(obj); | ||
1040 | evas_object_smart_member_add(VIEW(it), obj); | ||
1041 | |||
1042 | evas_object_event_callback_add(VIEW(it), | ||
1043 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
1044 | _changed_size_hints, | ||
1045 | obj); | ||
1046 | elm_object_signal_callback_add(VIEW(it), | ||
1047 | "elm,action,show,finished", | ||
1048 | "", | ||
1049 | _show_finished, it); | ||
1050 | elm_object_signal_callback_add(VIEW(it), | ||
1051 | "elm,action,pushed,finished", | ||
1052 | "", | ||
1053 | _pushed_finished, it); | ||
1054 | elm_object_signal_callback_add(VIEW(it), | ||
1055 | "elm,action,popped,finished", | ||
1056 | "", | ||
1057 | _popped_finished, it); | ||
1058 | elm_object_signal_callback_add(VIEW(it), | ||
1059 | "elm,action,title,clicked", | ||
1060 | "", | ||
1061 | _title_clicked, it); | ||
1062 | |||
1063 | _item_style_set(it, item_style); | ||
1064 | _item_text_set_hook((Elm_Object_Item *)it, "elm.text.title", title_label); | ||
1065 | |||
1066 | //title buttons | ||
1067 | if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack)) | ||
1068 | { | ||
1069 | prev_btn = _back_btn_new(obj); | ||
1070 | _title_prev_btn_set(it, prev_btn, EINA_TRUE); | ||
1071 | } | ||
1072 | else | ||
1073 | _title_prev_btn_set(it, prev_btn, EINA_FALSE); | ||
1074 | |||
1075 | _title_next_btn_set(it, next_btn); | ||
1076 | _item_content_set(it, content); | ||
1077 | it->title_visible = EINA_TRUE; | ||
1078 | return it; | ||
1079 | } | ||
1080 | |||
1081 | static Eina_Bool | ||
1082 | _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) | ||
1083 | { | ||
1084 | Eina_Bool ret; | ||
1085 | Elm_Naviframe_Item *top_it; | ||
1086 | Eina_List *l = NULL; | ||
1087 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1088 | void *(*list_data_get)(const Eina_List *list); | ||
1089 | if (!wd) return EINA_FALSE; | ||
1090 | |||
1091 | top_it = (Elm_Naviframe_Item *)elm_naviframe_top_item_get(obj); | ||
1092 | if (!top_it) return EINA_FALSE; | ||
1093 | |||
1094 | list_data_get = eina_list_data_get; | ||
1095 | |||
1096 | //Forcus order: prev button, next button, contents | ||
1097 | if (top_it->title_prev_btn) | ||
1098 | l = eina_list_append(l, top_it->title_prev_btn); | ||
1099 | if (top_it->title_next_btn) | ||
1100 | l = eina_list_append(l, top_it->title_next_btn); | ||
1101 | l = eina_list_append(l, VIEW(top_it)); | ||
1102 | |||
1103 | ret = elm_widget_focus_list_next_get(obj, l, list_data_get, dir, next); | ||
1104 | eina_list_free(l); | ||
1105 | return ret; | ||
1106 | } | ||
1107 | |||
1108 | EAPI Evas_Object * | ||
1109 | elm_naviframe_add(Evas_Object *parent) | ||
1110 | { | ||
1111 | Evas_Object *obj; | ||
1112 | Evas *e; | ||
1113 | Widget_Data *wd; | ||
1114 | |||
1115 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
1116 | ELM_SET_WIDTYPE(widtype, "naviframe"); | ||
1117 | elm_widget_type_set(obj, "naviframe"); | ||
1118 | elm_widget_sub_object_add(parent, obj); | ||
1119 | elm_widget_data_set(obj, wd); | ||
1120 | elm_widget_del_hook_set(obj, _del_hook); | ||
1121 | elm_widget_disable_hook_set(obj, _disable_hook); | ||
1122 | elm_widget_theme_hook_set(obj, _theme_hook); | ||
1123 | elm_widget_text_set_hook_set(obj, _text_set_hook); | ||
1124 | elm_widget_text_get_hook_set(obj, _text_get_hook); | ||
1125 | elm_widget_content_set_hook_set(obj, _content_set_hook); | ||
1126 | elm_widget_content_get_hook_set(obj, _content_get_hook); | ||
1127 | elm_widget_content_unset_hook_set(obj, _content_unset_hook); | ||
1128 | elm_widget_signal_emit_hook_set(obj, _emit_hook); | ||
1129 | elm_widget_can_focus_set(obj, EINA_FALSE); | ||
1130 | elm_widget_focus_next_hook_set(obj, _focus_next_hook); | ||
1131 | |||
1132 | //base | ||
1133 | //FIXME: Is this base layout really needed? | ||
1134 | wd->base = elm_layout_add(obj); | ||
1135 | evas_object_event_callback_add(wd->base, | ||
1136 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
1137 | _changed_size_hints, | ||
1138 | obj); | ||
1139 | elm_widget_resize_object_set(obj, wd->base); | ||
1140 | elm_layout_theme_set(wd->base, "naviframe", "base", "default"); | ||
1141 | |||
1142 | evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj); | ||
1143 | evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj); | ||
1144 | evas_object_smart_callbacks_descriptions_set(obj, _signals); | ||
1145 | |||
1146 | wd->auto_pushed = EINA_TRUE; | ||
1147 | wd->freeze_events = EINA_TRUE; | ||
1148 | |||
1149 | return obj; | ||
1150 | } | ||
1151 | |||
1152 | EAPI Elm_Object_Item * | ||
1153 | elm_naviframe_item_push(Evas_Object *obj, | ||
1154 | const char *title_label, | ||
1155 | Evas_Object *prev_btn, | ||
1156 | Evas_Object *next_btn, | ||
1157 | Evas_Object *content, | ||
1158 | const char *item_style) | ||
1159 | { | ||
1160 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1161 | Widget_Data *wd; | ||
1162 | Elm_Naviframe_Item *prev_it, *it; | ||
1163 | |||
1164 | wd = elm_widget_data_get(obj); | ||
1165 | if (!wd) return NULL; | ||
1166 | |||
1167 | it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style); | ||
1168 | if (!it) return NULL; | ||
1169 | |||
1170 | evas_object_show(VIEW(it)); | ||
1171 | |||
1172 | prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj); | ||
1173 | if (prev_it) | ||
1174 | { | ||
1175 | if (wd->freeze_events) | ||
1176 | { | ||
1177 | evas_object_freeze_events_set(VIEW(it), EINA_TRUE); | ||
1178 | evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE); | ||
1179 | } | ||
1180 | elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed", "elm"); | ||
1181 | elm_object_signal_emit(VIEW(it), "elm,state,new,pushed", "elm"); | ||
1182 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it))); | ||
1183 | if (prev_it->content) | ||
1184 | { | ||
1185 | prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content); | ||
1186 | elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE); | ||
1187 | } | ||
1188 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(it))); | ||
1189 | } | ||
1190 | wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it)); | ||
1191 | _sizing_eval(obj); | ||
1192 | return (Elm_Object_Item *)it; | ||
1193 | } | ||
1194 | |||
1195 | EAPI Elm_Object_Item * | ||
1196 | elm_naviframe_item_insert_before(Evas_Object *obj, | ||
1197 | Elm_Object_Item *before, | ||
1198 | const char *title_label, | ||
1199 | Evas_Object *prev_btn, | ||
1200 | Evas_Object *next_btn, | ||
1201 | Evas_Object *content, | ||
1202 | const char *item_style) | ||
1203 | { | ||
1204 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1205 | ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL); | ||
1206 | Elm_Naviframe_Item *it; | ||
1207 | Widget_Data *wd; | ||
1208 | |||
1209 | wd = elm_widget_data_get(obj); | ||
1210 | if (!wd) return NULL; | ||
1211 | |||
1212 | it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style); | ||
1213 | if (!it) return NULL; | ||
1214 | |||
1215 | wd->stack = | ||
1216 | eina_inlist_prepend_relative(wd->stack, | ||
1217 | EINA_INLIST_GET(it), | ||
1218 | EINA_INLIST_GET(((Elm_Naviframe_Item *) before))); | ||
1219 | _sizing_eval(obj); | ||
1220 | return (Elm_Object_Item *)it; | ||
1221 | } | ||
1222 | |||
1223 | EAPI Elm_Object_Item * | ||
1224 | elm_naviframe_item_insert_after(Evas_Object *obj, | ||
1225 | Elm_Object_Item *after, | ||
1226 | const char *title_label, | ||
1227 | Evas_Object *prev_btn, | ||
1228 | Evas_Object *next_btn, | ||
1229 | Evas_Object *content, | ||
1230 | const char *item_style) | ||
1231 | { | ||
1232 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1233 | ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL); | ||
1234 | Elm_Naviframe_Item *it; | ||
1235 | Widget_Data *wd; | ||
1236 | Eina_Bool top_inserted; | ||
1237 | |||
1238 | wd = elm_widget_data_get(obj); | ||
1239 | if (!wd) return NULL; | ||
1240 | |||
1241 | it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style); | ||
1242 | if (!it) return NULL; | ||
1243 | |||
1244 | if (elm_naviframe_top_item_get(obj) == after) top_inserted = EINA_TRUE; | ||
1245 | |||
1246 | wd->stack = | ||
1247 | eina_inlist_append_relative(wd->stack, | ||
1248 | EINA_INLIST_GET(it), | ||
1249 | EINA_INLIST_GET(((Elm_Naviframe_Item *) after))); | ||
1250 | if (top_inserted) | ||
1251 | { | ||
1252 | evas_object_show(VIEW(it)); | ||
1253 | evas_object_hide(VIEW(after)); | ||
1254 | } | ||
1255 | |||
1256 | _sizing_eval(obj); | ||
1257 | |||
1258 | return (Elm_Object_Item *)it; | ||
1259 | } | ||
1260 | |||
1261 | EAPI Evas_Object * | ||
1262 | elm_naviframe_item_pop(Evas_Object *obj) | ||
1263 | { | ||
1264 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1265 | Elm_Naviframe_Item *it, *prev_it = NULL; | ||
1266 | Widget_Data *wd; | ||
1267 | Evas_Object *content = NULL; | ||
1268 | |||
1269 | wd = elm_widget_data_get(obj); | ||
1270 | if (!wd) return NULL; | ||
1271 | |||
1272 | it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj); | ||
1273 | if (!it) return NULL; | ||
1274 | if (wd->preserve) | ||
1275 | content = it->content; | ||
1276 | |||
1277 | if (it->content) | ||
1278 | { | ||
1279 | it->content_unfocusable = elm_widget_tree_unfocusable_get(it->content); | ||
1280 | elm_widget_tree_unfocusable_set(it->content, EINA_TRUE); | ||
1281 | } | ||
1282 | |||
1283 | if (wd->stack->last->prev) | ||
1284 | prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev, | ||
1285 | Elm_Naviframe_Item); | ||
1286 | wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it)); | ||
1287 | if (prev_it) | ||
1288 | { | ||
1289 | if (wd->freeze_events) | ||
1290 | { | ||
1291 | evas_object_freeze_events_set(VIEW(it), EINA_TRUE); | ||
1292 | evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE); | ||
1293 | } | ||
1294 | elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm"); | ||
1295 | evas_object_show(VIEW(prev_it)); | ||
1296 | elm_object_signal_emit(VIEW(prev_it), | ||
1297 | "elm,state,prev,popped", | ||
1298 | "elm"); | ||
1299 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(it))); | ||
1300 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it))); | ||
1301 | } | ||
1302 | else | ||
1303 | { | ||
1304 | _item_del(it); | ||
1305 | elm_widget_item_free(it); | ||
1306 | } | ||
1307 | |||
1308 | return content; | ||
1309 | } | ||
1310 | |||
1311 | EAPI void | ||
1312 | elm_naviframe_item_pop_to(Elm_Object_Item *it) | ||
1313 | { | ||
1314 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it); | ||
1315 | Elm_Naviframe_Item *navi_it; | ||
1316 | Widget_Data *wd; | ||
1317 | Eina_Inlist *l, *prev_l; | ||
1318 | |||
1319 | navi_it = (Elm_Naviframe_Item *)it; | ||
1320 | wd = elm_widget_data_get(WIDGET(navi_it)); | ||
1321 | if (!wd) return; | ||
1322 | |||
1323 | if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return; | ||
1324 | |||
1325 | l = wd->stack->last->prev; | ||
1326 | |||
1327 | while (l) | ||
1328 | { | ||
1329 | if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) == | ||
1330 | ((Elm_Naviframe_Item *)it)) break; | ||
1331 | prev_l = l->prev; | ||
1332 | wd->stack = eina_inlist_remove(wd->stack, l); | ||
1333 | _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item)); | ||
1334 | elm_widget_item_free(EINA_INLIST_CONTAINER_GET(l, | ||
1335 | Elm_Naviframe_Item)); | ||
1336 | l = prev_l; | ||
1337 | } | ||
1338 | elm_naviframe_item_pop(WIDGET(navi_it)); | ||
1339 | } | ||
1340 | |||
1341 | EAPI void | ||
1342 | elm_naviframe_item_promote(Elm_Object_Item *it) | ||
1343 | { | ||
1344 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it); | ||
1345 | Elm_Naviframe_Item *navi_it; | ||
1346 | Elm_Naviframe_Item *prev_it; | ||
1347 | Widget_Data *wd; | ||
1348 | |||
1349 | navi_it = (Elm_Naviframe_Item *)it; | ||
1350 | wd = elm_widget_data_get(navi_it->base.widget); | ||
1351 | if (!wd) return; | ||
1352 | |||
1353 | if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return; | ||
1354 | wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it)); | ||
1355 | prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev, | ||
1356 | Elm_Naviframe_Item); | ||
1357 | if (prev_it->content) | ||
1358 | { | ||
1359 | prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content); | ||
1360 | elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE); | ||
1361 | } | ||
1362 | |||
1363 | if (wd->freeze_events) | ||
1364 | { | ||
1365 | evas_object_freeze_events_set(VIEW(it), EINA_TRUE); | ||
1366 | evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE); | ||
1367 | } | ||
1368 | elm_object_signal_emit(VIEW(prev_it), | ||
1369 | "elm,state,cur,pushed", | ||
1370 | "elm"); | ||
1371 | evas_object_show(VIEW(navi_it)); | ||
1372 | evas_object_raise(VIEW(navi_it)); | ||
1373 | elm_object_signal_emit(VIEW(navi_it), | ||
1374 | "elm,state,new,pushed", | ||
1375 | "elm"); | ||
1376 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it))); | ||
1377 | edje_object_message_signal_process(elm_layout_edje_get(VIEW(navi_it))); | ||
1378 | } | ||
1379 | |||
1380 | EAPI void | ||
1381 | elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content) | ||
1382 | { | ||
1383 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
1384 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1385 | if (!wd) return; | ||
1386 | Elm_Naviframe_Item *itr; | ||
1387 | EINA_INLIST_FOREACH(wd->stack, itr) | ||
1388 | { | ||
1389 | if (elm_object_item_content_get((Elm_Object_Item *)itr) == content) | ||
1390 | { | ||
1391 | elm_naviframe_item_promote((Elm_Object_Item *)itr); | ||
1392 | break; | ||
1393 | } | ||
1394 | } | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | EAPI void | ||
1399 | elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve) | ||
1400 | { | ||
1401 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
1402 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1403 | if (!wd) return; | ||
1404 | wd->preserve = !!preserve; | ||
1405 | } | ||
1406 | |||
1407 | EAPI Eina_Bool | ||
1408 | elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj) | ||
1409 | { | ||
1410 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
1411 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1412 | if (!wd) return EINA_FALSE; | ||
1413 | return wd->preserve; | ||
1414 | } | ||
1415 | |||
1416 | EAPI Elm_Object_Item* | ||
1417 | elm_naviframe_top_item_get(const Evas_Object *obj) | ||
1418 | { | ||
1419 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1420 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1421 | if ((!wd) || (!wd->stack)) return NULL; | ||
1422 | return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last, | ||
1423 | Elm_Naviframe_Item)); | ||
1424 | } | ||
1425 | |||
1426 | EAPI Elm_Object_Item* | ||
1427 | elm_naviframe_bottom_item_get(const Evas_Object *obj) | ||
1428 | { | ||
1429 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1430 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1431 | if ((!wd) || (!wd->stack)) return NULL; | ||
1432 | return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack, | ||
1433 | Elm_Naviframe_Item)); | ||
1434 | } | ||
1435 | |||
1436 | EAPI void | ||
1437 | elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style) | ||
1438 | { | ||
1439 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it); | ||
1440 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
1441 | |||
1442 | if (item_style) | ||
1443 | if (!strcmp(item_style, navi_it->style)) return; | ||
1444 | |||
1445 | if (!item_style) | ||
1446 | if (!strcmp("basic", navi_it->style)) return; | ||
1447 | |||
1448 | _item_style_set(navi_it, item_style); | ||
1449 | _item_title_visible_update(navi_it); | ||
1450 | } | ||
1451 | |||
1452 | EAPI const char * | ||
1453 | elm_naviframe_item_style_get(const Elm_Object_Item *it) | ||
1454 | { | ||
1455 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL); | ||
1456 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
1457 | return navi_it->style; | ||
1458 | } | ||
1459 | |||
1460 | EAPI void | ||
1461 | elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible) | ||
1462 | { | ||
1463 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it); | ||
1464 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
1465 | |||
1466 | visible = !!visible; | ||
1467 | if (navi_it->title_visible == visible) return; | ||
1468 | |||
1469 | navi_it->title_visible = visible; | ||
1470 | _item_title_visible_update(navi_it); | ||
1471 | } | ||
1472 | |||
1473 | EAPI Eina_Bool | ||
1474 | elm_naviframe_item_title_visible_get(const Elm_Object_Item *it) | ||
1475 | { | ||
1476 | ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); | ||
1477 | Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it; | ||
1478 | return navi_it->title_visible; | ||
1479 | } | ||
1480 | |||
1481 | EAPI void | ||
1482 | elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed) | ||
1483 | { | ||
1484 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
1485 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1486 | if (!wd) return; | ||
1487 | wd->auto_pushed = !!auto_pushed; | ||
1488 | } | ||
1489 | |||
1490 | EAPI Eina_Bool | ||
1491 | elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj) | ||
1492 | { | ||
1493 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
1494 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1495 | if (!wd) return EINA_FALSE; | ||
1496 | return wd->auto_pushed; | ||
1497 | } | ||
1498 | |||
1499 | EAPI Eina_List * | ||
1500 | elm_naviframe_items_get(const Evas_Object *obj) | ||
1501 | { | ||
1502 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
1503 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1504 | if (!wd) return NULL; | ||
1505 | Eina_List *ret = NULL; | ||
1506 | Elm_Naviframe_Item *itr; | ||
1507 | EINA_INLIST_FOREACH(wd->stack, itr) | ||
1508 | ret = eina_list_append(ret, itr); | ||
1509 | return ret; | ||
1510 | } | ||
1511 | |||
1512 | EAPI void | ||
1513 | elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled) | ||
1514 | { | ||
1515 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
1516 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1517 | if (!wd) return; | ||
1518 | enabled = !!enabled; | ||
1519 | if (wd->freeze_events == !enabled) return; | ||
1520 | wd->freeze_events = !enabled; | ||
1521 | } | ||
1522 | |||
1523 | EAPI Eina_Bool | ||
1524 | elm_naviframe_event_enabled_get(const Evas_Object *obj) | ||
1525 | { | ||
1526 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
1527 | Widget_Data *wd = elm_widget_data_get(obj); | ||
1528 | if (!wd) return EINA_FALSE; | ||
1529 | return !wd->freeze_events; | ||
1530 | } | ||