initial commit
[profile/tv/apps/native/homescreen.git] / src / dbar.c
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Elementary.h>
18 #include <utilX.h>
19 #include <ctype.h>
20 #include <string.h>
21
22 #include "i18n.h"
23 #include "bar.h"
24 #include "engine.h"
25 #include "defs.h"
26 #include "dbg.h"
27
28 #define STYLE_TITLE "title"
29 #define STYLE_VIDEO "video"
30 #define STYLE_AUDIO "audio"
31 #define STYLE_ALBUM "album"
32 #define STYLE_COMMON "common"
33
34 #define DEFAULT_TITLE "No Information"
35 #define UNKNOWN_DEVICE "Unknown device"
36 #define MESSAGE_DELETE "Are you sure you want to delete the"
37 #define MESSAGE_HISTORY_BANNER "Your history has been cleared"
38 #define KEY_DBAR_ITEM "dbar.item"
39 #define ICON_PIN "pin"
40 #define ICON_LOCK "lock"
41
42 #define ASPECT_RATIO ((double)198 / (double)(166))
43 #define LABEL_BUFMAX 512
44 #define DBAR_PADDING 10
45 #define FUNCS_PADDING 3
46 #define BUF_DELIMITER 2
47 #define BUF_STRING 128
48
49 #define IMG_FUNCS_FAVORITE IMAGEDIR"/ico_favorite_channel_nor.png"
50 #define IMG_FUNCS_PIN IMAGEDIR"/ico_pin_channel_nor.png"
51 #define IMG_FUNCS_LOCK IMAGEDIR"/ico_locked_channel_nor.png"
52
53 enum _dbar_state {
54         DBAR_STATE_HIDE,
55         DBAR_STATE_DBAR,
56         DBAR_STATE_XBAR
57 };
58
59 struct _dbar_item;
60
61 struct _dbar_data {
62         Evas_Object *base;
63         Evas_Object *ly;
64         Evas_Object *scr;
65         Evas_Object *tbl;
66         Eina_List *list;
67         struct _dbar_item *cur;
68         struct bar_cb focus_cb;
69         int tbl_idx;
70         int content_column;
71
72         enum _dbar_state state;
73 };
74
75 struct _dbar_item {
76         Evas_Object *eo;
77         struct engine_dbar_item *it;
78         struct _dbar_data *bar;
79         struct bar_info *xbar;
80         Eina_Bool focus;
81 };
82
83 struct _dbar_item_loader {
84         enum engine_dbar_item_style style;
85         Evas_Object *(*loader)(Evas_Object *p, struct engine_dbar_item *it,
86                         Eina_Bool *fill);
87 };
88
89 static void _bring_in_middle(Evas_Object *scr, Evas_Object *obj)
90 {
91         Evas_Coord y, h, sy, sh, rx, ry, rw, rh, my, smy, ch;
92
93         if (!scr || !obj)
94                 return;
95
96         evas_object_geometry_get(obj, NULL, &y, NULL, &h);
97         evas_object_geometry_get(scr, NULL, &sy, NULL, &sh);
98         elm_scroller_region_get(scr, &rx, &ry, &rw, &rh);
99         elm_scroller_child_size_get(scr, NULL, &ch);
100
101         my = y + (h >> 1);
102         smy = sy + (sh >> 1);
103
104         ry = ry - smy + my;
105
106         if (ry < 0)
107                 ry = 0;
108         else if (ry + rh > ch)
109                 ry = ch - rh;
110
111         elm_scroller_region_bring_in(scr, rx, ry, rw, rh);
112 }
113
114 static void _focused(void *data, Evas_Object *obj, void *ei)
115 {
116         struct _dbar_item *foc;
117         struct _dbar_data *bar;
118         Eina_Bool r;
119         Evas_Object *eo;
120
121         if (!data)
122                 return;
123
124         foc = data;
125         bar = foc->bar;
126
127         if (!foc->xbar) {
128                 r = bar->focus_cb.func(bar->focus_cb.data, foc->eo);
129                 if (r)
130                         _bring_in_middle(bar->scr, foc->eo);
131
132                 bar->cur = foc;
133                 bar->state = DBAR_STATE_DBAR;
134
135                 return;
136         }
137
138         switch (bar->state) {
139         case DBAR_STATE_XBAR:
140                 eo = bar->cur->xbar->ops->get_object(bar->cur->xbar);
141                 if (eo)
142                         elm_object_signal_emit(eo, SIG_UNFOCUS_TO_DBAR,
143                                         SRC_PROG);
144                 elm_object_signal_emit(foc->eo, SIG_UNFOCUS_FROM_XBAR,
145                                 SRC_PROG);
146
147                 if (foc != bar->cur) {
148                         elm_object_signal_emit(bar->cur->eo, SIG_HIDE,
149                                         SRC_PROG);
150                         bar->cur->xbar->ops->hide(bar->cur->xbar);
151                         foc->xbar->ops->update(foc->xbar, foc->it, foc->eo);
152                         foc->xbar->ops->show(foc->xbar);
153                 }
154                 break;
155         case DBAR_STATE_HIDE:
156                 eo = foc->xbar->ops->get_object(foc->xbar);
157                 if (eo)
158                         elm_object_signal_emit(eo, SIG_SHOW, SRC_PROG);
159                 r = bar->focus_cb.func(bar->focus_cb.data, foc->eo);
160                 if (r)
161                         _bring_in_middle(bar->scr, foc->eo);
162
163                 foc->xbar->ops->update(foc->xbar, foc->it, foc->eo);
164                 break;
165         case DBAR_STATE_DBAR:
166                 eo = foc->xbar->ops->get_object(foc->xbar);
167                 if (eo)
168                         elm_object_signal_emit(eo, SIG_SHOW, SRC_PROG);
169
170                 r = bar->focus_cb.func(bar->focus_cb.data, foc->eo);
171                 if (r)
172                         _bring_in_middle(bar->scr, foc->eo);
173
174                 if (foc != bar->cur && bar->cur->xbar)
175                         bar->cur->xbar->ops->hide(bar->cur->xbar);
176
177                 foc->xbar->ops->update(foc->xbar, foc->it, foc->eo);
178
179                 break;
180         default:
181                 return;
182         }
183
184         bar->cur = foc;
185         bar->state = DBAR_STATE_DBAR;
186 }
187
188 static void _mouse_over(void *data, Evas *e, Evas_Object *obj, void *ei)
189 {
190         struct _dbar_item *item;
191
192         if (!data) {
193                 _ERR("Invalide argument");
194                 return;
195         }
196
197         item = data;
198
199         if (elm_object_focus_get(item->eo))
200                 return;
201
202         elm_object_focus_set(item->eo, EINA_TRUE);
203 }
204
205 static void _clicked(void *data, Evas *e, Evas_Object *obj, void *ei)
206 {
207         struct _dbar_item *item;
208         Evas_Event_Mouse_Up *ev;
209         Evas_Coord x, y, w, h;
210
211         if (!data || !ei)
212                 return;
213
214         ev = ei;
215
216         evas_object_geometry_get(obj, &x, &y, &w, &h);
217         if (ev->canvas.x < x || ev->canvas.x > x + w ||
218                         ev->canvas.y < y || ev->canvas.y > y + h)
219                 return;
220
221         item = data;
222         engine_dbar_item_launch(item->it);
223 }
224
225 static int _launch_app(struct bar_info *info)
226 {
227         struct _dbar_data *bar;
228         struct _dbar_item *item;
229
230         if (!info)
231                 return EINA_FALSE;
232
233         bar = info->data;
234         item = bar->cur;
235
236         if (!item) {
237                 _ERR("Invalid argument");
238                 return -1;
239         }
240
241         return engine_dbar_item_launch(item->it);
242 }
243
244 static inline Evas_Object *_load_bg(Evas_Object *base,
245                 struct engine_dbar_item *it)
246 {
247         Evas_Object *bg;
248         int r, g, b;
249
250         if (!base || !it)
251                 return NULL;
252
253         bg = evas_object_rectangle_add(evas_object_evas_get(base));
254         if (!bg) {
255                 _ERR("bg add failed");
256                 return NULL;
257         }
258
259         r = 128;
260         g = 128;
261         b = 128;
262         engine_dbar_item_get_color(it, &r, &g, &b);
263         evas_object_color_set(bg, r, g, b, 255);
264
265         return bg;
266 }
267
268 static Evas_Object *_load_title(Evas_Object *p, struct engine_dbar_item *it,
269                 Eina_Bool *fill)
270 {
271         Evas_Object *ly;
272         const char *name;
273
274         if (!p || !it)
275                 return NULL;
276
277         name = engine_dbar_item_get_name(it);
278         if (!name)
279                 name = "";
280
281         ly = elm_layout_add(p);
282         if (!ly) {
283                 _ERR("layout add failed");
284                 return NULL;
285         }
286
287         elm_layout_file_set(ly, EDJEFILE, GRP_DBAR_LABEL);
288         elm_object_part_text_set(ly, PART_TITLE,
289                         engine_dbar_item_get_name(it));
290         if (fill)
291                 *fill = EINA_TRUE;
292
293         return ly;
294 }
295
296 static Evas_Object *_load_ly(Evas_Object *p,
297                 struct engine_dbar_item *it,
298                 const char *group)
299 {
300         Evas_Object *ly;
301         Evas_Object *bg;
302
303         if (!p || !it || !group)
304                 return NULL;
305
306         ly = elm_layout_add(p);
307         if (!ly) {
308                 _ERR("layout add failed");
309                 return NULL;
310         }
311         elm_layout_file_set(ly, EDJEFILE, group);
312
313         bg = _load_bg(ly, it);
314         if (!bg) {
315                 evas_object_del(ly);
316                 return NULL;
317         }
318         elm_object_part_content_set(ly, PART_BG, bg);
319
320         return ly;
321 }
322
323 static const char *_trim(char *str)
324 {
325         int i;
326
327         if (!str)
328                 return str;
329
330         i = strlen(str);
331         i--;
332
333         while (i > 0) {
334                 if (isspace(str[i]))
335                         str[i] = '\0';
336                 else
337                         break;
338                 i++;
339         }
340
341         return str;
342 }
343
344 static void _put_icon(Evas_Object *ly, const char *file, const char *part,
345                 const char *def_sig, const char *def_src,
346                 Eina_Bool make_thumbnail)
347 {
348         Evas_Object *ic;
349
350         if (file && strlen(file) > 0) {
351                 ic = elm_icon_add(ly);
352                 if (ic) {
353                         if (make_thumbnail) {
354                                 elm_need_ethumb();
355                                 elm_icon_thumb_set(ic, file, NULL);
356                         } else {
357                                 elm_image_file_set(ic, file, NULL);
358                         }
359                         elm_image_fill_outside_set(ic, EINA_TRUE);
360                         elm_object_part_content_set(ly, part, ic);
361                         return;
362                 }
363                 _ERR("icon add failed");
364         }
365
366         elm_object_signal_emit(ly, def_sig, def_src);
367 }
368
369 static void _lbl_start_slide(void *data, Evas_Object *obj, void *ei)
370 {
371         elm_label_ellipsis_set(data, EINA_FALSE);
372         elm_label_slide_mode_set(data, ELM_LABEL_SLIDE_MODE_AUTO);
373         elm_label_slide_go(data);
374 }
375
376 static void _lbl_stop_slide(void *data, Evas_Object *obj, void *ei)
377 {
378         elm_label_ellipsis_set(data, EINA_TRUE);
379         elm_label_slide_mode_set(data, ELM_LABEL_SLIDE_MODE_NONE);
380         elm_label_slide_go(data);
381 }
382
383 static Evas_Object *_add_icon(Evas_Object *box, const char *file)
384 {
385         Evas_Object *ic;
386
387         if (!box || !file) {
388                 _ERR("Invalid argument");
389                 return NULL;
390         }
391
392         ic = elm_icon_add(box);
393         if (!ic) {
394                 _ERR("icon add failed");
395                 return NULL;
396         }
397
398         elm_image_file_set(ic, file, NULL);
399         elm_image_no_scale_set(ic, EINA_TRUE);
400         evas_object_show(ic);
401
402         elm_box_pack_end(box, ic);
403
404         return ic;
405 }
406
407 static void _load_funcs(const char *icon, Evas_Object *p)
408 {
409         Evas_Object *box, *ic;
410         int padding;
411         char delimiter[BUF_DELIMITER] = ",";
412         char *iter;
413         char str[BUF_STRING];
414         bool lock, pin;
415
416         if (!icon || !p) {
417                 _ERR("Invalid argument");
418                 return;
419         }
420
421         padding = elm_config_scale_get() * FUNCS_PADDING;
422         box = elm_box_add(p);
423         if (!box) {
424                 _ERR("box add failed");
425                 return;
426         }
427         elm_object_part_content_set(p, PART_FUNCS, box);
428         elm_box_padding_set(box, padding, padding);
429         elm_box_horizontal_set(box, EINA_TRUE);
430
431         strcpy(str, icon);
432
433         iter = NULL;
434         lock = false;
435         pin = false;
436
437         iter = strtok(str, delimiter);
438         while (iter) {
439                 if (!strcmp(iter, ICON_PIN))
440                         pin = true;
441                 else if (!strcmp(iter, ICON_LOCK))
442                         lock = true;
443
444                 iter = strtok(NULL, delimiter);
445         }
446
447         if (pin) {
448                 ic = _add_icon(box, IMG_FUNCS_PIN);
449                 if (!ic) {
450                         _ERR("icon add failed");
451                         evas_object_del(box);
452                         return;
453                 }
454         }
455
456         if (lock) {
457                 ic = _add_icon(box, IMG_FUNCS_LOCK);
458                 if (!ic) {
459                         _ERR("icon add failed");
460                         evas_object_del(box);
461                         return;
462                 }
463         }
464 }
465
466 static Evas_Object *_add_label(Evas_Object *ly,
467                 const char *style, const char *name)
468 {
469         Evas_Object *lbl;
470
471         if (!ly || !style || !name) {
472                 _ERR("Invalid argument");
473                 return NULL;
474         }
475
476         lbl = elm_label_add(ly);
477         if (!lbl) {
478                 _ERR("failed to create label");
479                 return NULL;
480         }
481         elm_object_style_set(lbl, style);
482         elm_object_text_set(lbl, name);
483         evas_object_show(lbl);
484
485         return lbl;
486 }
487
488 static Evas_Object *_add_slide_label(Evas_Object *ly,
489                 const char *name, const char *style)
490 {
491         Evas_Object *lbl;
492         const char *s;
493
494         if (!ly || !name || !style) {
495                 _ERR("Invalid argument");
496                 return NULL;
497         }
498
499         lbl = _add_label(ly, style, name);
500         if (!lbl) {
501                 evas_object_del(ly);
502                 return NULL;
503         }
504         elm_label_ellipsis_set(lbl, EINA_TRUE);
505         s = edje_object_data_get(elm_layout_edje_get(ly),
506                         DATA_TITLE_WIDTH);
507         if (s)
508                 elm_label_wrap_width_set(lbl, atoi(s));
509         else
510                 _ERR("No title width exist");
511
512         elm_label_slide_speed_set(lbl, LABEL_SLIDE_SPEED);
513         evas_object_smart_callback_add(ly, "focused", _lbl_start_slide, lbl);
514         evas_object_smart_callback_add(ly, "unfocused", _lbl_stop_slide, lbl);
515
516         return lbl;
517 }
518
519 static Evas_Object *_load_content_broadcast(Evas_Object *p,
520                 const char *style, struct engine_dbar_item_content *ctnt,
521                 struct engine_dbar_item *it)
522 {
523         Evas_Object *ly, *lbl;
524         const char *channel, *progname, *progtime, *icon;
525
526         if (!p || !style || !ctnt || !it) {
527                 _ERR("Invalid argument");
528                 return NULL;
529         }
530
531         ly = _load_ly(p, it, style);
532         if (!ly)
533                 return NULL;
534
535         channel = engine_dbar_item_get_content_subtitle(ctnt);
536         _trim((char *)channel);
537
538         progname = engine_dbar_item_get_content_description(ctnt);
539         _trim((char *)progname);
540
541         progtime = engine_dbar_item_get_content_detail(ctnt);
542         _trim((char *)progtime);
543
544         icon = engine_dbar_item_get_content_icon(ctnt);
545         if (icon && strlen(icon) != 0)
546                 _load_funcs(_trim((char *)icon), ly);
547
548         lbl = _add_label(ly, STYLE_LABEL_SLIDE_CENTER_40,
549                         _trim((char *)engine_dbar_item_get_name(it)));
550         if (!lbl)
551                 goto err;
552         elm_object_part_content_set(ly, PART_NUMBER, lbl);
553
554         if (!progname || strlen(progname) <= 0) {
555                 if (!channel || strlen(channel) <= 0)
556                         channel = _(DEFAULT_TITLE);
557
558                 lbl = _add_slide_label(ly, channel, STYLE_LABEL_SLIDE_LEFT_32);
559                 if (!lbl)
560                         goto err;
561                 elm_object_part_content_set(ly, PART_PROGRAM, lbl);
562
563                 return ly;
564         }
565
566         lbl = _add_slide_label(ly, progname, STYLE_LABEL_SLIDE_LEFT_32);
567         if (!lbl)
568                 goto err;
569         elm_object_part_content_set(ly, PART_PROGRAM, lbl);
570
571         lbl = _add_label(ly, STYLE_LABEL_SLIDE_LEFT_20, channel);
572         if (!lbl)
573                 goto err;
574         elm_object_part_content_set(ly, PART_CHANNEL, lbl);
575
576         lbl = _add_label(ly, STYLE_LABEL_SLIDE_LEFT_20, progtime);
577         if (!lbl)
578                 goto err;
579         elm_object_part_content_set(ly, PART_DURATION, lbl);
580
581         return ly;
582 err:
583         _ERR("failed to create label");
584         evas_object_del(ly);
585         return NULL;
586 }
587
588 static Evas_Object *_load_content_history(Evas_Object *p,
589                 const char *style, struct engine_dbar_item_content *ctnt,
590                 struct engine_dbar_item *it)
591 {
592         Evas_Object *ly;
593         const char *name;
594         Evas_Object *bg;
595
596         ly = _load_ly(p, it, style);
597         if (!ly)
598                 return NULL;
599
600         bg =  _load_bg(ly, it);
601         if (!bg) {
602                 evas_object_del(ly);
603                 return NULL;
604         }
605         elm_object_part_content_set(ly, PART_BG2, bg);
606
607         name = engine_dbar_item_get_name(it);
608         _trim((char *)name);
609         if (!name || strlen(name) <= 0)
610                 name = _(DEFAULT_TITLE);
611
612         _put_icon(ly, engine_dbar_item_get_content_icon(ctnt),
613                         PART_ICON, SIG_SHOW_DEFAULT_ICON, SRC_PROG,
614                         EINA_FALSE);
615
616         elm_object_part_text_set(ly, PART_TITLE, name);
617
618         return ly;
619 }
620
621 static Evas_Object *_load_content_common(Evas_Object *p,
622                 const char *style, struct engine_dbar_item_content *ctnt,
623                 struct engine_dbar_item *it)
624 {
625         Evas_Object *ly;
626         const char *name;
627
628         ly = _load_ly(p, it, style);
629         if (!ly)
630                 return NULL;
631
632         name = engine_dbar_item_get_name(it);
633         _trim((char *)name);
634         if (!name || strlen(name) <= 0)
635                 name = _(DEFAULT_TITLE);
636
637         _put_icon(ly, engine_dbar_item_get_content_thumbnail(ctnt),
638                         PART_THUMB, SIG_SHOW_DEFAULT_THUMB, SRC_PROG,
639                         EINA_FALSE);
640         _put_icon(ly, engine_dbar_item_get_content_icon(ctnt),
641                         PART_ICON, SIG_SHOW_DEFAULT_ICON, SRC_PROG,
642                         EINA_FALSE);
643
644         elm_object_part_text_set(ly, PART_TITLE, name);
645         elm_object_part_text_set(ly, PART_SUBTITLE, _trim((char *)
646                         engine_dbar_item_get_content_subtitle(ctnt)));
647
648         return ly;
649 }
650
651 static Evas_Object *_load_content_music(Evas_Object *p,
652                 const char *style, struct engine_dbar_item_content *ctnt,
653                 struct engine_dbar_item *it)
654 {
655         Evas_Object *ly;
656         Evas_Object *lbl;
657         const char *name;
658
659         ly = _load_ly(p, it, style);
660         if (!ly)
661                 return NULL;
662
663         name = engine_dbar_item_get_name(it);
664         _trim((char *)name);
665         if (!name || strlen(name) <= 0)
666                 name = _(DEFAULT_TITLE);
667
668         _put_icon(ly, engine_dbar_item_get_content_thumbnail(ctnt),
669                         PART_THUMB, SIG_SHOW_DEFAULT_THUMB, SRC_PROG,
670                         EINA_TRUE);
671         _put_icon(ly, engine_dbar_item_get_content_icon(ctnt),
672                         PART_ICON, SIG_SHOW_DEFAULT_ICON, SRC_PROG,
673                         EINA_FALSE);
674
675         lbl = _add_slide_label(ly, name, STYLE_LABEL_SLIDE_LEFT);
676         if (!lbl) {
677                 evas_object_del(ly);
678                 return NULL;
679         }
680         elm_object_part_content_set(ly, PART_TITLE, lbl);
681
682         elm_object_part_text_set(ly, PART_SUBTITLE, _trim((char *)
683                         engine_dbar_item_get_content_subtitle(ctnt)));
684
685         return ly;
686 }
687
688 static Evas_Object *_load_content_source(Evas_Object *p,
689                 const char *style, struct engine_dbar_item_content *ctnt,
690                 struct engine_dbar_item *it)
691 {
692         Evas_Object *ly;
693         const char *name;
694
695         ly = _load_ly(p, it, style);
696         if (!ly)
697                 return NULL;
698
699         _put_icon(ly, engine_dbar_item_get_content_thumbnail(ctnt),
700                         PART_THUMB, SIG_SHOW_DEFAULT_THUMB, SRC_PROG,
701                         EINA_FALSE);
702
703         name = engine_dbar_item_get_name(it);
704         _trim((char *)name);
705         if (!name || strlen(name) <= 0)
706                 name = _(UNKNOWN_DEVICE);
707         elm_object_part_text_set(ly, PART_TITLE, name);
708         elm_object_part_text_set(ly, PART_SUBTITLE, _trim((char *)
709                         engine_dbar_item_get_content_subtitle(ctnt)));
710
711         return ly;
712 }
713
714 static Evas_Object *_load_content_notification(Evas_Object *p,
715                 const char *style, struct engine_dbar_item_content *ctnt,
716                 struct engine_dbar_item *it)
717 {
718         Evas_Object *ly;
719         const char *title, *subtitle, *icon, *description;
720         Evas_Object *bg;
721
722         icon = engine_dbar_item_get_content_icon(ctnt);
723         title = engine_dbar_item_get_name(it);
724         subtitle = engine_dbar_item_get_content_subtitle(ctnt);
725         description = engine_dbar_item_get_content_description(ctnt);
726
727         ly = _load_ly(p, it, GRP_DBAR_NOTIFICATION);
728         if (!ly)
729                 return NULL;
730
731         bg =  _load_bg(ly, it);
732         if (!bg) {
733                 evas_object_del(ly);
734                 return NULL;
735         }
736         elm_object_part_content_set(ly, PART_BG2, bg);
737
738         if (title)
739                 elm_object_part_text_set(ly, PART_TITLE, title);
740
741         if (subtitle)
742                 elm_object_part_text_set(ly, PART_SUBTITLE, subtitle);
743
744         if (description)
745                 elm_object_part_text_set(ly, PART_DESCRIPTION, description);
746
747         if (icon)
748                 _put_icon(ly, icon, PART_THUMB,
749                                 SIG_SHOW_DEFAULT_THUMB, SRC_PROG,
750                                 EINA_FALSE);
751
752         elm_object_focus_allow_set(ly, EINA_TRUE);
753
754         return ly;
755 }
756
757 static Evas_Object *_load_content(Evas_Object *p, struct engine_dbar_item *it,
758                 Eina_Bool *fill)
759 {
760         struct engine_dbar_item_content *ctnt;
761         const Eina_List *ctnts;
762         Evas_Object *eo;
763
764         ctnts = engine_dbar_item_get_contents(it);
765         if (!ctnts)
766                 return NULL;
767
768         ctnt = eina_list_data_get(ctnts);
769         if (!ctnt)
770                 return NULL;
771
772         eo = NULL;
773         switch (engine_dbar_item_get_content_type(ctnt)) {
774         case ENGINE_DBAR_CONTENT_TYPE_IMAGE:
775         case ENGINE_DBAR_CONTENT_TYPE_VIDEO:
776                 eo = _load_content_common(p, GRP_DBAR_COMMON, ctnt, it);
777                 if (eo && fill)
778                         *fill = EINA_TRUE;
779                 break;
780         case ENGINE_DBAR_CONTENT_TYPE_BROADCAST:
781                 eo = _load_content_broadcast(p, GRP_DBAR_BROADCAST, ctnt, it);
782                 if (eo && fill)
783                         *fill = EINA_TRUE;
784                 break;
785         case ENGINE_DBAR_CONTENT_TYPE_APP:
786                 eo = _load_content_common(p, GRP_DBAR_APP, ctnt, it);
787                 if (eo && fill)
788                         *fill = EINA_TRUE;
789                 break;
790         case ENGINE_DBAR_CONTENT_TYPE_MUSIC:
791                 eo = _load_content_music(p, GRP_DBAR_MUSIC, ctnt, it);
792                 if (eo && fill)
793                         *fill = EINA_FALSE;
794                 break;
795         case ENGINE_DBAR_CONTENT_TYPE_SOURCE:
796                 eo = _load_content_source(p, GRP_DBAR_SOURCE, ctnt, it);
797                 if (eo && fill)
798                         *fill = EINA_FALSE;
799                 break;
800         case ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_ONGOING:
801         case ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_NOTI:
802                 eo = _load_content_notification(p, NULL, ctnt, it);
803                 if (eo && fill)
804                         *fill = EINA_TRUE;
805                 break;
806         case ENGINE_DBAR_CONTENT_TYPE_HISTORY:
807                 eo = _load_content_history(p, GRP_DBAR_HISTORY, ctnt, it);
808                 if (eo && fill)
809                         *fill = EINA_TRUE;
810                 break;
811         default:
812                 eo = _load_content_common(p, GRP_DBAR_COMMON, ctnt, it);
813                 if (eo && fill)
814                         *fill = EINA_TRUE;
815                 break;
816         }
817
818         return eo;
819 }
820
821 static void _img_resized(void *data, Evas *e, Evas_Object *obj, void *ei)
822 {
823         Evas_Coord w, h;
824
825         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
826         evas_object_image_fill_set(obj, 0, 0, w, h);
827 }
828
829 static Evas_Object *_load_album_thumb(Evas_Object *p, const Eina_List *ctnts)
830 {
831         Evas_Object *ly;
832         Evas_Object *ic;
833         Eina_List *l;
834         int ctnt_cnt;
835         int i;
836         const char *thumb;
837         const char *sig;
838         const char * const parts[] = {
839                 PART_THUMB_1,
840                 PART_THUMB_2,
841                 PART_THUMB_3,
842                 PART_THUMB_4,
843                 PART_THUMB_5,
844                 PART_THUMB_6
845         };
846         const char * const sig_video[] = {
847                 SIG_SHOW_THUMB1_VIDEO,
848                 SIG_SHOW_THUMB2_VIDEO,
849                 SIG_SHOW_THUMB3_VIDEO,
850                 SIG_SHOW_THUMB4_VIDEO,
851                 SIG_SHOW_THUMB5_VIDEO,
852                 SIG_SHOW_THUMB6_VIDEO
853         };
854         struct engine_dbar_item_content *ctnt;
855
856         if (!p || !ctnts) {
857                 _ERR("Invalid argument");
858                 return NULL;
859         }
860
861         ly = elm_layout_add(p);
862         if (!ly) {
863                 _ERR("icon add failed");
864                 return NULL;
865         }
866         elm_layout_file_set(ly, EDJEFILE, GRP_ALBUM_THUMB);
867
868         ctnt_cnt = eina_list_count(ctnts);
869         if (ctnt_cnt >= 6) {
870                 ctnt_cnt = 6;
871                 sig = SIG_THUMB_6;
872         } else if (ctnt_cnt >= 3) {
873                 ctnt_cnt = 3;
874                 sig = SIG_THUMB_3;
875         } else {
876                 ctnt_cnt = 1;
877                 sig = NULL;
878         }
879
880         l = (Eina_List *)ctnts;
881
882         /* TODO, show default photo/video icon */
883         for (i = 0; i < ctnt_cnt; i++) {
884                 ctnt = eina_list_data_get(l);
885                 thumb = engine_dbar_item_get_content_thumbnail(ctnt);
886                 ic = evas_object_image_add(evas_object_evas_get(ly));
887                 if (!ic) {
888                         evas_object_del(ly);
889                         return NULL;
890                 }
891                 evas_object_image_preload(ic, EINA_TRUE);
892                 evas_object_image_file_set(ic, thumb, NULL);
893                 evas_object_event_callback_add(ic, EVAS_CALLBACK_RESIZE,
894                                 _img_resized, NULL);
895                 elm_object_part_content_set(ly, parts[i], ic);
896
897                 if (engine_dbar_item_get_content_type(ctnt) ==
898                                         ENGINE_DBAR_CONTENT_TYPE_VIDEO)
899                         elm_object_signal_emit(ly, sig_video[i], SRC_PROG);
900
901                 l = eina_list_next(l);
902                 if (!l)
903                         break;
904         }
905
906         if (sig)
907                 elm_object_signal_emit(ly, sig, SRC_PROG);
908
909         return ly;
910 }
911
912 static Evas_Object *_load_album(Evas_Object *p, struct engine_dbar_item *it,
913                 Eina_Bool *fill)
914 {
915         Evas_Object *ly;
916         Evas_Object *ly2;
917         const char *name;
918
919         ly = _load_ly(p, it, GRP_DBAR_ALBUM);
920         if (!ly)
921                 return NULL;
922
923         name = engine_dbar_item_get_name(it);
924         if (!name)
925                 name = "No Title";
926
927         ly2 = _load_album_thumb(ly, engine_dbar_item_get_contents(it));
928         if (!ly2) {
929                 evas_object_del(ly);
930                 return NULL;
931         }
932
933         elm_object_part_content_set(ly, PART_THUMB, ly2);
934         elm_object_part_text_set(ly, PART_TITLE, name);
935         if (fill)
936                 *fill = EINA_TRUE;
937
938         return ly;
939 }
940
941 Evas_Object *_item_load(Evas_Object *p, struct engine_dbar_item *it,
942                 Eina_Bool *fill, Eina_Bool *focus)
943 {
944         static struct _dbar_item_loader loaders[] = {
945                 {
946                         .style = ENGINE_DBAR_ITEM_STYLE_CONTENT,
947                         .loader = _load_content
948                 },
949                 {
950                         .style = ENGINE_DBAR_ITEM_STYLE_LABEL,
951                         .loader = _load_title
952                 },
953                 {
954                         .style = ENGINE_DBAR_ITEM_STYLE_ALBUM,
955                         .loader = _load_album
956                 },
957         };
958         Evas_Object *eo;
959         enum engine_dbar_item_style style;
960         int i;
961
962         if (!it) {
963                 _ERR("Invalid argument");
964                 return NULL;
965         }
966
967         style = engine_dbar_item_get_style(it);
968         if (style >= ENGINE_DBAR_ITEM_STYLE_MAX)
969                 style = ENGINE_DBAR_ITEM_STYLE_CONTENT;
970
971         for (i = 0; i < sizeof(loaders) / sizeof(*loaders); i++) {
972                 if (loaders[i].style == style) {
973                         eo = loaders[i].loader(p, it, fill);
974                         if (!eo)
975                                 return NULL;
976
977                         if (style == ENGINE_DBAR_ITEM_STYLE_LABEL)
978                                 *focus = EINA_FALSE;
979                         else
980                                 *focus = EINA_TRUE;
981
982                         return eo;
983                 }
984         }
985
986         _ERR("cannot find style: %d", style);
987
988         return NULL;
989 }
990
991 static int _add_bar(struct bar_info *info, Evas_Object *base)
992 {
993         Evas_Object *ly, *scr, *tbl, *bx;
994         struct _dbar_data *bar;
995         int padding;
996
997         if (!base || !info || !info->data) {
998                 _ERR("Invalid argument");
999                 return -1;
1000         }
1001
1002         bar = info->data;
1003         padding = elm_config_scale_get() * DBAR_PADDING;
1004
1005         ly = elm_layout_add(base);
1006         if (!ly) {
1007                 _ERR("layout add failed");
1008                 return -1;
1009         }
1010         elm_layout_file_set(ly, EDJEFILE, GRP_DBAR_ITEM);
1011
1012         scr = elm_scroller_add(ly);
1013         if (!scr) {
1014                 _ERR("scroller add failed");
1015                 evas_object_del(ly);
1016                 return -1;
1017         }
1018         elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF,
1019                         ELM_SCROLLER_POLICY_OFF);
1020
1021         bx = elm_box_add(scr);
1022         if (!bx) {
1023                 _ERR("box add failed");
1024                 evas_object_del(ly);
1025                 return -1;
1026         }
1027
1028         tbl = elm_table_add(bx);
1029         if (!tbl) {
1030                 _ERR("table add failed");
1031                 evas_object_del(ly);
1032                 return -1;
1033         }
1034
1035         evas_object_size_hint_align_set(tbl, 0.5, 0.0);
1036         evas_object_size_hint_weight_set(tbl, EVAS_HINT_EXPAND,
1037                         EVAS_HINT_EXPAND);
1038         elm_table_homogeneous_set(tbl, EINA_FALSE);
1039         elm_table_padding_set(tbl, padding, padding);
1040
1041         evas_object_show(tbl);
1042         evas_object_show(bx);
1043         elm_box_pack_end(bx, tbl);
1044         elm_object_content_set(scr, bx);
1045         elm_object_part_content_set(ly, PART_CONTENT, scr);
1046
1047         bar->base = base;
1048         bar->ly = ly;
1049         bar->scr = scr;
1050         bar->tbl = tbl;
1051
1052         return 0;
1053 }
1054
1055 static inline int _get_dbar_row_col(struct _dbar_data *bar,
1056                 Eina_Bool fill, int *row, int *col)
1057 {
1058         int r;
1059
1060         if (!bar || !row || !col || bar->content_column <= 0)
1061                 return -1;
1062
1063         *row = bar->tbl_idx / bar->content_column;
1064         *col = bar->tbl_idx % bar->content_column;
1065
1066         if (!fill)
1067                 return 1;
1068
1069         if (bar->content_column > 1 && *col > 0) {
1070                 *col = 0;
1071                 *row = *row + 1;
1072         }
1073         r = bar->content_column - *col;
1074
1075         return r;
1076 }
1077
1078 static Eina_Bool _xbar_focused(void *data, Evas_Object *foc)
1079 {
1080         struct _dbar_data *bar;
1081         struct _dbar_item *cur;
1082
1083         if (!data || !foc) {
1084                 _ERR("Invalid argument");
1085                 return EINA_FALSE;
1086         }
1087
1088         bar = data;
1089         if (!bar->cur) {
1090                 _ERR("There is no dbar item");
1091                 return EINA_FALSE;
1092         }
1093         cur = bar->cur;
1094
1095         switch (bar->state) {
1096         case DBAR_STATE_DBAR:
1097                 elm_object_signal_emit(foc, SIG_INITIAL_FOCUS, SRC_PROG);
1098                 elm_object_signal_emit(cur->eo, SIG_UNFOCUS_TO_XBAR,
1099                                 SRC_PROG);
1100                 break;
1101         default:
1102                 return EINA_FALSE;
1103         }
1104
1105         bar->state = DBAR_STATE_XBAR;
1106
1107         return EINA_TRUE;
1108 }
1109
1110 static int _init_child_bars(struct _dbar_item *item)
1111 {
1112         struct bar_info *xbar;
1113         int r;
1114
1115         if (!item) {
1116                 _ERR("Invalid argument");
1117                 return -1;
1118         }
1119
1120         xbar = calloc(1, sizeof(*xbar));
1121         if (!xbar) {
1122                 _ERR("failed to calloc xbar");
1123                 return -1;
1124         }
1125
1126         xbar->cb.func = _xbar_focused;
1127         xbar->cb.data = item->bar;
1128
1129         r = init_delete_bar(xbar);
1130         if (r < 0) {
1131                 free(xbar);
1132                 return -1;
1133         }
1134
1135         item->xbar = xbar;
1136
1137         return 0;
1138 }
1139
1140 static void _unfocused(void *data, Evas_Object *obj, const char *emission,
1141                 const char *source)
1142 {
1143         struct _dbar_item *cur;
1144         struct _dbar_data *bar;
1145
1146         if (!data) {
1147                 _ERR("Invalid argument");
1148                 return;
1149         }
1150
1151         cur = data;
1152         bar = cur->bar;
1153
1154         bar->state = DBAR_STATE_HIDE;
1155
1156         if (!cur->xbar)
1157                 return;
1158
1159         cur->xbar->ops->hide(cur->xbar);
1160 }
1161
1162 static void _cancel_delete_popup(void *data, Evas_Object *obj,
1163                 const char *emission, const char *source)
1164 {
1165         struct _dbar_item *cur;
1166
1167         if (!data) {
1168                 _ERR("Invalid argument");
1169                 return;
1170         }
1171
1172         cur = data;
1173
1174         if (cur->eo)
1175                 elm_object_focus_set(cur->eo, EINA_TRUE);
1176 }
1177
1178 static struct _dbar_item *_pack_item(struct _dbar_data *bar,
1179                 struct engine_dbar_item *it)
1180 {
1181         Evas_Object *eo;
1182         struct _dbar_item *item;
1183         Eina_Bool fill;
1184         Eina_Bool focus;
1185         int row, col;
1186         int step;
1187         int r;
1188         enum engine_dbar_content_type type;
1189         struct engine_dbar_item_content *ctnt;
1190
1191         if (!bar || !it)
1192                 return NULL;
1193
1194         item = calloc(1, sizeof(*item));
1195         if (!item) {
1196                 _ERR("Calloc failed");
1197                 return NULL;
1198         }
1199
1200         fill = EINA_FALSE;
1201         focus = EINA_FALSE;
1202
1203         eo = _item_load(bar->tbl, it, &fill, &focus);
1204         if (!eo) {
1205                 free(item);
1206                 return NULL;
1207         }
1208
1209         step = _get_dbar_row_col(bar, fill, &row, &col);
1210         if (step <= 0) {
1211                 evas_object_del(eo);
1212                 free(item);
1213                 return NULL;
1214         }
1215
1216         evas_object_size_hint_align_set(eo, EVAS_HINT_FILL, 0.0);
1217         elm_table_pack(bar->tbl, eo, col, row,
1218                         fill ? bar->content_column : 1, 1);
1219         evas_object_show(eo);
1220
1221         bar->tbl_idx += step;
1222         bar->state = DBAR_STATE_HIDE;
1223         item->eo = eo;
1224         item->it = it;
1225         item->bar = bar;
1226         item->focus = focus;
1227
1228         evas_object_event_callback_add(eo,
1229                         EVAS_CALLBACK_MOUSE_MOVE, _mouse_over, item);
1230         evas_object_event_callback_add(eo,
1231                         EVAS_CALLBACK_MOUSE_UP, _clicked, item);
1232         evas_object_smart_callback_add(eo, "focused", _focused, item);
1233         elm_object_signal_callback_add(eo, SIG_UNFOCUS_TO_HBAR, SRC_PROG,
1234                         _unfocused, item);
1235
1236         ctnt = eina_list_data_get(engine_dbar_item_get_contents(it));
1237         if (!ctnt) {
1238                 _ERR("failed to get ci");
1239                 return item;
1240         }
1241
1242         type = engine_dbar_item_get_content_type(ctnt);
1243         if ((type == ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_NOTI ||
1244                                 type == ENGINE_DBAR_CONTENT_TYPE_HISTORY) &&
1245                                 item->focus) {
1246                 r = _init_child_bars(item);
1247                 if (r < 0) {
1248                         free(item->xbar);
1249                         item->xbar = NULL;
1250                 }
1251
1252                 r = item->xbar->ops->add_bar(item->xbar, bar->base);
1253                 if (r < 0) {
1254                         item->xbar->ops->release(item->xbar);
1255                         free(item->xbar);
1256                         item->xbar = NULL;
1257                 }
1258
1259                 eo = item->xbar->ops->get_object(item->xbar);
1260                 if (eo)
1261                         elm_object_signal_callback_add(eo,
1262                                         SIG_CANCEL_CLICKED,
1263                                         SRC_PROG, _cancel_delete_popup, item);
1264         }
1265
1266         return item;
1267 }
1268
1269 static int _update(struct bar_info *info, void *eng, void *data)
1270 {
1271         struct _dbar_data *bar;
1272         const Eina_List *list;
1273         Eina_List *l;
1274         struct engine_dbar_item *it;
1275         struct _dbar_item *item;
1276         const char *noctnt_title;
1277         const char *noctnt_desc;
1278         int cnt;
1279
1280         if (!info || !info->data) {
1281                 _ERR("Invalid argument");
1282                 return -1;
1283         }
1284
1285         bar = info->data;
1286
1287         elm_table_clear(bar->tbl, EINA_TRUE);
1288         bar->tbl_idx = 0;
1289
1290         EINA_LIST_FREE(bar->list, item) {
1291                 if (item->xbar)
1292                         item->xbar->ops->release(item->xbar);
1293
1294                 evas_object_del(item->eo);
1295                 free(item);
1296         }
1297         bar->cur = NULL;
1298         bar->list = NULL;
1299
1300         engine_bar_item_get_content_column(eng, &bar->content_column);
1301
1302         cnt = 0;
1303         list = engine_get_dbar_items(eng);
1304         if (!list) {
1305                 noctnt_title = engine_bar_item_get_noctnt_title(eng);
1306                 noctnt_desc = engine_bar_item_get_noctnt_desc(eng);
1307                 elm_object_part_text_set(bar->ly,
1308                                 PART_DEFAULT_TITLE,
1309                                 noctnt_title ? noctnt_title : "");
1310                 elm_object_part_text_set(bar->ly,
1311                                 PART_DEFAULT_DESC,
1312                                 noctnt_desc ? noctnt_desc : "");
1313                 return cnt;
1314         }
1315         elm_object_part_text_set(bar->ly, PART_DEFAULT_TITLE, "");
1316         elm_object_part_text_set(bar->ly, PART_DEFAULT_DESC, "");
1317
1318         EINA_LIST_FOREACH((Eina_List *)list, l, it) {
1319                 item = _pack_item(bar, it);
1320                 if (!item)
1321                         continue;
1322
1323                 bar->list = eina_list_append(bar->list, item);
1324                 cnt++;
1325         }
1326
1327         return cnt;
1328 }
1329
1330 static Evas_Object *_get_object(struct bar_info *info)
1331 {
1332         struct _dbar_data *bar;
1333
1334         if (!info || !info->data) {
1335                 _ERR("Invalid argument");
1336                 return NULL;
1337         }
1338
1339         bar = info->data;
1340
1341         return bar->ly;
1342 }
1343
1344 static Evas_Object *_get_item(struct bar_info *info)
1345 {
1346         struct _dbar_data *bar;
1347         struct _dbar_item *item;
1348         Eina_List *l;
1349
1350         if (!info || !info->data) {
1351                 _ERR("Invalid argument");
1352                 return NULL;
1353         }
1354
1355         bar = info->data;
1356         if (bar->cur)
1357                 return bar->cur->eo;
1358
1359         EINA_LIST_FOREACH(bar->list, l, item) {
1360                 if (elm_object_focus_allow_get(item->eo)) {
1361                         bar->cur = item;
1362                         return bar->cur->eo;
1363                 }
1364         }
1365
1366         return NULL;
1367 }
1368
1369 static void _show(struct bar_info *info)
1370 {
1371         struct _dbar_data *bar;
1372         struct _dbar_item *item;
1373         Eina_List *l;
1374
1375         if (!info || !info->data) {
1376                 _ERR("Invalid argument");
1377                 return;
1378         }
1379
1380         bar = info->data;
1381
1382         EINA_LIST_FOREACH(bar->list, l, item) {
1383                 if (item->focus)
1384                         elm_object_focus_allow_set(item->eo, EINA_TRUE);
1385         }
1386         elm_object_signal_emit(bar->ly, SIG_SHOW, SRC_PROG);
1387 }
1388
1389 static void _hide(struct bar_info *info)
1390 {
1391         struct _dbar_data *bar;
1392         struct _dbar_item *item;
1393         Eina_List *l;
1394
1395         if (!info || !info->data) {
1396                 _ERR("Invalid argument");
1397                 return;
1398         }
1399
1400         bar = info->data;
1401
1402         EINA_LIST_FOREACH(bar->list, l, item) {
1403                 elm_object_signal_emit(item->eo, SIG_HIDE, SRC_PROG);
1404                 elm_object_focus_allow_set(item->eo, EINA_FALSE);
1405
1406                 if (item->xbar)
1407                         item->xbar->ops->hide(item->xbar);
1408         }
1409         elm_object_signal_emit(bar->ly, SIG_HIDE, SRC_PROG);
1410 }
1411
1412 static Eina_Bool _is_move(struct bar_info *info, int dir)
1413 {
1414         struct _dbar_data *bar;
1415         struct _dbar_item *item;
1416         struct _dbar_item *_item;
1417         Eina_List *l;
1418         int x;
1419
1420         if (!info || !info->data) {
1421                 _ERR("Invalid argument");
1422                 return EINA_FALSE;
1423         }
1424
1425         bar = info->data;
1426         item = bar->cur;
1427
1428         if (!item)
1429                 return EINA_FALSE;
1430
1431         if (bar->content_column == 1)
1432                 return EINA_TRUE;
1433
1434         elm_table_pack_get(item->eo, &x, NULL, NULL, NULL);
1435
1436         switch (dir) {
1437         case BAR_DIR_LEFT:
1438                 if (x > 0)
1439                         return EINA_FALSE;
1440                 break;
1441         case BAR_DIR_RIGHT:
1442                 if (x > 0)
1443                         return EINA_TRUE;
1444
1445                 l = eina_list_last(bar->list);
1446                 _item = eina_list_data_get(l);
1447                 if (item->eo != _item->eo)
1448                         return EINA_FALSE;
1449                 break;
1450         default:
1451                 return EINA_FALSE;
1452         }
1453
1454         return EINA_TRUE;
1455 }
1456
1457 static Eina_Bool _move(struct bar_info *info)
1458 {
1459         struct _dbar_data *bar;
1460         struct _dbar_item *item;
1461         Eina_List *l;
1462
1463         if (!info || !info->data) {
1464                 _ERR("Invalid argument");
1465                 return EINA_FALSE;
1466         }
1467
1468         bar = info->data;
1469         item = bar->cur;
1470
1471         if (!item) {
1472                 EINA_LIST_FOREACH(bar->list, l, item) {
1473                         if (elm_object_focus_allow_get(item->eo))
1474                                 break;
1475                 }
1476
1477                 if (!item)
1478                         return EINA_FALSE;
1479         }
1480
1481         elm_object_focus_set(item->eo, EINA_TRUE);
1482
1483         return EINA_TRUE;
1484 }
1485
1486 static enum bar_event _enter(struct bar_info *info)
1487 {
1488         Eina_Bool r;
1489         struct _dbar_data *bar;
1490
1491         if (!info) {
1492                 _ERR("Invalid argument");
1493                 return BAR_EVENT_ERROR;
1494         }
1495
1496         bar = info->data;
1497         r = EINA_FALSE;
1498
1499         switch (bar->state) {
1500         case DBAR_STATE_DBAR:
1501                 r = _launch_app(info);
1502                 break;
1503         default:
1504                 return BAR_EVENT_DONE;
1505         }
1506
1507         return r ? BAR_EVENT_DONE : BAR_EVENT_PASS;
1508 }
1509
1510 static enum bar_event _move_right(struct bar_info *info)
1511 {
1512         Eina_Bool r;
1513         struct _dbar_data *bar;
1514
1515         if (!info) {
1516                 _ERR("Invalid argument");
1517                 return BAR_EVENT_ERROR;
1518         }
1519
1520         bar = info->data;
1521         r = EINA_FALSE;
1522
1523         switch (bar->state) {
1524         case DBAR_STATE_DBAR:
1525                 if (_is_move(info, BAR_DIR_RIGHT)) {
1526                         if (bar->cur->xbar)
1527                                 r = bar->cur->xbar->ops->move(bar->cur->xbar);
1528                 }
1529                 break;
1530         default:
1531                 return BAR_EVENT_ERROR;
1532         }
1533
1534         return r ? BAR_EVENT_DONE : BAR_EVENT_PASS;
1535 }
1536
1537 static enum bar_event _move_left(struct bar_info *info)
1538 {
1539         struct _dbar_data *bar;
1540
1541         if (!info) {
1542                 _ERR("Invalid argument");
1543                 return BAR_EVENT_ERROR;
1544         }
1545
1546         bar = info->data;
1547
1548         switch (bar->state) {
1549         case DBAR_STATE_XBAR:
1550                 break;
1551         case DBAR_STATE_DBAR:
1552                 if (_is_move(info, BAR_DIR_LEFT)) {
1553                         if (bar->cur->xbar) {
1554                                 bar->cur->xbar->ops->hide(bar->cur->xbar);
1555                                 bar->state = DBAR_STATE_HIDE;
1556                         }
1557                         return BAR_EVENT_MOVE;
1558                 }
1559                 break;
1560         default:
1561                 return BAR_EVENT_ERROR;
1562         }
1563
1564         return BAR_EVENT_PASS;
1565 }
1566
1567 static enum bar_event _key_event(struct bar_info *info, void *ei)
1568 {
1569         Ecore_Event_Key *ev;
1570         enum bar_event r;
1571
1572         if (!info || !ei)
1573                 return BAR_EVENT_ERROR;
1574
1575         ev = ei;
1576
1577         if (!strcmp(ev->keyname, KEY_ENTER))
1578                 r = _enter(info);
1579         else if (!strcmp(ev->keyname, KEY_RIGHT))
1580                 r = _move_right(info);
1581         else if (!strcmp(ev->keyname, KEY_LEFT) ||
1582                         !strcmp(ev->keyname, KEY_BACK))
1583                 r = _move_left(info);
1584         else
1585                 r = BAR_EVENT_PASS;
1586
1587         return r;
1588 }
1589
1590 static enum bar_event _bar_event(struct bar_info *info, void *ei,
1591                 enum bar_event ev)
1592 {
1593         struct _dbar_data *bar;
1594         enum bar_event r;
1595
1596         if (!info || !ei)
1597                 return BAR_EVENT_ERROR;
1598
1599         bar = info->data;
1600
1601         switch (ev) {
1602         case BAR_EVENT_DONE:
1603         case BAR_EVENT_ERROR:
1604                 return ev;
1605         case BAR_EVENT_PASS:
1606                 r = _key_event(info, ei);
1607                 break;
1608         case BAR_EVENT_MOVE:
1609                 if (bar->state == DBAR_STATE_XBAR)
1610                         _move(info);
1611                 r = BAR_EVENT_DONE;
1612                 break;
1613         default:
1614                 r = BAR_EVENT_PASS;
1615                 break;
1616         }
1617
1618         return r;
1619 }
1620
1621 static enum bar_event _key_down(struct bar_info *info, void *ei)
1622 {
1623         struct _dbar_data *bar;
1624         struct _dbar_item *item;
1625         enum bar_event r;
1626
1627         if (!info || !ei)
1628                 return BAR_EVENT_ERROR;
1629
1630         bar = info->data;
1631         item = bar->cur;
1632
1633         if (!item)
1634                 return BAR_EVENT_ERROR;
1635
1636         r = BAR_EVENT_PASS;
1637
1638         switch (bar->state) {
1639         case DBAR_STATE_HIDE:
1640         case DBAR_STATE_DBAR:
1641                 r = BAR_EVENT_PASS;
1642                 break;
1643         case DBAR_STATE_XBAR:
1644                 if (!bar->cur->xbar)
1645                         break;
1646
1647                 r = bar->cur->xbar->ops->key_down(bar->cur->xbar, ei);
1648                 break;
1649         default:
1650                 return BAR_EVENT_ERROR;
1651         }
1652
1653         return _bar_event(info, ei, r);
1654 }
1655
1656 static void _release(struct bar_info *info)
1657 {
1658         struct _dbar_data *bar;
1659         struct _dbar_item *item;
1660
1661         if (!info) {
1662                 _ERR("Invalid argument");
1663                 return;
1664         }
1665
1666         bar = info->data;
1667
1668         _hide(info);
1669
1670         if (bar) {
1671                 EINA_LIST_FREE(bar->list, item) {
1672                         if (item->xbar)
1673                                 item->xbar->ops->release(item->xbar);
1674
1675                         evas_object_del(item->eo);
1676                         free(item);
1677                 }
1678                 evas_object_del(bar->ly);
1679                 free(bar);
1680                 bar = NULL;
1681         }
1682
1683         free(info);
1684         info = NULL;
1685 }
1686
1687 static struct bar_ops dbar_ops = {
1688         .add_bar        = _add_bar,
1689         .update         = _update,
1690         .get_object     = _get_object,
1691         .get_item       = _get_item,
1692         .is_move        = _is_move,
1693         .move           = _move,
1694         .show           = _show,
1695         .hide           = _hide,
1696         .key_down       = _key_down,
1697         .release        = _release,
1698 };
1699
1700 int init_dynamic_bar(struct bar_info *info)
1701 {
1702         struct _dbar_data *bar;
1703
1704         if (!info)
1705                 return -1;
1706
1707         bar = calloc(1, sizeof(*bar));
1708         if (!bar) {
1709                 _ERR("calloc failed");
1710                 return -1;
1711         }
1712
1713         info->data = bar;
1714         info->ops = &dbar_ops;
1715
1716         if (!info->cb.func) {
1717                 _ERR("invalid callback function");
1718                 free(bar);
1719                 return -1;
1720         }
1721
1722         bar->focus_cb = info->cb;
1723
1724         return 0;
1725 }