modify password error handling to set two cases
[profile/tv/apps/native/homescreen.git] / src / ubar.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
21 #include "i18n.h"
22 #include "bar.h"
23 #include "engine.h"
24 #include "defs.h"
25 #include "dbg.h"
26
27 #define BTN_MAX 3
28 #define UBAR_POPUP_PADDING_X 30
29 #define BUF_MAX 128
30 #define UBAR_ITEM_MAX 3
31 #define UBAR_ITEM_WIDTH 180
32
33 #define MESSAGE_ID "ID"
34 #define MESSAGE_PW "Password"
35 #define MESSAGE_WRONG_PW "Wrong Password"
36 #define TITLE_DELETE_POPUP "Delete User"
37 #define TITLE_ADD_POPUP "Add User"
38 #define TITLE_LOGIN_POPUP "Login"
39 #define TITLE_EDIT_POPUP "Edit User"
40 #define MESSAGE_DELETE_POPUP "Are you sure you want to delete"
41
42 #define USER_NAME_GUEST "guest"
43 #define USER_NAME_OWNER "owner"
44
45 #define ASSERT(exp) if (!(exp)) { _ERR(#exp); abort(); }
46
47 enum _ubar_state {
48         UBAR_STATE_HIDE,
49         UBAR_STATE_USER,
50         UBAR_STATE_ITEM,
51         UBAR_STATE_USER_CTXPOPUP,
52         UBAR_STATE_ITEM_CTXPOPUP,
53         UBAR_STATE_USER_POPUP,
54         UBAR_STATE_ITEM_POPUP
55 };
56
57 enum _popup_state {
58         POPUP_STATE_NONE,
59         POPUP_STATE_LOGIN,
60         POPUP_STATE_ADD,
61         POPUP_STATE_EDIT,
62         POPUP_STATE_DELETE
63 };
64
65 struct _ubar_item;
66
67 struct _ubar_data {
68         struct _ubar_item *user;
69         Evas_Object *ly;
70         Evas_Object *scr;
71         Evas_Object *bx;
72         Eina_List *list;
73         Evas_Object *base;
74         struct engine *eng;
75         struct _ubar_item *cur;
76         struct _ubar_item *popup_cur;
77         struct bar_cb focus_cb;
78         enum _ubar_state state;
79         Eina_List *popup_list;
80         Evas_Object *popup_scr;
81         Evas_Object *popup_box;
82         Evas_Object *arrow;
83 };
84
85 struct _ubar_item {
86         Evas_Object *eo;
87         Evas_Object *ic_bg;
88         Evas_Object *ic;
89         Evas_Object *ctxpopup;
90         Evas_Object *btn[BTN_MAX];
91         Evas_Object *popup;
92         Evas_Object *id_entry;
93         Evas_Object *pw_entry;
94         Evas_Object *left_arrow;
95         Evas_Object *right_arrow;
96         struct engine_ubar_item *it;
97         struct _ubar_data *bar;
98         enum _popup_state state;
99         bool is_user;
100 };
101
102 struct _btn_info {
103         const char *part;
104         const char *text;
105         void (*click_cb)(void *, Evas *, Evas_Object *, void *);
106 };
107
108 static const char *icon_path[] = {
109        IMAGEDIR"/ico_family_mini.png",
110        IMAGEDIR"/ico_man.png",
111        IMAGEDIR"/ico_woman_mini.png",
112        IMAGEDIR"/ico_grandfather_mini.png",
113        IMAGEDIR"/ico_grandmother_mini.png",
114        IMAGEDIR"/ico_boy_mini.png",
115        IMAGEDIR"/ico_girl_mini.png"
116 };
117
118 static void _update_arrow(Evas_Object *scr, Evas_Object *left_arrow,
119                 Evas_Object *right_arrow)
120 {
121         Evas_Coord rx, ry, rw, rh, cw;
122
123         if (!scr || !left_arrow || !right_arrow) {
124                 _ERR("Invalid argument");
125                 return;
126         }
127
128         elm_scroller_region_get(scr, &rx, &ry, &rw, &rh);
129         elm_scroller_child_size_get(scr, &cw, NULL);
130
131         if (cw  <= rw)
132                 return;
133
134         if (rx == 0) {
135                 elm_object_signal_emit(left_arrow, SIG_SHOW_ARROW, SRC_PROG);
136                 elm_object_signal_emit(right_arrow, SIG_HIDE_ARROW, SRC_PROG);
137         } else if (rx + rw == cw) {
138                 elm_object_signal_emit(left_arrow, SIG_HIDE_ARROW, SRC_PROG);
139                 elm_object_signal_emit(right_arrow, SIG_SHOW_ARROW, SRC_PROG);
140         } else {
141                 elm_object_signal_emit(left_arrow, SIG_SHOW_ARROW, SRC_PROG);
142                 elm_object_signal_emit(right_arrow, SIG_SHOW_ARROW, SRC_PROG);
143         }
144 }
145
146 static void _scroll_cb(void *data, Evas_Object *obj,
147                 const char *emission, const char *source)
148 {
149         struct _ubar_data *bar;
150
151         if (!data) {
152                 _ERR("Invalid arguement");
153                 return;
154         }
155
156         bar = data;
157
158         switch (bar->state) {
159         case UBAR_STATE_ITEM:
160                 _update_arrow(bar->scr, bar->arrow, bar->ly);
161                 break;
162         case UBAR_STATE_ITEM_POPUP:
163                 if (bar->cur->state == POPUP_STATE_ADD ||
164                                 bar->cur->state == POPUP_STATE_EDIT)
165                         _update_arrow(bar->popup_scr, bar->cur->right_arrow,
166                                         bar->cur->left_arrow);
167                 break;
168         default:
169                 return;
170         }
171 }
172
173 static void _focused(void *data, Evas_Object *obj, void *ei)
174 {
175         struct _ubar_data *bar;
176         struct _ubar_item *foc;
177
178         if (!data) {
179                 _ERR("Invalid argument");
180                 return;
181         }
182
183         foc = data;
184         bar = foc->bar;
185
186         bar->focus_cb.func(bar->focus_cb.data, foc->eo);
187
188         switch (bar->state) {
189         case UBAR_STATE_HIDE:
190                 elm_object_signal_emit(bar->user->eo,
191                                 SIG_FOCUS_FROM_DOWN, SRC_PROG);
192                 bar->state = UBAR_STATE_USER;
193                 break;
194         case UBAR_STATE_USER:
195                 elm_object_signal_emit(bar->user->eo, SIG_HIGHLIGHT, SRC_PROG);
196                 bar->state = UBAR_STATE_ITEM;
197                 break;
198         case UBAR_STATE_ITEM:
199                 if (foc == bar->user) {
200                         elm_object_signal_emit(bar->user->eo,
201                                         SIG_FOCUS_FROM_RIGHT, SRC_PROG);
202                         bar->state = UBAR_STATE_USER;
203                 }
204                 break;
205         default:
206                 break;
207         }
208
209         bar->cur = foc;
210 }
211
212 static void _mouse_over(void *data, Evas *e, Evas_Object *obj, void *ei)
213 {
214         if (!obj) {
215                 _ERR("Invalid argument");
216                 return;
217         }
218
219         if (elm_object_focus_get(obj))
220                 return;
221
222         elm_object_focus_set(obj, EINA_TRUE);
223 }
224
225 static int _add_init_user(struct _ubar_data *bar, Evas_Object *base)
226 {
227         struct _ubar_item *item;
228         Evas_Object *ly, *ic_bg, *ic;
229
230         if (!bar || !base) {
231                 _ERR("Invalid argument");
232                 return -1;
233         }
234
235         item = calloc(1, sizeof(*item));
236         if (!item) {
237                 _ERR("calloc failed");
238                 return -1;
239         }
240
241         ly = elm_layout_add(base);
242         if (!ly) {
243                 _ERR("layout add failed");
244                 free(item);
245                 return -1;
246         }
247         elm_layout_file_set(ly, EDJEFILE, GRP_USER);
248
249         ic_bg = elm_icon_add(ly);
250         if (!ic_bg) {
251                 _ERR("image add failed");
252                 evas_object_del(ly);
253                 free(item);
254                 return -1;
255         }
256         elm_object_part_content_set(ly, PART_USER_THUMB_BG, ic_bg);
257
258         ic = elm_icon_add(ly);
259         if (!ic) {
260                 _ERR("image add failed");
261                 evas_object_del(ly);
262                 free(item);
263                 return -1;
264         }
265         elm_object_part_content_set(ly, PART_USER_THUMB, ic);
266         elm_object_part_content_set(base, PART_USER, ly);
267
268         evas_object_event_callback_add(ly,
269                         EVAS_CALLBACK_MOUSE_MOVE, _mouse_over, NULL);
270         evas_object_smart_callback_add(ly, "focused", _focused, item);
271
272         item->eo = ly;
273         item->ic_bg = ic_bg;
274         item->ic = ic;
275         item->bar = bar;
276
277         bar->user = item;
278
279         return 0;
280 }
281
282 static void _arrow_clicked(void *data, Evas_Object *obj,
283                 const char *emission, const char *source)
284 {
285         struct _ubar_data *bar;
286         Evas_Coord rx, ry, rw, rh, cw;
287
288         if (!data) {
289                 _ERR("Invalid argument");
290                 return;
291         }
292
293         bar = data;
294
295         elm_scroller_region_get(bar->scr, &rx, &ry, &rw, &rh);
296         elm_scroller_child_size_get(bar->scr, &cw, NULL);
297
298         if (cw <= rw)
299                 return;
300
301         if (obj == bar->arrow)
302                 rx = rx + UBAR_ITEM_WIDTH;
303         else
304                 rx = rx - UBAR_ITEM_WIDTH;
305
306         elm_scroller_region_bring_in(bar->scr, rx, ry, rw, rh);
307         _update_arrow(bar->scr, bar->ly, bar->arrow);
308 }
309
310 static int _add_items(struct _ubar_data *bar, Evas_Object *base)
311 {
312         Evas_Object *ly, *scr, *bx;
313
314         if (!bar || !base) {
315                 _ERR("Invalid argument");
316                 return -1;
317         }
318
319         ly = elm_layout_add(base);
320         if (!ly) {
321                 _ERR("layout add failed");
322                 return -1;
323         }
324         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR);
325
326         scr = elm_scroller_add(ly);
327         if (!scr) {
328                 _ERR("scroller add failed");
329                 evas_object_del(ly);
330                 return -1;
331         }
332         elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF,
333                         ELM_SCROLLER_POLICY_OFF);
334         elm_object_signal_callback_add(scr, SIG_SCROLL_RIGHT, SRC_ELM,
335                         _scroll_cb, bar);
336         elm_object_signal_callback_add(scr, SIG_SCROLL_LEFT, SRC_ELM,
337                         _scroll_cb, bar);
338
339         bx = elm_box_add(scr);
340         if (!bx) {
341                 _ERR("box add failed");
342                 evas_object_del(ly);
343                 return -1;
344         }
345         evas_object_size_hint_align_set(bx, 0.0, EVAS_HINT_FILL);
346         evas_object_size_hint_weight_set(bx, 0.0, EVAS_HINT_EXPAND);
347         elm_box_horizontal_set(bx, EINA_TRUE);
348
349         elm_object_part_content_set(ly, PART_UBAR_CONTENT, scr);
350
351         evas_object_show(bx);
352         elm_object_content_set(scr, bx);
353
354         elm_object_signal_callback_add(ly, SIG_ARROW_CLICKED, SRC_EDJE,
355                         _arrow_clicked, bar);
356         elm_object_part_content_set(base, PART_UBAR, ly);
357
358         bar->ly = ly;
359         bar->scr = scr;
360         bar->bx = bx;
361         bar->base = base;
362
363         return 0;
364 }
365
366 static int _add_bar(struct bar_info *info, Evas_Object *base)
367 {
368         struct _ubar_data *bar;
369         int r;
370
371         if (!info || !info->data || !base) {
372                 _ERR("Invalid argument");
373                 return -1;
374         }
375
376         bar = info->data;
377
378         r = _add_init_user(bar, base);
379         if (r < 0)
380                 return -1;
381
382         r = _add_items(bar, base);
383         if (r < 0)
384                 return -1;
385
386         return 0;
387 }
388
389 static int _update_user(struct _ubar_data *bar, struct engine *eng)
390 {
391         struct _ubar_item *item;
392         const char *thumb_bg;
393         const char *thumb;
394         const char *name;
395
396         if (!bar || !eng) {
397                 _ERR("Invalid argument");
398                 return -1;
399         }
400
401         item = bar->user;
402
403         name = NULL;
404         thumb_bg = NULL;
405         thumb = NULL;
406
407         engine_get_user_info(eng, &name, &thumb_bg, &thumb);
408         elm_image_file_set(item->ic_bg,
409                         thumb_bg ? thumb_bg : DEF_USER_THUMB_BG, NULL);
410         elm_image_file_set(item->ic,
411                         thumb ? thumb : DEF_USER_THUMB, NULL);
412         elm_object_part_text_set(item->eo,
413                         PART_USER_NAME, name ? name : DEF_USER_NAME);
414
415         return 0;
416 }
417
418 static Eina_Bool _create_ctxpopup(struct _ubar_item *);
419
420 /* FIXME: check user status */
421 static Eina_Bool _check_guest_user(struct _ubar_item *user)
422 {
423         return EINA_TRUE;
424 }
425
426 static Eina_Bool _load_add_popup(struct _ubar_item *item);
427
428 static void _clicked(void *data, Evas *e, Evas_Object *obj, void *ei)
429 {
430         struct _ubar_data *bar;
431
432         if (!data) {
433                 _ERR("Invalid argument");
434                 return;
435         }
436
437         bar = data;
438         if (_check_guest_user(bar->user)) {
439                 if (!bar->cur->is_user){
440                         _load_add_popup(bar->cur);
441                         elm_object_signal_emit(bar->cur->eo,
442                                         SIG_HLIGHT_FROM_POPOVER,
443                                         SRC_PROG);
444                         bar->state = UBAR_STATE_ITEM_POPUP;
445                 } else {
446                         _create_ctxpopup(bar->cur);
447                         bar->state = UBAR_STATE_ITEM_CTXPOPUP;
448                 }
449         }
450 }
451
452 static void _lbl_start_slide(void *data, Evas_Object *obj, void *ei)
453 {
454         elm_label_ellipsis_set(data, EINA_FALSE);
455         elm_label_slide_mode_set(data, ELM_LABEL_SLIDE_MODE_AUTO);
456         elm_label_slide_go(data);
457 }
458
459 static void _lbl_stop_slide(void *data, Evas_Object *obj, void *ei)
460 {
461         elm_label_ellipsis_set(data, EINA_TRUE);
462         elm_label_slide_mode_set(data, ELM_LABEL_SLIDE_MODE_NONE);
463         elm_label_slide_go(data);
464 }
465
466 static Evas_Object *_add_label(Evas_Object *ly, const char *name,
467                 const char *style)
468 {
469         Evas_Object *lbl;
470         const char *s;
471
472         if (!ly) {
473                 _ERR("Invalid argument");
474                 return NULL;
475         }
476
477         lbl = elm_label_add(ly);
478         if (!lbl) {
479                 _ERR("failed to add label");
480                 return NULL;
481         }
482
483         if (style)
484                 elm_object_style_set(lbl, style);
485
486         s = edje_object_data_get(elm_layout_edje_get(ly),
487                         DATA_TITLE_WIDTH);
488         if (s)
489                 elm_label_wrap_width_set(lbl, atoi(s));
490         else
491                 _ERR("No title width exist");
492
493         elm_object_text_set(lbl, name ? name : "");
494         elm_label_slide_speed_set(lbl, LABEL_SLIDE_SPEED);
495         evas_object_smart_callback_add(ly, "focused", _lbl_start_slide, lbl);
496         evas_object_smart_callback_add(ly, "unfocused", _lbl_stop_slide, lbl);
497
498         return lbl;
499 }
500
501 static struct _ubar_item *_pack_item(struct _ubar_data *bar,
502                 struct engine_ubar_item *it)
503 {
504         Evas_Object *ly, *ic_bg, *ic, *lbl;
505         struct _ubar_item *item;
506         const char *name, *thumb_bg, *thumb;
507
508         if (!bar || !it)
509                 return NULL;
510
511         item = calloc(1, sizeof(*item));
512         if (!item) {
513                 _ERR("calloc failed");
514                 return NULL;
515         }
516
517         engine_ubar_item_get_info(it, &name, &thumb_bg, &thumb, NULL);
518
519         ly = elm_layout_add(bar->bx);
520         if (!ly) {
521                 _ERR("layout add failed");
522                 free(item);
523                 return NULL;
524         }
525         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_ITEM);
526
527         ic_bg = elm_icon_add(ly);
528         if (!ic_bg)
529                 goto err;
530         elm_object_part_content_set(ly, PART_USER_THUMB_BG, ic_bg);
531
532         ic = elm_icon_add(ly);
533         if (!ic)
534                 goto err;
535         elm_object_part_content_set(ly, PART_USER_THUMB, ic);
536
537         evas_object_show(ly);
538         elm_object_focus_allow_set(ly, EINA_TRUE);
539
540         lbl = _add_label(ly, name, STYLE_LABEL_SLIDE_CENTER_22);
541         if (!lbl) {
542                 _ERR("failed to create name");
543                 evas_object_del(ly);
544                 return NULL;
545         }
546         elm_object_part_content_set(ly, PART_USER_NAME, lbl);
547
548         item->eo = ly;
549         item->ic_bg = ic_bg;
550         item->ic = ic;
551         item->bar = bar;
552         item->it = it;
553         item->is_user = true;
554
555         if (!strcmp(name, DEF_ADD_NAME))
556                 item->is_user = false;
557
558         elm_image_file_set(item->ic_bg,
559                         thumb_bg ? thumb_bg : DEF_UBAR_ITEM_THUMB_BG, NULL);
560         elm_image_file_set(item->ic,
561                         thumb ? thumb : DEF_UBAR_ITEM_THUMB, NULL);
562
563         evas_object_event_callback_add(ly,
564                         EVAS_CALLBACK_MOUSE_UP, _clicked, bar);
565         evas_object_event_callback_add(ly,
566                         EVAS_CALLBACK_MOUSE_MOVE, _mouse_over, NULL);
567         evas_object_smart_callback_add(ly, "focused", _focused, item);
568
569         elm_box_pack_end(bar->bx, ly);
570
571         return item;
572 err:
573         _ERR("image add failed");
574         evas_object_del(ly);
575         free(item);
576         return NULL;
577 }
578
579 static void _pack_arrow(struct _ubar_data *bar, int size)
580 {
581         Evas_Object *ly;
582
583         if (!bar) {
584                 _ERR("Invalid argument");
585                 return;
586         }
587
588         ly = elm_layout_add(bar->bx);
589         if (!ly) {
590                 _ERR("failed to create layout");
591                 return;
592         }
593         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_ITEM_RIGHT_ARROW);
594         evas_object_show(ly);
595
596         elm_object_signal_callback_add(ly, SIG_ARROW_CLICKED, SRC_EDJE,
597                         _arrow_clicked, bar);
598
599         if (size == UBAR_ITEM_MAX) {
600                 elm_object_part_content_set(bar->base,
601                                 PART_UBAR_RIGHT_ARROW, ly);
602         } else if (size > UBAR_ITEM_MAX) {
603                 elm_object_part_content_set(bar->base,
604                                 PART_UBAR_RIGHT_ARROW, ly);
605                 elm_object_signal_emit(ly, SIG_SHOW_ARROW, SRC_PROG);
606         } else {
607                 elm_box_pack_end(bar->bx, ly);
608         }
609
610         bar->arrow = ly;
611 }
612
613 static int _update_items(struct _ubar_data *bar, void *eng)
614 {
615         const Eina_List *list;
616         Eina_List *l;
617         struct engine_ubar_item *it;
618         struct _ubar_item *item;
619
620         if (!bar || !eng) {
621                 _ERR("Invalid argument");
622                 return -1;
623         }
624
625         EINA_LIST_FREE(bar->list, item)
626                 free(item);
627
628         bar->cur = NULL;
629         bar->list = NULL;
630         elm_box_clear(bar->bx);
631
632         list = engine_get_ubar_items(eng);
633         if (!list)
634                 return -1;
635
636         EINA_LIST_FOREACH((Eina_List *)list, l, it) {
637                 item = _pack_item(bar, it);
638                 if (!item)
639                         continue;
640
641                 bar->list = eina_list_append(bar->list, item);
642         }
643
644         _pack_arrow(bar, eina_list_count(bar->list));
645
646         elm_object_focus_allow_set(bar->user->eo, EINA_TRUE);
647         evas_object_focus_set(bar->user->eo, EINA_TRUE);
648         elm_object_signal_emit(bar->ly, SIG_SHOW, SRC_PROG);
649
650         return 0;
651 }
652
653 static int _update(struct bar_info *info, void *eng, void *data)
654 {
655         struct _ubar_data *bar;
656         int r;
657
658         if (!info || !info->data || !eng) {
659                 _ERR("Invalid argument");
660                 return -1;
661         }
662
663         bar = info->data;
664
665         r = _update_user(bar, eng);
666         if (r < 0)
667                 return -1;
668
669         r = _update_items(bar, eng);
670         if (r < 0)
671                 return -1;
672
673         bar->eng = eng;
674
675         return 0;
676 }
677
678 static Evas_Object *_get_item(struct bar_info *info)
679 {
680         struct _ubar_data *bar;
681
682         if (!info || !info->data) {
683                 _ERR("Invalid argument");
684                 return NULL;
685         }
686
687         bar = info->data;
688
689         if (!bar->cur)
690                 bar->cur = bar->user;
691
692         return bar->cur->eo;
693 }
694
695 static Eina_Bool _move_user(struct bar_info *info)
696 {
697         struct _ubar_data *bar;
698
699         if (!info || !info->data) {
700                 _ERR("Invalid argument");
701                 return EINA_FALSE;
702         }
703
704         bar = info->data;
705
706         elm_object_focus_set(bar->user->eo, EINA_TRUE);
707
708         return EINA_TRUE;
709 }
710
711 static Eina_Bool _move_item(struct bar_info *info)
712 {
713         struct _ubar_data *bar;
714         struct _ubar_item *item;
715
716         if (!info || !info->data) {
717                 _ERR("Invalid argument");
718                 return EINA_FALSE;
719         }
720
721         bar = info->data;
722
723         item = eina_list_data_get(bar->list);
724         if (!item)
725                 return EINA_FALSE;
726
727         elm_object_focus_set(item->eo, EINA_TRUE);
728
729         return EINA_TRUE;
730 }
731
732 static Eina_Bool _is_move(struct bar_info *info, int dir)
733 {
734         struct _ubar_data *bar;
735
736         if (!info || !info->data) {
737                 _ERR("Invalid argument");
738                 return EINA_FALSE;
739         }
740
741         bar = info->data;
742
743         switch (dir) {
744         case BAR_DIR_LEFT:
745         case BAR_DIR_DOWN:
746                 if (bar->state != UBAR_STATE_USER)
747                         return EINA_FALSE;
748
749                 if (bar->cur == bar->user)
750                         return EINA_TRUE;
751
752                 break;
753         default:
754                 return EINA_FALSE;
755         }
756
757         return EINA_FALSE;
758 }
759
760 static enum bar_event _move_right(struct bar_info *info)
761 {
762         struct _ubar_data *bar;
763         Eina_Bool r;
764
765         if (!info || !info->data) {
766                 _ERR("Invalid argument");
767                 return BAR_EVENT_ERROR;
768         }
769
770         bar = info->data;
771
772         if (bar->state == UBAR_STATE_USER)
773                 r = _move_item(info);
774         else
775                 r = EINA_FALSE;
776
777         return r ? BAR_EVENT_DONE : BAR_EVENT_PASS;
778 }
779
780 static enum bar_event _move_left(struct bar_info *info)
781 {
782         struct _ubar_data *bar;
783         Eina_Bool r;
784
785         if (!info || !info->data) {
786                 _ERR("Invalid argumnet");
787                 return BAR_EVENT_ERROR;
788         }
789
790         bar = info->data;
791
792         if (bar->state != UBAR_STATE_USER &&
793                         bar->state != UBAR_STATE_ITEM)
794                 return BAR_EVENT_ERROR;
795
796         if (eina_list_data_get(bar->list) == bar->cur)
797                 r = _move_user(info);
798         else
799                 r = EINA_FALSE;
800
801         return r ? BAR_EVENT_DONE : BAR_EVENT_PASS;
802 }
803
804 static void _destroy_ctxpopup(struct _ubar_item *item)
805 {
806         int i;
807
808         ASSERT(item);
809
810         evas_object_del(item->ctxpopup);
811         item->ctxpopup = NULL;
812         for (i = 0; i < BTN_MAX; i++) {
813                 memset(item->btn, 0x00, sizeof(item->btn));
814                 item->btn[i] = NULL;
815         }
816 }
817
818 static void _destroy_popup(struct _ubar_item *item)
819 {
820         int i;
821
822         ASSERT(item);
823
824         evas_object_del(item->popup);
825         item->popup = NULL;
826         item->state = POPUP_STATE_NONE;
827
828         for (i = 0; i < BTN_MAX; i++) {
829                 memset(item->btn, 0x00, sizeof(item->btn));
830                 item->btn[i] = NULL;
831         }
832
833         switch (item->bar->state) {
834         case UBAR_STATE_USER_POPUP:
835                 item->bar->state = UBAR_STATE_USER;
836                 break;
837         case UBAR_STATE_ITEM_POPUP:
838                 item->bar->state = UBAR_STATE_ITEM;
839                 break;
840         default:
841                 break;
842         }
843 }
844
845 static enum bar_event _back(struct bar_info *info)
846 {
847         struct _ubar_data *bar;
848         enum bar_event r;
849
850         if (!info || !info->data) {
851                 _ERR("Invalid argument");
852                 return BAR_EVENT_ERROR;
853         }
854
855         bar = info->data;
856
857         switch (bar->state) {
858         case UBAR_STATE_USER:
859                 r = BAR_EVENT_MOVE;
860                 break;
861         case UBAR_STATE_ITEM:
862                 r = _move_user(info) ? BAR_EVENT_DONE : BAR_EVENT_PASS;
863                 break;
864         case UBAR_STATE_USER_CTXPOPUP:
865                 _destroy_ctxpopup(bar->user);
866                 bar->state = UBAR_STATE_USER;
867                 r = BAR_EVENT_DONE;
868                 break;
869         case UBAR_STATE_ITEM_CTXPOPUP:
870                 _destroy_ctxpopup(bar->cur);
871                 bar->state = UBAR_STATE_ITEM;
872                 r = BAR_EVENT_DONE;
873                 break;
874         case UBAR_STATE_USER_POPUP:
875                 _destroy_popup(bar->user);
876                 r = BAR_EVENT_DONE;
877                 break;
878         case UBAR_STATE_ITEM_POPUP:
879                 _destroy_popup(bar->cur);
880                 r = BAR_EVENT_DONE;
881                 break;
882         default:
883                 return BAR_EVENT_ERROR;
884         }
885
886         return r;
887 }
888
889 static Eina_Bool _add_popup_btn(Evas_Object *p, struct _ubar_item *item,
890                 struct _btn_info *btn_info, int size)
891 {
892         Evas_Object *btn;
893         int i;
894
895         if (!p || !item || !btn_info) {
896                 _ERR("Invalid argument");
897                 return EINA_FALSE;
898         }
899
900         for (i = 0; i < size; i++) {
901                 btn = elm_button_add(p);
902                 if (!btn) {
903                         _ERR("failed to create button");
904                         memset(item->btn, 0x00, sizeof(item->btn));
905                         return EINA_FALSE;
906                 }
907                 elm_object_part_content_set(p, btn_info[i].part, btn);
908                 elm_object_text_set(btn, btn_info[i].text);
909                 evas_object_show(btn);
910                 item->btn[i] = btn;
911
912                 evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_DOWN,
913                                 btn_info[i].click_cb, item);
914                 evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_MOVE,
915                                 _mouse_over, NULL);
916         }
917
918         return EINA_TRUE;
919 }
920
921 static void _popup_cancel_clicked(void *data, Evas *e, Evas_Object *obj,
922                 void *ei)
923 {
924         struct _ubar_item *item;
925
926         if (!data) {
927                 _ERR("Invalid argument");
928                 return;
929         }
930
931         item = data;
932
933         item->pw_entry = NULL;
934         _destroy_popup(item);
935 }
936
937 static Evas_Object *_add_popup(Evas_Object *base, const char *title,
938                 const char *style)
939 {
940         Evas_Object *popup, *win;
941
942         if (!base || !title) {
943                 _ERR("Invalid argument");
944                 return NULL;
945         }
946
947         win = elm_object_parent_widget_get(base);
948         if (!win) {
949                 _ERR("failed to get win eo");
950                 return NULL;
951         }
952
953         popup = elm_popup_add(win);
954         if (!popup) {
955                 _ERR("failed to create popup");
956                 return NULL;
957         }
958         if (style)
959                 elm_object_style_set(popup, style);
960         elm_object_part_text_set(popup, PART_POPUP_TEXT, title);
961         elm_popup_orient_set(popup, ELM_POPUP_ORIENT_CENTER);
962         elm_object_focus_allow_set(popup, EINA_FALSE);
963
964         return popup;
965 }
966
967 static void _show_message(struct _ubar_item *item, const char *signal)
968 {
969         Evas_Object *ly;
970
971         if (!item || !signal) {
972                 _ERR("Invalid argument");
973                 return;
974         }
975
976         elm_entry_entry_set(item->pw_entry, "");
977         ly = elm_object_parent_widget_get(item->pw_entry);
978         if (!ly) {
979                 _ERR("failed to get parent widget");
980                 return;
981         }
982
983         elm_object_signal_emit(ly, signal, SRC_PROG);
984 }
985
986 static Eina_Bool _check_delete_user(struct _ubar_item *item)
987 {
988         struct _ubar_data *bar;
989         const char *password;
990
991         if (!item) {
992                 _ERR("Invalid argument");
993                 return EINA_FALSE;
994         }
995
996         bar = item->bar;
997
998         password = elm_entry_entry_get(item->pw_entry);
999         if (!password || strlen(password) == 0) {
1000                 _ERR("wrong password");
1001                 _show_message(item, SIG_SHOW_WRONG_PW);
1002                 return EINA_FALSE;
1003         }
1004
1005         if (!engine_ubar_item_delete(bar->eng, item->it, password)) {
1006                 _ERR("failed to delete user");
1007                 _show_message(item, SIG_SHOW_SYSTEM_FAIL);
1008                 return EINA_FALSE;
1009         }
1010
1011         _destroy_popup(item);
1012
1013         evas_object_del(bar->ly);
1014         bar->ly = NULL;
1015
1016         _add_items(bar, bar->base);
1017         _update_items(bar, bar->eng);
1018
1019         return EINA_TRUE;
1020 }
1021
1022 static void _popup_delete_clicked(void *data, Evas *e, Evas_Object *obj,
1023                 void *ei)
1024 {
1025         _check_delete_user(data);
1026 }
1027
1028 static Evas_Object *_add_arrow(struct _ubar_item *item, Evas_Object *p,
1029                 const char *group, const char *part)
1030 {
1031         Evas_Object *ly;
1032
1033         if (!item || !p || !part || !group) {
1034                 _ERR("Invalid argument");
1035                 return NULL;
1036         }
1037
1038         ly = elm_layout_add(p);
1039         if (!ly) {
1040                 _ERR("failed to create icon");
1041                 evas_object_del(p);
1042                 return NULL;
1043         }
1044         elm_layout_file_set(ly, EDJEFILE, group);
1045         elm_object_part_content_set(p, part, ly);
1046         evas_object_show(ly);
1047
1048         evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_MOVE,
1049                         _mouse_over, item);
1050
1051         return ly;
1052 }
1053
1054 static void _popup_user_focused(void *data, Evas_Object *obj, void *ei)
1055 {
1056         struct _ubar_data *bar;
1057         struct _ubar_item *foc;
1058
1059         if (!data) {
1060                 _ERR("Invalid argument");
1061                 return;
1062         }
1063
1064         foc = data;
1065         bar = foc->bar;
1066
1067         _update_arrow(bar->popup_scr, bar->cur->right_arrow,
1068                         bar->cur->left_arrow);
1069
1070         bar->popup_cur = foc;
1071 }
1072
1073 static void _scroll_focused(void *data, Evas_Object *obj, void *ei)
1074 {
1075         struct _ubar_data *bar;
1076
1077         if (!data) {
1078                 _ERR("Invalid argument");
1079                 return;
1080         }
1081
1082         bar = data;
1083         if (!bar || !bar->popup_cur)
1084                 return;
1085
1086         elm_object_focus_set(bar->popup_cur->eo, EINA_TRUE);
1087 }
1088
1089 static struct _ubar_item *_pack_icon(struct _ubar_data *bar, const char *icon,
1090                 Evas_Object *p)
1091 {
1092         Evas_Object *ly, *ic, *ic_bg;
1093         struct _ubar_item *item;
1094
1095         if (!bar || !icon || !p) {
1096                 _ERR("Invalid argument");
1097                 return NULL;
1098         }
1099
1100         item = calloc(1, sizeof(*item));
1101         if (!item) {
1102                 _ERR("calloc failed");
1103                 return NULL;
1104         }
1105
1106         ly = elm_layout_add(p);
1107         if (!ly) {
1108                 _ERR("failed to create layout");
1109                 evas_object_del(p);
1110                 return NULL;
1111         }
1112         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_POPUP_ITEM);
1113
1114         ic = elm_icon_add(ly);
1115         if (!ic) {
1116                 _ERR("failed to create icon");
1117                 evas_object_del(p);
1118                 return NULL;
1119         }
1120         elm_object_part_content_set(ly, PART_USER_THUMB, ic);
1121
1122         ic_bg = elm_icon_add(ly);
1123         if (!ic_bg) {
1124                 _ERR("failed to create icon");
1125                 evas_object_del(p);
1126                 return NULL;
1127         }
1128         elm_object_focus_allow_set(ly, EINA_TRUE);
1129         elm_object_part_content_set(ly, PART_USER_THUMB_BG, ic_bg);
1130         evas_object_show(ly);
1131
1132         elm_image_file_set(ic, icon, NULL);
1133         elm_image_file_set(ic_bg, DEF_UBAR_ITEM_THUMB_BG, NULL);
1134         elm_box_pack_end(p, ly);
1135
1136         evas_object_smart_callback_add(ly, "focused", _popup_user_focused,
1137                         item);
1138         evas_object_event_callback_add(ly, EVAS_CALLBACK_MOUSE_MOVE,
1139                         _mouse_over, bar);
1140
1141         item->ic = ic;
1142         item->eo = ly;
1143         item->bar = bar;
1144
1145         return item;
1146 }
1147
1148 static Eina_Bool _load_users(struct _ubar_data *bar, Evas_Object *p)
1149 {
1150         Evas_Object *scr, *box;
1151         struct _ubar_item *item, *_item;
1152         int i;
1153
1154         if (!bar || !p) {
1155                 _ERR("Invalid argument");
1156                 return EINA_FALSE;
1157         }
1158
1159         scr = elm_scroller_add(p);
1160         if (!scr) {
1161                 _ERR("failed to create scroll");
1162                 evas_object_del(p);
1163                 return EINA_FALSE;
1164         }
1165         evas_object_smart_callback_add(scr, "focused", _scroll_focused, bar);
1166         elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF,
1167                         ELM_SCROLLER_POLICY_OFF);
1168         elm_object_signal_callback_add(scr, SIG_SCROLL_RIGHT, SRC_ELM,
1169                         _scroll_cb, bar);
1170         elm_object_signal_callback_add(scr, SIG_SCROLL_LEFT, SRC_ELM,
1171                         _scroll_cb, bar);
1172
1173         box = elm_box_add(scr);
1174         if (!box) {
1175                 _ERR("failed to create box");
1176                 evas_object_del(p);
1177                 return EINA_FALSE;
1178         }
1179         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND,
1180                         EVAS_HINT_EXPAND);
1181         elm_box_horizontal_set(box, EINA_TRUE);
1182         elm_box_padding_set(box,
1183                         elm_config_scale_get() * UBAR_POPUP_PADDING_X, 0);
1184
1185         elm_object_part_content_set(p, PART_POPUP_USER, scr);
1186         evas_object_show(box);
1187         elm_object_content_set(scr, box);
1188
1189         bar->popup_scr = scr;
1190         bar->popup_box = box;
1191
1192         bar->popup_list = NULL;
1193         bar->popup_cur = NULL;
1194         EINA_LIST_FREE(bar->popup_list, _item)
1195                 free(_item);
1196
1197         for (i = 0; i < sizeof(icon_path) / sizeof(*icon_path); i++) {
1198                 item = _pack_icon(bar, icon_path[i], box);
1199                 if (!item)
1200                         continue;
1201
1202                 bar->popup_list = eina_list_append(bar->popup_list, item);
1203         }
1204
1205         return EINA_TRUE;
1206 }
1207
1208 static Evas_Object *_add_entry(Evas_Object *p, const char *part, bool password)
1209 {
1210         Evas_Object *entry;
1211
1212         if (!p || !part) {
1213                 _ERR("Invalid argument");
1214                 return NULL;
1215         }
1216
1217         entry = elm_entry_add(p);
1218         if (!entry) {
1219                 _ERR("failed to create entry");
1220                 evas_object_del(p);
1221                 return NULL;
1222         }
1223         if (password) {
1224                 elm_entry_password_set(entry, EINA_TRUE);
1225                 elm_config_password_show_last_set(EINA_FALSE);
1226         }
1227         elm_object_style_set(entry, STYLE_ENTRY);
1228         elm_entry_single_line_set(entry, EINA_TRUE);
1229         elm_entry_input_panel_language_set(entry,
1230                         ELM_INPUT_PANEL_LANG_ALPHABET);
1231         elm_entry_cursor_end_set(entry);
1232         elm_entry_scrollable_set(entry, EINA_TRUE);
1233         elm_scroller_policy_set(entry, ELM_SCROLLER_POLICY_OFF,
1234                         ELM_SCROLLER_POLICY_OFF);
1235         elm_object_part_content_set(p, part, entry);
1236         evas_object_show(entry);
1237
1238         return entry;
1239 }
1240
1241 static void _popup_arrow_clicked(void *data, Evas_Object *obj,
1242                 const char *emission, const char *source)
1243 {
1244         struct _ubar_item *item;
1245         Evas_Object *scr;
1246         Evas_Coord rx, ry, rw, rh, cw;
1247
1248         if (!data) {
1249                 _ERR("Invalid argument");
1250                 return;
1251         }
1252
1253         item = data;
1254         scr = item->bar->popup_scr;
1255
1256         elm_scroller_region_get(scr, &rx, &ry, &rw, &rh);
1257         elm_scroller_child_size_get(scr, &cw, NULL);
1258
1259         if (cw <= rw)
1260                 return;
1261
1262         if (obj == item->left_arrow)
1263                 rx = rx - UBAR_ITEM_WIDTH;
1264         else if (obj == item->right_arrow)
1265                 rx = rx + UBAR_ITEM_WIDTH;
1266
1267         elm_scroller_region_bring_in(scr, rx, ry, rw, rh);
1268         _update_arrow(scr, item->right_arrow, item->left_arrow);
1269 }
1270
1271 static void _pw_entry_focused(void *data, Evas_Object *obj, void *ei)
1272 {
1273         if (!elm_entry_is_empty(obj))
1274                 return;
1275
1276         elm_object_signal_emit(data, SIG_HIDE_PW, SRC_PROG);
1277 }
1278
1279 static void _pw_entry_unfocused(void *data, Evas_Object *obj, void *ei)
1280 {
1281         if (!elm_entry_is_empty(obj))
1282                 return;
1283
1284         elm_object_signal_emit(data, SIG_SHOW_PW, SRC_PROG);
1285 }
1286
1287 static Evas_Object *_add_popup_items(struct _ubar_item *item, Evas_Object *popup)
1288 {
1289         Evas_Object *ly, *pw_entry, *right_arrow, *left_arrow;
1290
1291         if (!item || !popup) {
1292                 _ERR("Invalid argument");
1293                 return NULL;
1294         }
1295
1296         ly = elm_layout_add(popup);
1297         if (!ly) {
1298                 _ERR("failed to create layout");
1299                 return NULL;
1300         }
1301         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_POPUP);
1302         evas_object_show(ly);
1303         elm_object_content_set(popup, ly);
1304
1305         left_arrow = _add_arrow(item, ly, GRP_UBAR_LEFT_ARROW, PART_LEFT_ARROW);
1306         if (!left_arrow) {
1307                 _ERR("failed to create left arrow");
1308                 evas_object_del(ly);
1309                 return NULL;
1310         }
1311         elm_object_signal_callback_add(left_arrow, SIG_ARROW_CLICKED, SRC_EDJE,
1312                         _popup_arrow_clicked, item);
1313
1314         right_arrow = _add_arrow(item, ly, GRP_UBAR_RIGHT_ARROW,
1315                         PART_RIGHT_ARROW);
1316         if (!right_arrow) {
1317                 _ERR("failed to create right arrow");
1318                 evas_object_del(ly);
1319                 return NULL;
1320         }
1321         elm_object_signal_callback_add(right_arrow, SIG_ARROW_CLICKED, SRC_EDJE,
1322                         _popup_arrow_clicked, item);
1323
1324         if (!_load_users(item->bar, ly)) {
1325                 _ERR("failed to create users");
1326                 evas_object_del(ly);
1327                 return NULL;
1328         }
1329
1330         pw_entry = _add_entry(ly, PART_POPUP_ENTRY_PW, true);
1331         if (!pw_entry) {
1332                 _ERR("failed to create pw entry");
1333                 evas_object_del(ly);
1334                 return NULL;
1335         }
1336         elm_object_focus_next_object_set(pw_entry, item->btn[0],
1337                         ELM_FOCUS_DOWN);
1338         elm_object_signal_emit(ly, SIG_SHOW_PW, SRC_PROG);
1339         evas_object_smart_callback_add(pw_entry, "focused",
1340                         _pw_entry_focused, ly);
1341         evas_object_smart_callback_add(pw_entry, "unfocused",
1342                         _pw_entry_unfocused, ly);
1343
1344         item->left_arrow = left_arrow;
1345         item->right_arrow = right_arrow;
1346         item->pw_entry = pw_entry;
1347
1348         return ly;
1349 }
1350
1351 static Eina_Bool _check_edit_user(struct _ubar_item *item)
1352 {
1353         struct _ubar_data *bar;
1354         struct _ubar_item *cur;
1355         const char *icon, *password;
1356
1357         if (!item) {
1358                 _ERR("Invalid argument");
1359                 return EINA_FALSE;
1360         }
1361
1362         bar = item->bar;
1363         cur = bar->popup_cur;
1364
1365         password = elm_entry_entry_get(item->pw_entry);
1366         if (!password || strlen(password) == 0) {
1367                 _ERR("wrong password");
1368                 _show_message(item, SIG_SHOW_WRONG_PW);
1369                 return EINA_FALSE;
1370         }
1371
1372         elm_image_file_get(cur->ic, &icon, NULL);
1373         if (!engine_ubar_item_update(bar->eng, item->it, icon, password)) {
1374                 _ERR("failed to update user");
1375                 _show_message(item, SIG_SHOW_SYSTEM_FAIL);
1376                 return EINA_FALSE;
1377         }
1378
1379         _destroy_popup(item);
1380
1381         evas_object_del(bar->ly);
1382         bar->ly = NULL;
1383
1384         _add_items(bar, bar->base);
1385         _update_items(bar, bar->eng);
1386
1387         return EINA_TRUE;
1388 }
1389
1390 static void _popup_edit_clicked(void *data, Evas *e, Evas_Object *obj,
1391                 void *ei)
1392 {
1393         _check_edit_user(data);
1394 }
1395
1396 static void _delete_ctxpopup(struct _ubar_data *bar)
1397 {
1398         if (!bar) {
1399                 _ERR("Invalid argument");
1400                 return;
1401         }
1402
1403         switch (bar->state) {
1404         case UBAR_STATE_USER_CTXPOPUP:
1405                 _destroy_ctxpopup(bar->user);
1406                 bar->state = UBAR_STATE_USER_POPUP;
1407                 break;
1408         case UBAR_STATE_ITEM_CTXPOPUP:
1409                 _destroy_ctxpopup(bar->cur);
1410                 bar->state = UBAR_STATE_ITEM_POPUP;
1411                 break;
1412         default:
1413                 return;
1414         }
1415 }
1416
1417 static Eina_Bool _load_edit_popup(struct _ubar_item *item)
1418 {
1419         struct _ubar_data *bar;
1420         Evas_Object *popup, *lbl, *ly;
1421         struct _ubar_item *cur;
1422         Eina_List *l;
1423         const char *icon, *name, *thumb;
1424         struct _btn_info btn_info[] = {
1425                 {
1426                         "button1",
1427                         "Edit",
1428                         _popup_edit_clicked
1429                 },
1430                 {
1431                         "button2",
1432                         "Cancel",
1433                         _popup_cancel_clicked
1434                 }
1435         };
1436
1437         if (!item) {
1438                 _ERR("Invalid argument");
1439                 return EINA_FALSE;
1440         }
1441
1442         bar = item->bar;
1443         _delete_ctxpopup(bar);
1444
1445         popup = _add_popup(bar->base, TITLE_EDIT_POPUP, NULL);
1446         if (!popup) {
1447                 _ERR("failed to create popup");
1448                 return EINA_FALSE;
1449         }
1450
1451         if (!_add_popup_btn(popup, item, btn_info,
1452                         sizeof(btn_info) / sizeof(btn_info[0]))) {
1453                 _ERR("failed to create popup button");
1454                 evas_object_del(popup);
1455                 return EINA_FALSE;
1456         }
1457
1458         ly = _add_popup_items(item, popup);
1459         if (!ly) {
1460                 _ERR("failed to create popup user");
1461                 evas_object_del(popup);
1462                 return EINA_FALSE;
1463         }
1464         evas_object_show(popup);
1465
1466         engine_ubar_item_get_info(item->it, &name, NULL, &thumb, NULL);
1467
1468         lbl = elm_label_add(ly);
1469         if (!lbl) {
1470                 _ERR("failed to create label");
1471                 evas_object_del(popup);
1472                 return EINA_FALSE;
1473         }
1474         elm_object_part_content_set(ly, PART_POPUP_ENTRY_NAME, lbl);
1475         elm_object_text_set(lbl, name);
1476         elm_object_style_set(lbl, STYLE_LABEL_SLIDE_LEFT_28);
1477         elm_label_slide_speed_set(lbl, LABEL_SLIDE_SPEED);
1478         elm_label_slide_mode_set(lbl, ELM_LABEL_SLIDE_MODE_AUTO);
1479
1480         engine_ubar_item_get_info(item->it, &name, NULL, &thumb, NULL);
1481         if (bar->popup_list) {
1482                 EINA_LIST_FOREACH(bar->popup_list, l, cur) {
1483                         elm_image_file_get(cur->ic, &icon, NULL);
1484                         if (!strcmp(icon, thumb))
1485                                 elm_object_focus_set(cur->eo, EINA_TRUE);
1486                 }
1487         }
1488
1489         elm_object_signal_emit(item->eo, SIG_HLIGHT_FROM_POPOVER, SRC_PROG);
1490
1491         item->popup = popup;
1492         item->state = POPUP_STATE_EDIT;
1493
1494         return EINA_TRUE;
1495 }
1496
1497 static Eina_Bool _add_delete_item(Evas_Object *p, struct _ubar_item *item)
1498 {
1499         Evas_Object *ly, *entry, *lbl;
1500         const char *name;
1501         char buf[BUF_MAX];
1502
1503         if (!p || !item || !item->it) {
1504                 _ERR("Invalid argument");
1505                 return EINA_FALSE;
1506         }
1507
1508         ly = elm_layout_add(p);
1509         if (!ly) {
1510                 _ERR("failed to create layout");
1511                 return EINA_FALSE;
1512         }
1513         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_DELETE);
1514         elm_object_content_set(p, ly);
1515         evas_object_show(ly);
1516
1517         engine_ubar_item_get_info(item->it, &name, NULL, NULL, NULL);
1518         snprintf(buf, sizeof(buf), "%s %s?", MESSAGE_DELETE_POPUP,
1519                         name ? name : "");
1520
1521         lbl = elm_label_add(ly);
1522         if (!lbl) {
1523                 _ERR("failed to create label");
1524                 evas_object_del(ly);
1525                 return EINA_FALSE;
1526         }
1527         elm_object_text_set(lbl, buf);
1528         elm_object_style_set(lbl, STYLE_LABEL_SLIDE_CENTER_22);
1529         elm_label_slide_speed_set(lbl, LABEL_SLIDE_SPEED);
1530         elm_label_slide_mode_set(lbl, ELM_LABEL_SLIDE_MODE_AUTO);
1531         elm_object_part_content_set(ly, PART_USER_DELETE_MESSAGE, lbl);
1532
1533         entry = _add_entry(ly, PART_USER_LOGIN_PW, true);
1534         if (!entry) {
1535                 _ERR("failed to create entry");
1536                 evas_object_del(ly);
1537                 return EINA_FALSE;
1538         }
1539         elm_object_signal_emit(ly, SIG_SHOW_PW, SRC_PROG);
1540         evas_object_smart_callback_add(entry, "focused", _pw_entry_focused, ly);
1541         evas_object_smart_callback_add(entry, "unfocused", _pw_entry_unfocused,
1542                         ly);
1543
1544         item->pw_entry = entry;
1545
1546         return EINA_TRUE;
1547 }
1548
1549 static Eina_Bool _load_delete_popup(struct _ubar_item *item)
1550 {
1551         struct _ubar_data *bar;
1552         Evas_Object *popup;
1553         struct _btn_info btn_info[] = {
1554                 {
1555                         "button1",
1556                         "Delete",
1557                         _popup_delete_clicked
1558                 },
1559                 {
1560                         "button2",
1561                         "Cancel",
1562                         _popup_cancel_clicked
1563                 }
1564         };
1565
1566         if (!item) {
1567                 _ERR("Invalid argument");
1568                 return EINA_FALSE;
1569         }
1570
1571         bar = item->bar;
1572         _delete_ctxpopup(bar);
1573
1574         popup = _add_popup(bar->base, TITLE_DELETE_POPUP, NULL);
1575         if (!popup) {
1576                 _ERR("failed to create popup");
1577                 return EINA_FALSE;
1578         }
1579
1580         if (!_add_popup_btn(popup, item, btn_info,
1581                         sizeof(btn_info) / sizeof(btn_info[0]))) {
1582                 _ERR("failed to create popup button");
1583                 evas_object_del(popup);
1584                 return EINA_FALSE;
1585         }
1586         evas_object_show(popup);
1587
1588         if (!_add_delete_item(popup, item)) {
1589                 _ERR("failed to create login item");
1590                 evas_object_del(popup);
1591                 return EINA_FALSE;
1592         }
1593
1594         if (item->pw_entry)
1595                 elm_object_focus_set(item->pw_entry, EINA_TRUE);
1596
1597         elm_object_signal_emit(item->eo, SIG_HLIGHT_FROM_POPOVER, SRC_PROG);
1598
1599         item->state = POPUP_STATE_DELETE;
1600         item->popup = popup;
1601
1602         return EINA_TRUE;
1603 }
1604
1605 static void _cancel_clicked(void *data, Evas *e, Evas_Object *obj, void *ei)
1606 {
1607         struct _ubar_item *item;
1608
1609         if (!data) {
1610                 _ERR("Invalid argument");
1611                 return;
1612         }
1613
1614         item = data;
1615
1616         item->pw_entry = NULL;
1617         _destroy_popup(item);
1618 }
1619
1620 static Eina_Bool _check_login_user(struct _ubar_item *item)
1621 {
1622         const char *password;
1623
1624         if (!item) {
1625                 _ERR("Invalid argument");
1626                 return EINA_FALSE;
1627         }
1628
1629         password = elm_entry_entry_get(item->pw_entry);
1630         if (!password || strlen(password) == 0) {
1631                 _ERR("wrong password");
1632                 _show_message(item, SIG_SHOW_WRONG_PW);
1633                 return EINA_FALSE;
1634         }
1635
1636         if (!engine_ubar_item_change_user(item->bar->eng, item->it, password)) {
1637                 _ERR("failed to delete user");
1638                 _show_message(item, SIG_SHOW_SYSTEM_FAIL);
1639                 return EINA_FALSE;
1640         }
1641
1642         item->pw_entry = NULL;
1643         _destroy_popup(item);
1644
1645         return EINA_TRUE;
1646 }
1647
1648 static void _login_clicked(void *data, Evas *e, Evas_Object *obj, void *ei)
1649 {
1650         _check_login_user(data);
1651 }
1652
1653 static Eina_Bool _add_login_item(Evas_Object *p, struct _ubar_item *item)
1654 {
1655         Evas_Object *ly, *ic, *lbl, *entry;
1656         const char *name, *thumb;
1657
1658         if (!p || !item || !item->it) {
1659                 _ERR("Invalid argument");
1660                 return EINA_FALSE;
1661         }
1662
1663         engine_ubar_item_get_info(item->it, &name, NULL, &thumb, NULL);
1664
1665         ly = elm_layout_add(p);
1666         if (!ly) {
1667                 _ERR("failed to create layout");
1668                 return EINA_FALSE;
1669         }
1670         elm_layout_file_set(ly, EDJEFILE, GRP_UBAR_LOGIN);
1671         elm_object_content_set(p, ly);
1672         evas_object_show(ly);
1673
1674         ic = elm_icon_add(ly);
1675         if (!ic) {
1676                 _ERR("failed to create icon");
1677                 evas_object_del(ly);
1678                 return EINA_FALSE;
1679         }
1680         elm_image_file_set(ic, thumb ? thumb : DEF_UBAR_ITEM_THUMB, NULL);
1681         evas_object_color_set(ic, 66, 71, 108, 255);
1682         elm_object_part_content_set(ly, PART_USER_LOGIN_THUMB, ic);
1683
1684         lbl = elm_label_add(ly);
1685         if (!lbl) {
1686                 _ERR("failed to create label");
1687                 evas_object_del(ly);
1688                 return EINA_FALSE;
1689         }
1690         elm_object_part_content_set(ly, PART_USER_LOGIN_NAME, lbl);
1691         elm_object_text_set(lbl, name);
1692         elm_object_style_set(lbl, STYLE_LABEL_SLIDE_LEFT_28);
1693         elm_label_slide_speed_set(lbl, LABEL_SLIDE_SPEED);
1694         elm_label_slide_mode_set(lbl, ELM_LABEL_SLIDE_MODE_AUTO);
1695
1696         entry = _add_entry(ly, PART_USER_LOGIN_PW, true);
1697         if (!entry) {
1698                 _ERR("failed to create entry");
1699                 evas_object_del(ly);
1700                 return EINA_FALSE;
1701         }
1702         elm_object_focus_next_object_set(entry, item->btn[0],
1703                         ELM_FOCUS_DOWN);
1704         elm_object_signal_emit(ly, SIG_SHOW_PW, SRC_PROG);
1705         evas_object_smart_callback_add(entry, "focused", _pw_entry_focused, ly);
1706         evas_object_smart_callback_add(entry, "unfocused", _pw_entry_unfocused,
1707                         ly);
1708
1709         item->pw_entry = entry;
1710
1711         return EINA_TRUE;
1712 }
1713
1714 static Eina_Bool _load_login_popup(struct _ubar_item *item)
1715 {
1716         Evas_Object *popup;
1717         struct _btn_info btn_info[] = {
1718                 {
1719                         "button1",
1720                         "Login",
1721                         _login_clicked
1722                 },
1723                 {
1724                         "button2",
1725                         "Cancel",
1726                         _cancel_clicked
1727                 }
1728         };
1729
1730         if (!item) {
1731                 _ERR("Invalid argument");
1732                 return EINA_FALSE;
1733         }
1734
1735         _delete_ctxpopup(item->bar);
1736
1737         popup = _add_popup(item->bar->base, TITLE_LOGIN_POPUP, NULL);
1738         if (!popup) {
1739                 _ERR("failed to create popup");
1740                 return EINA_FALSE;
1741         }
1742
1743         if (!_add_popup_btn(popup, item, btn_info,
1744                         sizeof(btn_info) / sizeof(btn_info[0]))) {
1745                 _ERR("failed to create popup button");
1746                 evas_object_del(popup);
1747                 return EINA_FALSE;
1748         }
1749         evas_object_show(popup);
1750
1751         if (!_add_login_item(popup, item)) {
1752                 _ERR("failed to create login item");
1753                 evas_object_del(popup);
1754                 return EINA_FALSE;
1755         }
1756
1757         if (item->pw_entry)
1758                 elm_object_focus_set(item->pw_entry, EINA_TRUE);
1759
1760         elm_object_signal_emit(item->eo, SIG_HLIGHT_FROM_POPOVER, SRC_PROG);
1761
1762         item->popup = popup;
1763         item->state = POPUP_STATE_LOGIN;
1764
1765         return EINA_TRUE;
1766 }
1767
1768 static void _ctxpopup_edit_clicked(void *data, Evas *e, Evas_Object *obj,
1769                 void *ei)
1770 {
1771         _load_edit_popup(data);
1772 }
1773
1774 static void _ctxpopup_delete_clicked(void *data, Evas *e, Evas_Object *obj,
1775                 void *ei)
1776 {
1777         _load_delete_popup(data);
1778 }
1779
1780 static void _ctxpopup_login_clicked(void *data, Evas *e, Evas_Object *obj,
1781                 void *ei)
1782 {
1783         _load_login_popup(data);
1784 }
1785
1786 static bool _check_user(struct _ubar_item *item)
1787 {
1788         if (!item) {
1789                 _ERR("Invalid argument");
1790                 return EINA_FALSE;
1791         }
1792
1793         return engine_ubar_item_get_privilege(item->bar->eng);
1794 }
1795
1796 static Eina_Bool _add_ctxpopup_btn(struct _ubar_item *item, Evas_Object *base)
1797 {
1798         Evas_Object *btn, *firstbtn;
1799         int i;
1800         struct _btn_info btn_info[] = {
1801                 {
1802                         NULL,
1803                         "Login",
1804                         _ctxpopup_login_clicked
1805                 },
1806                 {
1807                         NULL,
1808                         "Edit",
1809                         _ctxpopup_edit_clicked
1810                 },
1811                 {
1812                         NULL,
1813                         "Delete",
1814                         _ctxpopup_delete_clicked
1815                 }
1816         };
1817
1818         if (!item || !base) {
1819                 _ERR("Invalid argument");
1820                 return EINA_FALSE;
1821         }
1822
1823         for (i = 0; i < sizeof(btn_info) / sizeof(*btn_info); i++) {
1824                 btn = elm_button_add(base);
1825                 if (!btn) {
1826                         _ERR("failed to add button");
1827                         memset(item->btn, 0x00, sizeof(item->btn));
1828                         return EINA_FALSE;
1829                 }
1830
1831                 elm_object_text_set(btn, btn_info[i].text);
1832                 evas_object_show(btn);
1833                 item->btn[i] = btn;
1834
1835                 if (i == 0)
1836                         firstbtn = btn;
1837
1838                 evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_MOVE,
1839                                 _mouse_over, NULL);
1840
1841                 if (i > 0 && !_check_user(item)) {
1842                         elm_object_style_set(btn, STYLE_BTN_DIM_HOVERTEXT);
1843                         elm_object_focus_allow_set(btn, EINA_FALSE);
1844                 } else {
1845                         elm_object_style_set(btn, STYLE_BTN_HOVERTEXT);
1846                         evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_DOWN,
1847                                         btn_info[i].click_cb, item);
1848                 }
1849
1850                 elm_box_pack_end(base, btn);
1851         }
1852
1853         if (firstbtn)
1854                 elm_object_focus_set(firstbtn, EINA_TRUE);
1855
1856         return EINA_TRUE;
1857 }
1858
1859 static Eina_Bool _create_ctxpopup(struct _ubar_item *item)
1860 {
1861         Evas_Object *ctxpopup, *box, *win;
1862         Evas_Coord x, w;
1863         const char *s;
1864
1865         if (!item) {
1866                 _ERR("Invalid argument");
1867                 return EINA_FALSE;
1868         }
1869
1870         win = elm_object_parent_widget_get(item->bar->base);
1871         if (!win) {
1872                 _ERR("failed to get win");
1873                 return EINA_FALSE;
1874         }
1875
1876         ctxpopup = elm_ctxpopup_add(win);
1877         if (!ctxpopup) {
1878                 _ERR("failed to create ctxpopup");
1879                 return EINA_FALSE;
1880         }
1881         elm_object_style_set(ctxpopup, STYLE_CTXPOPUP_HOVER);
1882         elm_ctxpopup_direction_priority_set(ctxpopup, 0, 0, 0, 0);
1883         evas_object_geometry_get(item->ic, &x, NULL, &w, NULL);
1884         s = edje_object_data_get(elm_layout_edje_get(item->eo),
1885                         DATA_TITLE_WIDTH);
1886         evas_object_move(ctxpopup, (x + atoi(s) / 2) * elm_config_scale_get(),
1887                         POSITION_CTXPOPUP_Y *elm_config_scale_get());
1888
1889         box = elm_box_add(ctxpopup);
1890         if (!box) {
1891                 _ERR("failed to create popup box");
1892                 evas_object_del(ctxpopup);
1893                 return EINA_FALSE;
1894         }
1895         elm_object_content_set(ctxpopup, box);
1896         evas_object_show(box);
1897         evas_object_show(ctxpopup);
1898
1899         if (!_add_ctxpopup_btn(item, box)) {
1900                 _ERR("failed to create popup button");
1901                 evas_object_del(ctxpopup);
1902                 return EINA_FALSE;
1903         }
1904
1905         elm_object_signal_emit(item->eo, SIG_HLIGHT_FROM_POPOVER, SRC_PROG);
1906         item->ctxpopup = ctxpopup;
1907
1908         return EINA_TRUE;
1909 }
1910
1911 static Eina_Bool _check_add_user(struct _ubar_item *item)
1912 {
1913         struct _ubar_data *bar;
1914         struct _ubar_item *cur;
1915         const char *id, *password, *icon;
1916
1917         if (!item) {
1918                 _ERR("Invalid argument");
1919                 return EINA_FALSE;
1920         }
1921
1922         bar = item->bar;
1923         cur = bar->popup_cur;
1924         if (!cur || !item->pw_entry || !item->id_entry) {
1925                 _ERR("failed to get current item");
1926                 return EINA_FALSE;
1927         }
1928
1929         id = elm_entry_entry_get(item->id_entry);
1930         if (!id)
1931                 return EINA_FALSE;
1932
1933         password = elm_entry_entry_get(item->pw_entry);
1934         if (!password || strlen(password) == 0) {
1935                 _ERR("wrong password");
1936                 _show_message(item, SIG_SHOW_WRONG_PW);
1937                 return EINA_FALSE;
1938         }
1939
1940         elm_image_file_get(cur->ic, &icon, NULL);
1941         if (!engine_ubar_item_add(bar->eng, id, password, icon)) {
1942                 _ERR("failed to add user");
1943                 _show_message(item, SIG_SHOW_SYSTEM_FAIL);
1944                 return EINA_FALSE;
1945         }
1946
1947         _destroy_popup(item);
1948
1949         evas_object_del(bar->ly);
1950         bar->ly = NULL;
1951
1952         _add_items(bar, bar->base);
1953         _update_items(bar, bar->eng);
1954
1955         return EINA_TRUE;
1956 }
1957
1958 static Eina_Bool _check_popup_state(struct _ubar_item *item)
1959 {
1960         struct _ubar_data *bar;
1961         Eina_Bool r;
1962
1963         if (!item) {
1964                 _ERR("Invalid argument");
1965                 return EINA_FALSE;
1966         }
1967
1968         bar = item->bar;
1969         r = EINA_FALSE;
1970
1971         switch (item->state) {
1972         case POPUP_STATE_ADD:
1973                 if (elm_object_focus_get(item->btn[0])) {
1974                         if (_check_add_user(item))
1975                                 r = EINA_TRUE;
1976                 } else if (elm_object_focus_get(item->btn[1])) {
1977                         _destroy_popup(item);
1978                         r = EINA_TRUE;
1979                 } else if (bar->popup_cur &&
1980                                 elm_object_focus_get(bar->popup_cur->eo)) {
1981                         elm_object_focus_set(item->id_entry, EINA_TRUE);
1982                         r = EINA_TRUE;
1983                 }
1984                 break;
1985         case POPUP_STATE_LOGIN:
1986                 if (elm_object_focus_get(item->btn[0])) {
1987                         if (_check_login_user(item))
1988                                 r = EINA_TRUE;
1989                 } else if (elm_object_focus_get(item->btn[1])) {
1990                         _destroy_popup(item);
1991                         r = EINA_TRUE;
1992                 }
1993                 break;
1994         case POPUP_STATE_DELETE:
1995                 if (elm_object_focus_get(item->btn[0])) {
1996                         if (_check_delete_user(item))
1997                                 r = EINA_TRUE;
1998                 } else if (elm_object_focus_get(item->btn[1])) {
1999                         _destroy_popup(item);
2000                         r = EINA_TRUE;
2001                 }
2002                 break;
2003         case POPUP_STATE_EDIT:
2004                 if (elm_object_focus_get(item->btn[0])) {
2005                         if (_check_edit_user(item))
2006                                 r = EINA_TRUE;
2007                 } else if (elm_object_focus_get(item->btn[1])){
2008                         _destroy_popup(item);
2009                         r = EINA_TRUE;
2010                 } else if (bar->popup_cur &&
2011                                 elm_object_focus_get(bar->popup_cur->eo)) {
2012                         elm_object_focus_set(item->pw_entry, EINA_TRUE);
2013                         r = EINA_TRUE;
2014                 }
2015                 break;
2016         default:
2017                 return EINA_FALSE;
2018         }
2019
2020         return r;
2021 }
2022
2023 static void _popup_add_clicked(void *data, Evas *e, Evas_Object *obj,
2024                 void *ei)
2025 {
2026         _check_add_user(data);
2027 }
2028
2029 static void _id_entry_focused(void *data, Evas_Object *obj, void *ei)
2030 {
2031         if (!elm_entry_is_empty(obj))
2032                 return;
2033
2034         elm_object_signal_emit(data, SIG_HIDE_ID, SRC_PROG);
2035 }
2036
2037 static void _id_entry_unfocused(void *data, Evas_Object *obj, void *ei)
2038 {
2039         if (!elm_entry_is_empty(obj))
2040                 return;
2041
2042         elm_object_signal_emit(data, SIG_SHOW_ID, SRC_PROG);
2043 }
2044
2045 static Eina_Bool _load_add_popup(struct _ubar_item *item)
2046 {
2047         struct _ubar_data *bar;
2048         Evas_Object *popup, *id_entry, *ly;
2049         struct _ubar_item *cur;
2050         struct _btn_info btn_info[] = {
2051                 {
2052                         "button1",
2053                         "Add",
2054                         _popup_add_clicked
2055                 },
2056                 {
2057                         "button2",
2058                         "Cancel",
2059                         _popup_cancel_clicked
2060                 }
2061         };
2062
2063         if (!item) {
2064                 _ERR("Invalid argument");
2065                 return EINA_FALSE;
2066         }
2067
2068         bar = item->bar;
2069
2070         popup = _add_popup(bar->base, TITLE_ADD_POPUP, NULL);
2071         if (!popup) {
2072                 _ERR("failed to create popup");
2073                 return EINA_FALSE;
2074         }
2075
2076         if (!_add_popup_btn(popup, item, btn_info,
2077                         sizeof(btn_info) / sizeof(btn_info[0]))) {
2078                 _ERR("failed to create popup button");
2079                 evas_object_del(popup);
2080                 return EINA_FALSE;
2081         }
2082
2083         ly = _add_popup_items(item, popup);
2084         if (!ly) {
2085                 _ERR("failed to create popup user");
2086                 evas_object_del(popup);
2087                 return EINA_FALSE;
2088         }
2089         evas_object_show(popup);
2090
2091         id_entry = _add_entry(ly, PART_POPUP_ENTRY_NAME, false);
2092         if (!id_entry) {
2093                 _ERR("failed to create name entry");
2094                 evas_object_del(ly);
2095                 return EINA_FALSE;
2096         }
2097         elm_object_signal_emit(ly, SIG_SHOW_ID, SRC_PROG);
2098         evas_object_smart_callback_add(id_entry, "focused", _id_entry_focused, ly);
2099         evas_object_smart_callback_add(id_entry, "unfocused", _id_entry_unfocused, ly);
2100
2101         if (bar->popup_list) {
2102                 cur = eina_list_data_get(bar->popup_list);
2103                 if (cur)
2104                         elm_object_focus_set(cur->eo, EINA_TRUE);
2105         }
2106
2107         elm_object_signal_emit(item->eo, SIG_HLIGHT_FROM_POPOVER, SRC_PROG);
2108
2109         item->id_entry = id_entry;
2110         item->popup = popup;
2111         item->state = POPUP_STATE_ADD;
2112
2113         return EINA_TRUE;
2114 }
2115
2116 static enum bar_event _enter(struct bar_info *info)
2117 {
2118         struct _ubar_data *bar;
2119         Eina_Bool r;
2120
2121         if (!info || !info->data) {
2122                 _ERR("Invalid argument");
2123                 return BAR_EVENT_ERROR;
2124         }
2125
2126         bar = info->data;
2127
2128         r = EINA_FALSE;
2129         switch (bar->state) {
2130         case UBAR_STATE_USER:
2131                 r = EINA_TRUE;
2132                 if (_check_guest_user(bar->user))
2133                         break;
2134                 break;
2135         case UBAR_STATE_ITEM:
2136                 r = EINA_TRUE;
2137                 if (_check_guest_user(bar->user)) {
2138                         if (!bar->cur->is_user){
2139                                 _load_add_popup(bar->cur);
2140                                 bar->state = UBAR_STATE_ITEM_POPUP;
2141                         } else {
2142                                 _create_ctxpopup(bar->cur);
2143                                 bar->state = UBAR_STATE_ITEM_CTXPOPUP;
2144                         }
2145                 }
2146                 break;
2147         case UBAR_STATE_USER_CTXPOPUP:
2148                 r = EINA_TRUE;
2149                 break;
2150         case UBAR_STATE_ITEM_CTXPOPUP:
2151                 if (!bar->cur->ctxpopup)
2152                         break;
2153
2154                 if (elm_object_focus_get(bar->cur->btn[0]))
2155                         r = _load_login_popup(bar->cur);
2156                 else if (elm_object_focus_get(bar->cur->btn[1])) {
2157                         r = _load_edit_popup(bar->cur);
2158                 } else if (elm_object_focus_get(bar->cur->btn[2])) {
2159                         r = _load_delete_popup(bar->cur);
2160                 }
2161                 break;
2162         case UBAR_STATE_USER_POPUP:
2163                 if (!bar->user->popup)
2164                         break;
2165
2166                 _destroy_popup(bar->user);
2167                 r = EINA_TRUE;
2168                 break;
2169         case UBAR_STATE_ITEM_POPUP:
2170                 if (!bar->cur->popup)
2171                         break;
2172
2173                 r = _check_popup_state(bar->cur);
2174                 break;
2175         default:
2176                 return BAR_EVENT_ERROR;
2177         }
2178
2179         return r ? BAR_EVENT_DONE : BAR_EVENT_PASS;
2180 }
2181
2182 static enum bar_event _key_down(struct bar_info *info, void *ei)
2183 {
2184         Ecore_Event_Key *ev;
2185         enum bar_event r;
2186
2187         if (!info || !ei)
2188                 return BAR_EVENT_ERROR;
2189
2190         ev = ei;
2191
2192         if (!strcmp(ev->keyname, KEY_ESC) ||
2193                         !strcmp(ev->keyname, KEY_ESC_REMOTE))
2194                 r = _back(info);
2195         else if (!strcmp(ev->keyname, KEY_RIGHT))
2196                 r = _move_right(info);
2197         else if (!strcmp(ev->keyname, KEY_LEFT))
2198                 r = _move_left(info);
2199         else if (!strcmp(ev->keyname, KEY_ENTER) ||
2200                         !strcmp(ev->keyname, KEY_ENTER_REMOTE))
2201                 r = _enter(info);
2202         else
2203                 r = BAR_EVENT_PASS;
2204
2205         return r;
2206 }
2207
2208 static void _hide(struct bar_info *info)
2209 {
2210         struct _ubar_data *bar;
2211
2212         if (!info || !info->data) {
2213                 _ERR("Invalid argument");
2214                 return;
2215         }
2216
2217         bar = info->data;
2218
2219         elm_object_signal_emit(bar->user->eo, SIG_UNFOCUS_TO_DOWN, SRC_PROG);
2220
2221         bar->state = UBAR_STATE_HIDE;
2222 }
2223
2224 static void _hide_bar(struct _ubar_data *bar)
2225 {
2226         struct _ubar_item *item;
2227         Eina_List *l;
2228
2229         if (!bar) {
2230                 _ERR("Invalid argument");
2231                 return;
2232         }
2233
2234         elm_object_signal_emit(bar->user->eo, SIG_HIDE, SRC_PROG);
2235
2236         EINA_LIST_FOREACH(bar->list, l, item)
2237                 elm_object_signal_emit(item->eo, SIG_HIDE, SRC_PROG);
2238
2239         elm_object_signal_emit(bar->ly, SIG_HIDE, SRC_PROG);
2240 }
2241
2242 static void _release(struct bar_info *info)
2243 {
2244         struct _ubar_data *bar;
2245         struct _ubar_item *item;
2246
2247         if (!info || !info->data) {
2248                 _ERR("Invalid argument");
2249                 return;
2250         }
2251
2252         bar = info->data;
2253
2254         _hide_bar(bar);
2255
2256         if (bar) {
2257                 EINA_LIST_FREE(bar->list, item) {
2258                         evas_object_del(item->eo);
2259                         free(item);
2260                 }
2261                 evas_object_del(bar->user->eo);
2262                 free(bar->user);
2263                 evas_object_del(bar->ly);
2264                 free(bar);
2265                 bar = NULL;
2266         }
2267
2268         free(info);
2269         info = NULL;
2270 }
2271
2272 static struct bar_ops ubar_ops = {
2273         .add_bar        = _add_bar,
2274         .update         = _update,
2275         .get_item       = _get_item,
2276         .hide           = _hide,
2277         .is_move        = _is_move,
2278         .move           = _move_user,
2279         .key_down       = _key_down,
2280         .release        = _release,
2281 };
2282
2283 int init_user_bar(struct bar_info *info)
2284 {
2285         struct _ubar_data *bar;
2286
2287         if (!info)
2288                 return -1;
2289
2290         bar = calloc(1, sizeof(*bar));
2291         if (!bar) {
2292                 _ERR("calloc failed");
2293                 return -1;
2294         }
2295
2296         info->data = bar;
2297         info->ops = &ubar_ops;
2298
2299         if (!info->cb.func) {
2300                 _ERR("invalid callback function");
2301                 free(bar);
2302                 return -1;
2303         }
2304
2305         bar->focus_cb = info->cb;
2306
2307         return 0;
2308 }