b373629bebc35da85e33d0fc2944cbf166e42ee6
[framework/uifw/elementary.git] / src / lib / elm_softkey.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Softkey Softkey
6  * @ingroup Elementary
7  *
8  * This is a softkey
9  */
10
11 /**
12  * internal data structure of softkey object
13  */
14 #define BTN_ANIMATOR_MAX        4
15 #define PANEL_ANIMATOR_MAX      1
16 typedef struct _Widget_Data Widget_Data;
17
18 struct _Widget_Data
19 {
20         Evas_Object *lay;
21         Evas_Object *button[2];
22         Evas_Object *bg_rect;
23         Evas_Object *panel;
24         Evas_Object *glow_obj;
25
26         Evas_Coord x, y, w, h;
27         Evas_Coord glow_w, glow_h;
28         Evas_Coord win_h;
29         Evas_Coord panel_height;
30         Ecore_Animator *animator;
31         Eina_List *items;
32         unsigned int panel_btn_idx;
33         Eina_Bool button_show[2];
34         Eina_Bool show_panel :1;
35         Eina_Bool animating :1;
36         Eina_Bool is_horizontal;
37         double scale_factor;
38         int max_button;
39         Eina_Bool panel_suppported;
40 };
41
42 struct _Elm_Softkey_Item
43 {
44         Evas_Object *obj;
45         Evas_Object *base;
46         Evas_Object *icon;
47         const char *label;
48         void (*func)(void *data, Evas_Object *obj, void *event_info);
49         const void *data;
50         Eina_Bool disabled :1;
51 };
52
53 static void _item_disable(Elm_Softkey_Item *it, Eina_Bool disabled);
54 static void _del_hook(Evas_Object *obj);
55 static void _theme_hook(Evas_Object *obj);
56 static void _sizing_eval(Evas_Object *obj);
57 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
58
59 /*
60  * callback functions
61  */
62 static void _softkey_down_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
63 static void _softkey_up_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
64
65 static void _panel_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
66 static void _panel_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
67
68 static void _more_btn_click_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
69 static void _close_btn_click_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
70 static void _bg_click_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
71
72 static int _show_button_animator_cb(void *data);
73 static int _hide_button_animator_cb(void *data);
74 static int _panel_up_animator_cb(void *data);
75 static int _panel_down_animator_cb(void *data);
76
77 /*
78  * internal function
79  */
80 static int
81 _show_button(Evas_Object *obj, Elm_Softkey_Type type, Eina_Bool show);
82 static int _delete_button(Evas_Object *obj);
83
84 static void _softkey_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
85 static void _softkey_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
86 static void _softkey_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info);
87 static void _softkey_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
88 static void _softkey_horizontal_set(Evas_Object *obj, Eina_Bool horizontal_mode);
89 static void _icon_disable(Evas_Object *icon, Eina_Bool disabled)
90 {
91         Evas_Object *edj;
92
93         if (!icon)
94                 return;
95         edj = elm_layout_edje_get(icon);
96
97         if (disabled) {
98                 if (!edj) {
99                         edje_object_signal_emit(icon, "elm,state,disabled", "elm");
100                 }
101                 else {
102                         edje_object_signal_emit(edj, "elm,state,disabled", "elm");
103                 }
104         }
105         else {
106                 if (!edj) {
107                         edje_object_signal_emit(icon, "elm,state,enabled", "elm");
108                 }
109                 else {
110                         edje_object_signal_emit(edj, "elm,state,enabled", "elm");
111                 }
112         }
113 }
114
115 static void _item_disable(Elm_Softkey_Item *it, Eina_Bool disabled)
116 {
117         Widget_Data *wd = elm_widget_data_get(it->obj);
118         if (!wd)
119                 return;
120         if (it->disabled == disabled)
121                 return;
122         it->disabled = disabled;
123         if (it->disabled) {
124                 edje_object_signal_emit(it->base, "elm,state,disabled", "elm");
125         }
126         else {
127                 edje_object_signal_emit(it->base, "elm,state,enabled", "elm");
128         }
129
130         _icon_disable(it->icon, disabled);
131 }
132
133 static void _del_hook(Evas_Object *obj)
134 {
135         int i;
136         Evas_Object *btn;
137         Widget_Data *wd = elm_widget_data_get(obj);
138
139         if (!wd)
140                 return;
141
142         if (wd->lay) {
143                 evas_object_del(wd->lay);
144                 wd->lay = NULL;
145         }
146
147         /* delete button */
148         for (i = 0; i < 2; i++) {
149                 btn = wd->button[i];
150                 if (btn != NULL) {
151                         _delete_button(btn);
152                 }
153         }
154
155         /* delete background */
156         if (wd->bg_rect) {
157                 evas_object_del(wd->bg_rect);
158                 wd->bg_rect = NULL;
159         }
160
161         /* delete panel */
162         if (wd->panel) {
163                 elm_softkey_panel_del(obj);
164                 //<Commenting as clean up for panel is being done in method elm_softkey_panel_del()
165                 /*evas_object_del(wd->panel);
166                  wd->panel = NULL;*/
167                 //<Commenting as clean up for panel is being done in method elm_softkey_panel_del()
168         }
169
170         /* delete glow effect image */
171         if (wd->glow_obj) {
172                 evas_object_del(wd->glow_obj);
173                 wd->glow_obj = NULL;
174         }
175
176         free(wd);
177 }
178
179 static void _theme_hook(Evas_Object *obj)
180 {
181         Elm_Softkey_Item* item;
182         Widget_Data *wd = elm_widget_data_get(obj);
183         Elm_Softkey_Item *it;
184         const Eina_List *l;
185
186         if (!wd) {
187                 return;
188         }
189         _elm_theme_object_set(obj, wd->lay, "softkey", "bg", elm_widget_style_get(obj));
190         _elm_theme_object_set(obj, wd->glow_obj, "softkey", "glow", "default");
191
192         if (wd->button[ELM_SK_LEFT_BTN]) {
193
194                 item = evas_object_data_get(wd->button[ELM_SK_LEFT_BTN], "item_data");
195                 _elm_theme_object_set(obj, wd->button[ELM_SK_LEFT_BTN], "softkey", "button_left", elm_widget_style_get(obj));
196
197                 elm_softkey_item_label_set(item, item->label);
198
199         }
200
201         if (wd->button[ELM_SK_RIGHT_BTN]) {
202
203                 item = evas_object_data_get(wd->button[ELM_SK_RIGHT_BTN], "item_data");
204
205                 _elm_theme_object_set(obj, wd->button[ELM_SK_RIGHT_BTN], "softkey", "button_right", elm_widget_style_get(obj));
206
207                 elm_softkey_item_label_set(item, item->label);
208
209         }
210
211         if (wd->panel) {
212                 _elm_theme_object_set(obj, wd->panel, "softkey", "panel", elm_widget_style_get(obj));
213                 if (wd->panel_btn_idx > 0) {
214                         //show more button
215                         edje_object_signal_emit(wd->lay, "more_btn_show", "");
216                         EINA_LIST_FOREACH (wd->items, l, it) {
217                                 _elm_theme_object_set(obj, it->base, "softkey", "panel_button", elm_widget_style_get(obj));
218                                 if (it->label) {
219                                         edje_object_part_text_set(it->base, "elm.text", it->label); // set text
220                                 }
221                         }
222                 }
223         }
224
225         _sizing_eval(obj);
226 }
227
228 static void _sub_del(void *data, Evas_Object *obj, void *event_info)
229 {
230         Widget_Data *wd = elm_widget_data_get(obj);
231         Evas_Object *sub = event_info;
232         const Eina_List *l;
233         Elm_Softkey_Item *it;
234         if (!wd)
235                 return;
236
237         EINA_LIST_FOREACH(wd->items, l, it) {
238                 if (sub == it->icon) {
239                         it->icon = NULL;
240                 }
241                 break;
242         }
243 }
244
245 static void _sizing_eval(Evas_Object *obj)
246 {
247         Widget_Data *wd = elm_widget_data_get(obj);
248
249         if (!wd)
250                 return;
251
252         _softkey_object_move(obj, NULL, obj, NULL);
253         _softkey_object_resize(obj, NULL, obj, NULL);
254 }
255
256 static int _panel_up_animator_cb(void *data)
257 {
258         int max = PANEL_ANIMATOR_MAX;
259         static int progress = 0;
260         Widget_Data *wd;
261         Evas_Coord ypos;
262
263         wd = elm_widget_data_get(data);
264         if (!wd)
265                 return 0;
266
267         progress++;
268         wd->animating = EINA_TRUE;
269
270         if (progress > max) {
271                 if (!wd->animator)
272                         return 0;
273                 ecore_animator_del(wd->animator);
274                 wd->animator = NULL;
275                 wd->animating = EINA_FALSE;
276                 wd->show_panel = EINA_TRUE;
277                 progress = 0;
278                 return 0;
279         }
280
281         /* move up panel */
282         if (wd->panel) {
283                 ypos = wd->win_h - (wd->panel_height * progress / max);
284                 evas_object_move(wd->panel, wd->x, ypos);
285         }
286
287         return 1;
288 }
289
290 static int _panel_down_animator_cb(void *data)
291 {
292         int max = PANEL_ANIMATOR_MAX;
293         static int progress = 0;
294         Widget_Data *wd;
295         Evas_Coord ypos;
296
297         wd = elm_widget_data_get(data);
298         if (!wd)
299                 return 0;
300
301         progress++;
302         wd->animating = EINA_TRUE;
303
304         if (progress > max) {
305                 if (!wd->animator)
306                         return 0;
307                 ecore_animator_del(wd->animator);
308                 wd->animator = NULL;
309                 wd->animating = EINA_FALSE;
310                 //wd->animator = ecore_animator_add(_show_button_animator_cb, data);
311                 wd->show_panel = EINA_FALSE;
312                 progress = 0;
313
314                 evas_object_smart_callback_call(data, "panel,hide", NULL);
315
316                 return 0;
317         }
318
319         /* move down panel */
320         if (wd->panel) {
321                 ypos = wd->win_h - wd->panel_height + (wd->panel_height * progress / max);
322                 evas_object_move(wd->panel, wd->x, ypos);
323         }
324
325         return 1;
326 }
327
328 static int _hide_button_animator_cb(void *data)
329 {
330         int max = BTN_ANIMATOR_MAX;
331         static int progress = 0;
332         Widget_Data *wd;
333         Evas_Coord btn_w, xpos;
334
335         wd = elm_widget_data_get(data);
336         if (!wd)
337                 return 0;
338
339         progress++;
340         wd->animating = EINA_TRUE;
341
342         if (progress > max) {
343                 if (!wd->animator)
344                         return 0;
345                 ecore_animator_del(wd->animator);
346                 wd->animating = EINA_FALSE;
347                 wd->animator = ecore_animator_add(_panel_up_animator_cb, data);
348                 progress = 0;
349                 return 0;
350         }
351
352         /* move left button */
353         if (wd->button[ELM_SK_LEFT_BTN]) {
354                 edje_object_part_geometry_get(wd->button[ELM_SK_LEFT_BTN], "button_rect", NULL, NULL, &btn_w, NULL);
355
356                 xpos = wd->x + -1 * btn_w * progress / max;
357                 evas_object_move(wd->button[ELM_SK_LEFT_BTN], xpos, wd->y);
358         }
359
360         /* move right button */
361         if (wd->button[ELM_SK_RIGHT_BTN]) {
362                 edje_object_part_geometry_get(wd->button[ELM_SK_RIGHT_BTN], "button_rect", NULL, NULL, &btn_w, NULL);
363
364                 xpos = (wd->x + wd->w - btn_w) + (btn_w * progress / max);
365                 evas_object_move(wd->button[ELM_SK_RIGHT_BTN], xpos, wd->y);
366         }
367
368         return 1;
369 }
370
371 static int _show_button_animator_cb(void *data)
372 {
373         int max = BTN_ANIMATOR_MAX;
374         static int progress = 0;
375         Widget_Data *wd;
376         Evas_Coord btn_w, xpos;
377
378         wd = elm_widget_data_get(data);
379         if (!wd)
380                 return 0;
381
382         progress++;
383
384         wd->animating = EINA_TRUE;
385
386         if (progress > max) {
387                 if (!wd->animator)
388                         return 0;
389                 ecore_animator_del(wd->animator);
390                 wd->animating = EINA_FALSE;
391                 progress = 0;
392                 return 0;
393         }
394
395         /* move left button */
396         if (wd->button[ELM_SK_LEFT_BTN]) {
397                 edje_object_part_geometry_get(wd->button[ELM_SK_LEFT_BTN], "button_rect", NULL, NULL, &btn_w, NULL);
398
399                 xpos = wd->x + (-1 * btn_w) + (btn_w * progress / max);
400                 evas_object_move(wd->button[ELM_SK_LEFT_BTN], xpos, wd->y);
401         }
402
403         /* move right button */
404         if (wd->button[ELM_SK_RIGHT_BTN]) {
405                 edje_object_part_geometry_get(wd->button[ELM_SK_RIGHT_BTN], "button_rect", NULL, NULL, &btn_w, NULL);
406
407                 xpos = wd->x + wd->w - (btn_w * progress / max);
408                 evas_object_move(wd->button[ELM_SK_RIGHT_BTN], xpos, wd->y);
409         }
410
411         return 1;
412 }
413
414 static void _more_btn_click_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
415 {
416         Widget_Data *wd;
417         wd = elm_widget_data_get(data);
418         if (!wd)
419                 return;
420
421         evas_object_smart_callback_call(data, "panel,show", NULL);
422
423         if (!wd->panel)
424                 return;
425         evas_object_show(wd->panel);
426
427         if (wd->bg_rect) {
428                 evas_object_show(wd->bg_rect);
429         }
430
431         /*if (wd->animating == EINA_FALSE) {
432                 wd->animator = ecore_animator_add(_hide_button_animator_cb, data);
433         }*/
434         if (wd->animating == EINA_FALSE) {
435                 wd->animator = ecore_animator_add(_panel_up_animator_cb, data);
436         }
437 }
438
439 static void _close_panel(Evas_Object *obj)
440 {
441         Widget_Data *wd;
442         wd = elm_widget_data_get(obj);
443         if (!wd)
444                 return;
445
446         if (wd->bg_rect) {
447                 evas_object_hide(wd->bg_rect);
448         }
449
450         if (!wd->panel)
451                 return;
452
453         if (wd->animating == EINA_FALSE) {
454                 wd->animator = ecore_animator_add(_panel_down_animator_cb, obj);
455         }
456 }
457
458 static void _bg_click_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
459 {
460         _close_panel(data);
461 }
462
463 static void _close_btn_click_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
464 {
465         _close_panel(data);
466 }
467
468 static int _show_button(Evas_Object *obj, Elm_Softkey_Type type, Eina_Bool show)
469 {
470         if (!obj)
471                 return -1;
472
473         Widget_Data *wd = elm_widget_data_get(obj);
474         Evas_Object *btn = wd->button[type];
475         if (!btn)
476                 return -1;
477
478         /* Make visible button */
479         if (show) {
480                 wd->button_show[type] = EINA_TRUE;
481                 evas_object_show(btn);
482         }
483         else {
484                 wd->button_show[type] = EINA_FALSE;
485                 evas_object_hide(btn);
486         }
487
488         return 0;
489 }
490
491 static int _arrange_button(Evas_Object *obj, Elm_Softkey_Type type)
492 {
493         Widget_Data *wd;
494         Evas_Coord btn_w = 0;
495         Evas_Object *btn;
496
497         if (!obj)
498                 return -1;
499         wd = elm_widget_data_get(obj);
500         if (!wd)
501                 return -1;
502
503         btn = wd->button[type];
504         if (!btn)
505                 return -1;
506
507         switch (type)
508         {
509                 case ELM_SK_LEFT_BTN:
510                         evas_object_move(btn, wd->x, wd->y);
511                         break;
512                 case ELM_SK_RIGHT_BTN:
513                         edje_object_part_geometry_get(btn, "button_rect", NULL, NULL, &btn_w, NULL);
514                         evas_object_move(btn, wd->x + wd->w - btn_w, wd->y);
515                         break;
516                 default:
517                         break;
518         }
519
520         return 0;
521 }
522
523 static void _softkey_up_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
524 {
525         Evas_Object *edj;
526
527         Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
528         elm_softkey_panel_close(it->obj);
529         if (it->icon)
530         {
531              edj = elm_layout_edje_get(it->icon);
532              if (!edj)
533                 return;
534              edje_object_signal_emit(edj, "elm,state,unselected", "elm");
535         }
536         if (it->func)
537                 it->func((void *) (it->data), it->obj, it);
538         evas_object_smart_callback_call(it->obj, "clicked", it);
539 }
540
541 static void _softkey_down_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
542 {
543         Evas_Object *edj;
544
545         Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
546         evas_object_smart_callback_call(it->obj, "press", it);
547
548         if (!it->icon)
549                 return;
550         edj = elm_layout_edje_get(it->icon);
551         if (!edj)
552                 return;
553
554         edje_object_signal_emit(edj, "elm,state,selected", "elm");
555 }
556
557 static void _panel_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
558 {
559         Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
560
561         Widget_Data *wd;
562         wd = elm_widget_data_get(it->obj);
563         if (wd == NULL)
564                 return;
565
566         /* hide glow effect */
567         if (wd->glow_obj) {
568                 evas_object_hide(wd->glow_obj);
569         }
570
571         elm_softkey_panel_close(it->obj);
572         if (it->func)
573                 it->func((void *) (it->data), it->obj, it);
574         evas_object_smart_callback_call(it->obj, "clicked", it);
575 }
576
577 static void _panel_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
578 {
579         Evas_Coord glow_x, glow_y;
580         Widget_Data *wd;
581
582         Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
583         wd = elm_widget_data_get(it->obj);
584         if (wd == NULL)
585                 return;
586
587         /* show glow effect */
588         if (wd->glow_obj) {
589                 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *) event_info;
590                 glow_x = ev->canvas.x - (wd->glow_w / 2);
591                 glow_y = ev->canvas.y - (wd->glow_h / 2);
592
593                 evas_object_move(wd->glow_obj, glow_x, glow_y);
594                 evas_object_show(wd->glow_obj);
595         }
596
597         evas_object_smart_callback_call(it->obj, "press", it);
598 }
599
600 static int _delete_button(Evas_Object *obj)
601 {
602         if (!obj)
603                 return -1;
604
605         if (obj) {
606                 evas_object_del(obj);
607                 obj = NULL;
608         }
609
610         return 0;
611 }
612
613 static void _calc_win_height(Widget_Data *wd)
614 {
615         wd->win_h = wd->y + wd->h;
616
617         if (wd->bg_rect) {
618                 evas_object_resize(wd->bg_rect, wd->w, wd->win_h);
619                 evas_object_move(wd->bg_rect, wd->x, 0);
620         }
621
622         if (wd->show_panel) {
623                 evas_object_move(wd->panel, wd->x, (wd->win_h - wd->panel_height));
624         }
625         else {
626                 evas_object_move(wd->panel, wd->x, wd->win_h);
627         }
628 }
629
630 static void _softkey_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
631 {
632         Widget_Data *wd;
633         int i;
634         Evas_Coord x, y;
635
636         if (!data)
637                 return;
638         wd = elm_widget_data_get((Evas_Object *) data);
639         if (!wd)
640                 return;
641
642         evas_object_geometry_get(wd->lay, &x, &y, NULL, NULL);
643
644         wd->x = x;
645         wd->y = y;
646
647         evas_object_move(wd->lay, x, y);
648
649         for (i = 0; i < 2; i++) {
650                 _arrange_button((Evas_Object *) data, i);
651         }
652
653         _calc_win_height(wd);
654 }
655
656 static void _softkey_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
657 {
658         Widget_Data *wd;
659         Evas_Object *btn;
660         int i;
661         Evas_Coord btn_w;
662         Evas_Coord w, h;
663
664         if (!data)
665                 return;
666         wd = elm_widget_data_get((Evas_Object *) data);
667         if (!wd)
668                 return;
669
670         evas_object_geometry_get(wd->lay, NULL, NULL, &w, &h);
671
672         wd->w = w;
673         wd->h = h;
674
675         if (!wd->lay)
676                 return;
677         evas_object_resize(wd->lay, w, h);
678
679         /* resize button */
680         for (i = 0; i < 2; i++) {
681                 btn = wd->button[i];
682                 if (btn != NULL) {
683                         edje_object_part_geometry_get(btn, "button_rect", NULL, NULL, &btn_w, NULL);
684                         evas_object_resize(btn, btn_w, h);
685                         _arrange_button((Evas_Object *) data, i);
686                 }
687         }
688
689         if (wd->w >= wd->win_h) {
690                 _softkey_horizontal_set(data, EINA_TRUE);
691         }
692         else {
693                 _softkey_horizontal_set(data, EINA_FALSE);
694         }
695         _calc_win_height(wd);
696 }
697
698 static void _softkey_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info)
699 {
700         Widget_Data *wd = NULL;
701         Evas_Object *btn;
702         int i;
703         if (data == NULL)
704                 return;
705         wd = elm_widget_data_get((Evas_Object *) data);
706         if (wd == NULL)
707                 return;
708
709         if (wd->lay) {
710                 evas_object_show(wd->lay);
711         }
712
713         /* show button */
714         for (i = 0; i < 2; i++) {
715                 btn = wd->button[i];
716                 if (btn != NULL && wd->button_show[i] == EINA_TRUE) {
717                         evas_object_show(btn);
718                         //evas_object_clip_set(btn, evas_object_clip_get((Evas_Object *)data));
719                 }
720         }
721         if (wd->panel_btn_idx > 0) {
722                 /* show more button */
723                 edje_object_signal_emit(wd->lay, "more_btn_show", "");
724         }
725 }
726
727 static void _softkey_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
728 {
729         Widget_Data *wd = NULL;
730         Evas_Object *btn;
731         int i;
732
733         if (data == NULL)
734                 return;
735         wd = elm_widget_data_get((Evas_Object *) data);
736         if (wd == NULL)
737                 return;
738
739         if (wd->lay) {
740                 evas_object_hide(wd->lay);
741         }
742
743         /* hide button */
744         for (i = 0; i < 2; i++) {
745                 btn = wd->button[i];
746                 if (btn != NULL) {
747                         evas_object_hide(btn);
748                 }
749         }
750
751         if (wd->panel_btn_idx > 0) {
752                 /* hide more button */
753                 edje_object_signal_emit(wd->lay, "more_btn_hide", "");
754         }
755 }
756
757 /**
758  * Add a new softkey to the parent
759
760  * @param parent the parent of the smart object
761  * @return              Evas_Object* pointer of softkey(evas object) or NULL
762  * @ingroup             Softkey 
763  */
764 EAPI Evas_Object *
765 elm_softkey_add(Evas_Object *parent)
766 {
767         Evas_Object *obj = NULL;
768         Widget_Data *wd = NULL;
769         Evas *e;
770
771         wd = ELM_NEW(Widget_Data);
772         e = evas_object_evas_get(parent);
773         if (e == NULL)
774                 return NULL;
775         obj = elm_widget_add(e);
776         elm_widget_type_set(obj, "softkey");
777         elm_widget_sub_object_add(parent, obj);
778         elm_widget_data_set(obj, wd);
779         elm_widget_del_hook_set(obj, _del_hook);
780         elm_widget_theme_hook_set(obj, _theme_hook);
781
782         /* load background edj */
783         wd->lay = edje_object_add(e);
784         _elm_theme_object_set(obj, wd->lay, "softkey", "bg", "default");
785         if (wd->lay == NULL) {
786                 printf("Cannot load bg edj\n");
787                 return NULL;
788         }
789         elm_widget_resize_object_set(obj, wd->lay);
790         edje_object_signal_callback_add(wd->lay, "clicked", "more_btn", _more_btn_click_cb, obj);
791
792         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _softkey_object_resize, obj);
793         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _softkey_object_move, obj);
794         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _softkey_object_show, obj);
795         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _softkey_object_hide, obj);
796         wd->is_horizontal = EINA_FALSE;
797         wd->panel_suppported = EINA_TRUE;
798         wd->scale_factor = elm_scale_get();
799         if (wd->scale_factor == 0.0) {
800                 wd->scale_factor = 1.0;
801         }
802
803         /* load glow effect */
804         wd->glow_obj = edje_object_add(e);
805         _elm_theme_object_set(obj, wd->glow_obj, "softkey", "glow", "default");
806         evas_object_geometry_get(wd->glow_obj, NULL, NULL, &wd->glow_w, &wd->glow_h);
807         evas_object_resize(wd->glow_obj, wd->glow_w, wd->glow_h);
808
809         // FIXME
810         evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
811
812         //      _sizing_eval(obj);
813
814         return obj;
815 }
816
817 static void _softkey_horizontal_set(Evas_Object *obj, Eina_Bool horizontal_mode)
818 {
819         Widget_Data *wd;
820         char buff[32];
821         if (!obj)
822                 return;
823         wd = elm_widget_data_get(obj);
824         if (!wd)
825                 return;
826         wd->is_horizontal = horizontal_mode;
827         if (wd->panel) {
828                 if ((edje_object_data_get(wd->panel, "max_item_count") == NULL) || (edje_object_data_get(wd->panel, "panel_height") == NULL) || (edje_object_data_get(wd->panel, "panel_height_horizontal") == NULL)) {
829                         wd->panel_suppported = EINA_FALSE;
830                 }
831                 else
832                         wd->panel_suppported = EINA_TRUE;
833                 if (wd->panel_suppported == EINA_TRUE) {
834                         if (wd->is_horizontal == EINA_TRUE) {
835                                 sprintf(buff, "button_%d", (wd->panel_btn_idx + wd->max_button));
836                                 edje_object_signal_emit(wd->panel, buff, "panel_rect");
837                                 wd->panel_height = (int) (atoi(edje_object_data_get(wd->panel, buff)) * wd->scale_factor);
838                                 evas_object_resize(wd->panel, wd->w, ((int) (atoi(edje_object_data_get(wd->panel, "panel_height_horizontal")) * wd->scale_factor)));
839                         }
840                         else {
841                                 sprintf(buff, "button_%d", (wd->panel_btn_idx));
842                                 edje_object_signal_emit(wd->panel, buff, "panel_rect");
843                                 wd->panel_height = (int) (atoi(edje_object_data_get(wd->panel, buff)) * wd->scale_factor);
844                                 evas_object_resize(wd->panel, wd->w, ((int) (atoi(edje_object_data_get(wd->panel, "panel_height")) * wd->scale_factor)));
845                         }
846                 }
847                 _calc_win_height(wd);
848         }
849
850 }
851
852 /**
853  * add side button of softkey
854  * @param       obj     softkey object 
855  * @param       type softkey button type
856  * @param       icon The icon object to use for the item
857  * @param       label The text label to use for the item
858  * @param       func Convenience function to call when this item is selected
859  * @param       data Data to pass to convenience function
860  * @return      A handle to the item added
861  * 
862  * @ingroup     Softkey  
863  */
864 EAPI Elm_Softkey_Item *
865 elm_softkey_button_add(Evas_Object *obj, Elm_Softkey_Type type, Evas_Object *icon, const char *label, void(*func)(void *data, Evas_Object *obj, void *event_info), const void *data)
866 {
867         Widget_Data *wd;
868         Evas* evas;
869         char button_type[64];
870         Elm_Softkey_Item *it;
871
872         if (!obj)
873                 return NULL;
874         wd = elm_widget_data_get(obj);
875         if (!wd)
876                 return NULL;
877
878         if (wd->button[type]) {
879                 printf("already created.\n");
880                 return NULL;
881         }
882
883         /* get evas */
884         evas = evas_object_evas_get(obj);
885         if (!evas)
886                 return NULL;
887
888         /* set item data */
889         it = ELM_NEW(Elm_Softkey_Item);
890         it->obj = obj;
891         it->func = func;
892         it->data = data;
893         it->label = NULL;
894         /* load button edj */
895         if (wd->button[type] == NULL) {
896                 if (type == ELM_SK_LEFT_BTN) {
897                         strcpy(button_type, "button_left");
898                 }
899                 else {
900                         strcpy(button_type, "button_right");
901                 }
902
903                 it->base = wd->button[type] = edje_object_add(evas);
904                 if (!wd->button[type]) {
905                         free(it);
906                         return NULL;
907                 }
908                 _elm_theme_object_set(obj, wd->button[type], "softkey", button_type, elm_widget_style_get(obj));
909
910                 wd->button_show[type] = EINA_TRUE;
911                 if (evas_object_visible_get(obj)) {
912                         evas_object_show(wd->button[type]);
913                 }
914                 evas_object_smart_member_add(wd->button[type], obj);
915
916                 edje_object_signal_callback_add(wd->button[type], "elm,action,down", "", _softkey_down_cb, it);
917                 edje_object_signal_callback_add(wd->button[type], "elm,action,click", "", _softkey_up_cb, it);
918
919                 evas_object_clip_set(wd->button[type], evas_object_clip_get(obj));
920                 if (wd->panel)
921                         evas_object_raise(wd->panel);
922         }
923
924         _sizing_eval(obj);
925
926         elm_softkey_item_label_set(it, label);
927         elm_softkey_item_icon_set(it, icon);
928         if (wd->button[type])
929                 evas_object_data_set(wd->button[type], "item_data", it);
930         else {
931                 if (it->label)
932                         eina_stringshare_del(it->label);
933                 it->label = NULL;
934                 free(it);
935                 return NULL;
936         }
937
938         return it;
939 }
940
941 /**
942  * delete side button of softkey
943  * @param       obj     softkey object 
944  * @param       type softkey button type
945  * 
946  * @ingroup     Softkey  
947  */
948 EAPI void elm_softkey_button_del(Evas_Object *obj, Elm_Softkey_Type type)
949 {
950         Widget_Data *wd;
951         Elm_Softkey_Item *it;
952         Evas_Object *btn;
953
954         if (!obj) {
955                 printf("Invalid argument: softkey object is NULL\n");
956                 return;
957         }
958
959         wd = elm_widget_data_get(obj);
960         if (!wd)
961                 return;
962
963         btn = wd->button[type];
964         if (!btn)
965                 return;
966
967         it = evas_object_data_get(btn, "item_data");
968         free(it);
969         _delete_button(btn);
970         wd->button[type] = NULL;
971 }
972
973 /**
974  * show button of softkey
975  * @param       obj     softkey object 
976  * @param       type    softkey button type
977  *
978  * @ingroup     Softkey  
979  */
980 EAPI void elm_softkey_button_show(Evas_Object *obj, Elm_Softkey_Type type)
981 {
982         _show_button(obj, type, EINA_TRUE);
983 }
984
985 /**
986  * hide button of softkey
987  * @param       obj     softkey object 
988  * @param       type    softkey button type
989  *
990  * @ingroup     Softkey  
991  */
992 EAPI void elm_softkey_button_hide(Evas_Object *obj, Elm_Softkey_Type type)
993 {
994         _show_button(obj, type, EINA_FALSE);
995 }
996
997 /**
998  * add item in panel
999  * @param       obj     softkey object 
1000  * @param       icon The icon object
1001  * @param       label The text label to use for the item
1002  * @param       func Convenience function to call when this item is selected
1003  * @param       data Data to pass to convenience function
1004  * @return      A handle to the item added
1005  * 
1006  * @ingroup     Softkey  
1007  */
1008 EAPI Elm_Softkey_Item *
1009 elm_softkey_panel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void(*func)(void *data, Evas_Object *obj, void *event_info), const void *data)
1010 {
1011         Widget_Data *wd;
1012         Evas *evas;
1013         char button_name[32];
1014         Evas_Object *btn;
1015         Elm_Softkey_Item *it;
1016         char buff[PATH_MAX];
1017
1018         wd = elm_widget_data_get(obj);
1019         if (!wd) {
1020                 printf("Cannot get smart data\n");
1021                 return NULL;
1022         }
1023
1024         /* get evas */
1025         evas = evas_object_evas_get(obj);
1026         if (!evas)
1027                 return NULL;
1028
1029         if (wd->panel == NULL) {
1030                 /* create panel */
1031                 wd->bg_rect = evas_object_rectangle_add(evas);
1032                 if (!wd->bg_rect)
1033                         return NULL;
1034                 evas_object_color_set(wd->bg_rect, 10, 10, 10, 150);
1035                 evas_object_pass_events_set(wd->bg_rect, 0);
1036
1037                 if (wd->bg_rect) {
1038                         evas_object_resize(wd->bg_rect, wd->w, wd->win_h);
1039                         evas_object_event_callback_add(wd->bg_rect, EVAS_CALLBACK_MOUSE_UP, _bg_click_cb, obj);
1040                         evas_object_smart_member_add(wd->bg_rect, obj);
1041                 }
1042
1043                 wd->panel = edje_object_add(evas);
1044                 if (!wd->panel)
1045                         return NULL;
1046                 _elm_theme_object_set(obj, wd->panel, "softkey", "panel", elm_widget_style_get(obj));
1047
1048                 evas_object_move(wd->panel, 0, wd->win_h);
1049                 edje_object_signal_callback_add(wd->panel, "clicked", "close_btn", _close_btn_click_cb, obj);
1050                 evas_object_smart_member_add(wd->panel, obj);
1051                 if (evas_object_visible_get(obj)) {
1052                         evas_object_show(wd->panel);
1053                 }
1054                 wd->panel_height = 0;
1055                 if ((edje_object_data_get(wd->panel, "max_item_count") == NULL) || (edje_object_data_get(wd->panel, "panel_height") == NULL) || (edje_object_data_get(wd->panel, "panel_height_horizontal") == NULL)) {
1056                         //If this key is not found in data section, then it means the panel won't come.
1057                         wd->max_button = 0;
1058                         // delete panel
1059                         if (wd->panel) {
1060                                 elm_softkey_panel_del(obj);
1061                         }
1062                         wd->panel_suppported = EINA_FALSE;
1063                         return NULL;
1064                 }
1065                 else {
1066                         wd->max_button = (int) (atoi(edje_object_data_get(wd->panel, "max_item_count")));
1067                         if (wd->is_horizontal) {
1068                                 evas_object_resize(wd->panel, wd->w, ((int) (atoi(edje_object_data_get(wd->panel, "panel_height_horizontal")) * wd->scale_factor)));
1069                         }
1070                         else {
1071                                 evas_object_resize(wd->panel, wd->w, ((int) (atoi(edje_object_data_get(wd->panel, "panel_height")) * wd->scale_factor)));
1072                         }
1073                 }
1074
1075                 evas_object_clip_set(wd->panel, evas_object_clip_get(obj));
1076         }
1077
1078         wd->panel_btn_idx++;
1079         if (wd->panel_btn_idx >= wd->max_button)
1080                 return NULL;
1081
1082         /* set item data */
1083         it = ELM_NEW(Elm_Softkey_Item);
1084         wd->items = eina_list_append(wd->items, it);
1085         it->obj = obj;
1086         if (label)
1087                 it->label = eina_stringshare_add(label);
1088         it->icon = icon;
1089         it->func = func;
1090         it->data = data;
1091         /* load panel button */
1092         it->base = btn = edje_object_add(evas);
1093         if (!btn) {
1094                 if (it->label)
1095                         eina_stringshare_del(it->label);
1096                 free(it);
1097                 wd->panel_btn_idx--;
1098                 return NULL;
1099         }
1100         _elm_theme_object_set(obj, btn, "softkey", "panel_button", elm_widget_style_get(obj));
1101
1102         edje_object_part_text_set(btn, "elm.text", label); /* set text */
1103         edje_object_message_signal_process(btn);
1104
1105         evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_DOWN, _panel_down_cb, it);
1106         evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_UP, _panel_up_cb, it);
1107
1108         if (wd->panel) {
1109                 /* swallow button */
1110                 sprintf(button_name, "panel_button_area_%d", wd->panel_btn_idx);
1111                 edje_object_part_swallow(wd->panel, button_name, btn);
1112
1113                 if (wd->is_horizontal) {
1114                         sprintf(buff, "button_%d", wd->max_button + wd->panel_btn_idx);
1115                         edje_object_signal_emit(wd->panel, buff, "panel_rect");
1116                         const char* val = edje_object_data_get(wd->panel, buff);
1117                         if (val)
1118                                 wd->panel_height = (int) (atoi(val) * wd->scale_factor);
1119                         else {
1120                                 if (it->label)
1121                                         eina_stringshare_del(it->label);
1122                                 evas_object_del(it->base);
1123                                 free(it);
1124                                 wd->panel_btn_idx--;
1125                                 return NULL;
1126                         }
1127                 }
1128                 else {
1129                         sprintf(buff, "button_%d", wd->panel_btn_idx);
1130                         edje_object_signal_emit(wd->panel, buff, "panel_rect");
1131                         const char* val = edje_object_data_get(wd->panel, buff);
1132                         if (val)
1133                                 wd->panel_height = (int) (atoi(val) * wd->scale_factor);
1134                         else {
1135                                 if (it->label)
1136                                         eina_stringshare_del(it->label);
1137                                 evas_object_del(it->base);
1138                                 free(it);
1139                                 wd->panel_btn_idx--;
1140                                 return NULL;
1141                         }
1142                 }
1143         }
1144         else {
1145                 wd->panel_btn_idx--;
1146                 return NULL;
1147         }
1148
1149         if (evas_object_visible_get(obj)) {
1150                 /* show more button */
1151                 edje_object_signal_emit(wd->lay, "more_btn_show", "");
1152         }
1153         return it;
1154 }
1155
1156 /**
1157  * delete panel
1158
1159  * @param obj softkey object
1160  * @return int 0 (SUCCESS) or -1 (FAIL)
1161  *
1162  * @ingroup Softkey
1163  */
1164 EAPI int elm_softkey_panel_del(Evas_Object *obj)
1165 {
1166         Widget_Data *wd;
1167         char button_name[32];
1168         Evas_Object *btn;
1169         int i;
1170         Elm_Softkey_Item *it;
1171
1172         wd = elm_widget_data_get(obj);
1173         if (!wd)
1174                 return -1;
1175         if (wd->panel == NULL)
1176                 return -1;
1177         if(wd->animator) {
1178            ecore_animator_del(wd->animator);
1179            wd->animator = NULL;
1180            wd->animating=EINA_FALSE;
1181         }
1182
1183         for (i = 1; i <= wd->panel_btn_idx; i++) {
1184                 sprintf(button_name, "panel_button_area_%d", i);
1185                 btn = edje_object_part_swallow_get(wd->panel, button_name);
1186                 _delete_button(btn);
1187         }
1188
1189         EINA_LIST_FREE(wd->items, it) {
1190                 eina_stringshare_del(it->label);
1191                 free(it);
1192         }
1193
1194         wd->panel_btn_idx = 0;
1195         wd->panel_height = 0;
1196
1197         //hide more button
1198         edje_object_signal_emit(wd->lay, "more_btn_hide", "");
1199
1200         if (wd->panel) {
1201                 evas_object_move(wd->panel, 0, wd->win_h);
1202                 evas_object_clip_unset(wd->panel);
1203                 //<Added to delete the panel completely>
1204                 evas_object_del(wd->panel);
1205                 wd->panel = NULL;
1206                 //<Added to delete the panel completely>
1207         }
1208
1209         return 0;
1210 }
1211
1212 /**
1213  * sliding up panel if it is closed
1214
1215  * @param obj softkey object
1216  * @return int 0 (SUCCESS) or -1 (FAIL)
1217  *
1218  * @ingroup Softkey
1219  */
1220 EAPI int elm_softkey_panel_open(Evas_Object *obj)
1221 {
1222         Widget_Data *wd;
1223         wd = elm_widget_data_get(obj);
1224
1225         if (!wd)
1226                 return -1;
1227         if (!wd->panel)
1228                 return -1;
1229
1230         if (wd->show_panel == EINA_FALSE) {
1231                 _more_btn_click_cb(obj, NULL, NULL, NULL);
1232         }
1233
1234         return 0;
1235 }
1236
1237 /**
1238  * sliding down panel if it is opened
1239
1240  * @param obj softkey object
1241  * @return int 0 (SUCCESS) or -1 (FAIL)
1242  *
1243  * @ingroup Softkey
1244  */
1245 EAPI int elm_softkey_panel_close(Evas_Object *obj)
1246 {
1247         Widget_Data *wd;
1248         wd = elm_widget_data_get(obj);
1249         if (!wd)
1250                 return -1;
1251
1252         if (wd->panel == NULL)
1253                 return -1;
1254
1255         if (wd->show_panel == EINA_TRUE) {
1256                 _close_btn_click_cb(obj, obj, NULL, NULL);
1257         }
1258
1259         return 0;
1260 }
1261
1262 /**
1263  * Set the icon of an softkey item
1264  *
1265  * @param it The item to set the icon
1266  * @param icon The icon object
1267  *
1268  * @ingroup Softkey
1269  */
1270 EAPI void elm_softkey_item_icon_set(Elm_Softkey_Item *it, Evas_Object *icon)
1271 {
1272         if (!it)
1273                 return;
1274
1275         if ((it->icon != icon) && (it->icon))
1276                 elm_widget_sub_object_del(it->obj, it->icon);
1277
1278         if ((icon) && (it->icon != icon)) {
1279                 it->icon = icon;
1280                 elm_widget_sub_object_add(it->obj, icon);
1281                 //evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
1282                 //edje_object_part_swallow(it->base, "elm.swallow.content", icon);
1283                 edje_object_part_swallow(it->base, "elm.swallow.icon", icon);
1284                 edje_object_signal_emit(it->base, "elm,state,icon,visible", "elm");
1285                 edje_object_message_signal_process(it->base);
1286                 _sizing_eval(it->obj);
1287         }
1288         else
1289                 it->icon = icon;
1290 }
1291
1292 /**
1293  * Get the icon of an softkey item
1294  *
1295  * @param it The item to get the icon
1296  * @return The icon object
1297  *
1298  * @ingroup Softkey
1299  */
1300 EAPI Evas_Object *
1301 elm_softkey_item_icon_get(Elm_Softkey_Item *it)
1302 {
1303         if (!it)
1304                 return NULL;
1305         return it->icon;
1306 }
1307
1308 /**
1309  * Get the text label of an softkey item
1310  *
1311  * @param it The item to set the label
1312  * @param label label
1313  *
1314  * @ingroup Softkey
1315  */
1316 EAPI void elm_softkey_item_label_set(Elm_Softkey_Item *it, const char *label)
1317 {
1318         if (!it)
1319                 return;
1320         if (it->label)
1321                 eina_stringshare_del(it->label);
1322
1323         if (label) {
1324                 it->label = eina_stringshare_add(label);
1325                 edje_object_signal_emit(it->base, "elm,state,text,visible", "elm");
1326
1327                 /* set text */
1328                 edje_object_part_text_set(it->base, "elm.text", label == NULL ? "" : label);
1329         }
1330         else {
1331                 it->label = NULL;
1332                 edje_object_signal_emit(it->base, "elm,state,text,hidden", "elm");
1333         }
1334         edje_object_message_signal_process(it->base);
1335 }
1336
1337 /**
1338  * Set the item callback function 
1339  *
1340  * @param it Item to set callback function.
1341  * @param func callback function pointer.
1342  * @param data callback function argument data.
1343  *
1344  * @ingroup Softkey
1345  */
1346 EAPI void elm_softkey_item_callback_set(Elm_Softkey_Item* item, void(*func)(void *data, Evas_Object *obj, void *event_info), const void *data)
1347 {
1348         if (!item)
1349                 return;
1350
1351         item->func = func;
1352         item->data = data;
1353
1354 }
1355
1356 /**
1357  * Get the text label of an softkey item
1358  *
1359  * @param it The item to get the label
1360  * @return The text label of the softkey item
1361  *
1362  * @ingroup Softkey
1363  */
1364 EAPI const char *
1365 elm_softkey_item_label_get(Elm_Softkey_Item *it)
1366 {
1367         if (!it)
1368                 return NULL;
1369         return it->label;
1370 }
1371
1372 EAPI Eina_Bool elm_softkey_item_disabled_get(Elm_Softkey_Item *it)
1373 {
1374         if (!it)
1375                 return EINA_FALSE;
1376         return it->disabled;
1377 }
1378
1379 EAPI void elm_softkey_item_disabled_set(Elm_Softkey_Item *it, Eina_Bool disabled)
1380 {
1381         if (!it)
1382                 return;
1383         _item_disable(it, disabled);
1384 }