ctxpopup: delete objects when failed to create
[profile/tv/apps/native/air_mediahub.git] / src / util / ctxpopup.c
1 /*
2  * Copyright (c) 2015 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 <stdbool.h>
18 #include <Elementary.h>
19 #include <app_debug.h>
20 #include <inputmgr.h>
21
22 #include "define.h"
23 #include "util/ctxpopup.h"
24 #include "util/util.h"
25
26 struct _selected_cb {
27         void (*func)(void *data, int id);
28         void *data;
29 };
30
31 struct ctxpopup {
32         Evas_Object *popup;
33         struct _selected_cb cb;
34 };
35
36 static void _key_down_cb(int id, void *data, Evas *e, Evas_Object *obj,
37                         Evas_Event_Key_Down *ev)
38 {
39         struct ctxpopup *m;
40
41         if (!data || !ev)
42                 return;
43
44         m = data;
45
46         if (!strcmp(ev->keyname, KEY_BACK) ||
47                 !strcmp(ev->keyname, KEY_ESC))
48                 ctxpopup_destroy(m);
49 }
50
51 static void _mouse_move_cb(int id, void *data, Evas *e, Evas_Object *obj,
52                         Evas_Event_Mouse_Move *ev)
53 {
54         if (!obj)
55                 return;
56
57         if (!elm_object_focus_get(obj))
58                 elm_object_focus_set(obj, EINA_TRUE);
59 }
60
61 static void _clicked_cb(int id, void *data, Evas_Object *obj)
62 {
63         struct ctxpopup *m;
64
65         if (!data)
66                 return;
67
68         m = data;
69
70         if (m->cb.func)
71                 m->cb.func(m->cb.data, id);
72
73         ctxpopup_destroy(m);
74 }
75
76 static void _dismissed_cb(void *data, Evas_Object *obj, void *event_info)
77 {
78         struct ctxpopup *m;
79
80         if (!data)
81                 return;
82
83         m = data;
84
85         ctxpopup_destroy(m);
86 }
87
88 static input_handler _handler = {
89         .key_down = _key_down_cb,
90         .mouse_move = _mouse_move_cb,
91         .clicked = _clicked_cb
92 };
93
94 void ctxpopup_set_callback(struct ctxpopup *m, void (*func)(void *, int),
95                         void *data)
96 {
97         if (!m) {
98                 _ERR("failed to get ctxpopup info");
99                 return;
100         }
101
102         m->cb.func = func;
103         m->cb.data = data;
104 }
105
106 void ctxpopup_show(struct ctxpopup *m, int x, int y)
107 {
108         if (!m) {
109                 _ERR("failed to get ctxpopup info");
110                 return;
111         }
112
113         evas_object_move(m->popup, x * elm_config_scale_get(),
114                                 y * elm_config_scale_get());
115
116         evas_object_show(m->popup);
117 }
118
119 struct ctxpopup *ctxpopup_create(Evas_Object *base, const char *ctxpopup_style,
120                         const char *btn_style, const char **text, int text_size)
121 {
122         struct ctxpopup *m;
123         Evas_Object *ctxpopup, *box, *btn;
124         Evas_Object *firstbtn;
125         int i;
126
127         if (!base || !text || text_size <= 0) {
128                 _ERR("invalid argument");
129                 return NULL;
130         }
131
132         m = calloc(1, sizeof(*m));
133         if (!m) {
134                 _ERR("failed to allocate");
135                 return NULL;
136         }
137
138         ctxpopup = elm_ctxpopup_add(base);
139         if (!ctxpopup) {
140                 _ERR("failed to create ctxpopup object");
141                 free(m);
142                 return NULL;
143         }
144
145         if (ctxpopup_style)
146                 elm_object_style_set(ctxpopup, ctxpopup_style);
147
148         box = util_add_box(ctxpopup, EINA_FALSE);
149         if (!box) {
150                 _ERR("failed to add box");
151                 evas_object_del(ctxpopup);
152                 free(m);
153                 return false;
154         }
155
156         elm_box_padding_set(box, 0, 0);
157
158         for (i = 0; i < text_size; i++) {
159                 btn = util_add_button(box, btn_style, text[i]);
160                 if (!btn) {
161                         _ERR("failed to add button");
162                         evas_object_del(ctxpopup);
163                         free(m);
164                         return false;
165                 }
166
167                 elm_box_pack_end(box, btn);
168
169                 evas_object_show(btn);
170
171                 inputmgr_add_callback(btn, i, &_handler, m);
172
173                 if (i == 0)
174                         firstbtn = btn;
175         }
176
177         elm_object_focus_next_object_set(firstbtn, btn, ELM_FOCUS_UP);
178         elm_object_focus_next_object_set(btn, firstbtn, ELM_FOCUS_DOWN);
179
180         elm_object_content_set(ctxpopup, box);
181
182         evas_object_smart_callback_add(ctxpopup, SIG_DISMISSED,
183                                 _dismissed_cb, m);
184
185         m->popup = ctxpopup;
186
187         return m;
188 }
189
190 void ctxpopup_destroy(struct ctxpopup *m)
191 {
192         if (!m) {
193                 _ERR("failed to get ctxpopup info");
194                 return;
195         }
196
197         evas_object_hide(m->popup);
198         evas_object_del(m->popup);
199
200         free(m);
201 }