37f34c93d4ff5e239a69146aabc2af446bacb75e
[profile/tv/apps/native/air_home.git] / src / view / view_action_menu.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 <Elementary.h>
18 #include <app_debug.h>
19 #include <viewmgr.h>
20 #include <inputmgr.h>
21
22 #include "defs.h"
23 #include "view.h"
24 #include "utils.h"
25
26 #define ACTION_MENU_TITLE_RESET "Reset"
27
28 enum input_handler_type {
29         INPUT_HANDLER_TYPE_BTN,
30         INPUT_HANDLER_TYPE_ITEM,
31         INPUT_HANDLER_TYPE_RESET,
32         INPUT_HANDLER_TYPE_DISCARD,
33         INPUT_HANDLER_TYPE_CANCEL
34 };
35
36 struct _priv {
37         Evas_Object *win;
38         Evas_Object *base;
39         Evas_Object *btn;
40         Evas_Object *item;
41         Evas_Object *popup;
42
43         bool edited;
44 };
45
46 static void _focused(int id, void *data, Evas_Object *obj,
47                 Elm_Object_Item *item)
48 {
49         elm_object_signal_emit(obj, SIG_FOCUS, SRC_PROG);
50 }
51
52 static void _unfocused(int id, void *data, Evas_Object *obj,
53                 Elm_Object_Item *item)
54 {
55         elm_object_signal_emit(obj, SIG_UNFOCUS, SRC_PROG);
56 }
57
58 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
59                 Evas_Event_Key_Down *ev);
60
61 static void _mouse_down(int id, void *data, Evas *e, Evas_Object *obj,
62                 Evas_Event_Mouse_Down *ev);
63
64 static void _mouse_move(int id, void *data, Evas *e, Evas_Object *obj,
65                 Evas_Event_Mouse_Move *ev)
66 {
67         if (!elm_object_focus_get(obj))
68                 elm_object_focus_set(obj, EINA_TRUE);
69 }
70
71 static input_handler handler = {
72         .focused = _focused,
73         .unfocused = _unfocused,
74         .key_down = _key_down,
75         .mouse_down = _mouse_down,
76         .mouse_move = _mouse_move
77 };
78
79 static void _add_popup(struct _priv *priv, char *title, char *message,
80                 char *first_btn_message, int first_btn_id,
81                 char *second_btn_message, int second_btn_id)
82 {
83         Evas_Object *popup, *first_btn, *second_btn;
84
85         popup = utils_add_popup(priv->base, title, message);
86         if (!popup) {
87                 _ERR("failed to add popup");
88                 return;
89         }
90
91         first_btn = utils_add_button(popup, first_btn_message,
92                         PART_POPUP_BUTTON_1);
93         if (!first_btn) {
94                 _ERR("failed to add delete btn");
95                 evas_object_del(popup);
96                 return;
97         }
98         inputmgr_add_callback(first_btn, first_btn_id, &handler, priv);
99
100         second_btn = utils_add_button(popup, second_btn_message,
101                         PART_POPUP_BUTTON_2);
102         if (!second_btn) {
103                 _ERR("failed to add cancel btn");
104                 evas_object_del(popup);
105                 return;
106         }
107         inputmgr_add_callback(second_btn, second_btn_id, &handler, priv);
108         elm_object_focus_set(second_btn, EINA_TRUE);
109
110         priv->popup = popup;
111 }
112
113 static void _delete_popup(struct _priv *priv, Evas_Object *obj)
114 {
115         inputmgr_remove_callback(obj, &handler);
116         evas_object_del(priv->popup);
117         priv->popup = NULL;
118 }
119
120 static void _select(int id, void *data, Evas_Object *obj)
121 {
122         struct _priv *priv;
123
124         priv = data;
125
126         switch (id) {
127         case INPUT_HANDLER_TYPE_BTN:
128                 if (priv->edited) {
129                         _add_popup(priv, MESSAGE_DISCARD,
130                                         MESSAGE_DISCARD_CONTENTS,
131                                         MESSAGE_DISCARD,
132                                         INPUT_HANDLER_TYPE_DISCARD,
133                                         MESSAGE_CANCEL,
134                                         INPUT_HANDLER_TYPE_CANCEL);
135                         return;
136                 }
137                 viewmgr_update_view(VIEW_USER_EDIT, UPDATE_TYPE_RESET, NULL);
138                 viewmgr_hide_view(VIEW_ACTION_MENU);
139                 break;
140         case INPUT_HANDLER_TYPE_ITEM:
141                 _add_popup(priv, MESSAGE_RESET, MESSAGE_RESET_CONTENTS,
142                                 MESSAGE_RESET, INPUT_HANDLER_TYPE_RESET,
143                                 MESSAGE_CANCEL, INPUT_HANDLER_TYPE_CANCEL);
144                 break;
145         case INPUT_HANDLER_TYPE_RESET:
146         case INPUT_HANDLER_TYPE_DISCARD:
147                 viewmgr_update_view(VIEW_USER_EDIT, UPDATE_TYPE_RESET, NULL);
148                 viewmgr_hide_view(VIEW_ACTION_MENU);
149                 _delete_popup(priv, obj);
150                 break;
151         case INPUT_HANDLER_TYPE_CANCEL:
152                 _delete_popup(priv, obj);
153                 break;
154         default:
155                 return;
156         }
157 }
158
159 static void _key_down(int id, void *data, Evas *e, Evas_Object *obj,
160                 Evas_Event_Key_Down *ev)
161 {
162         struct _priv *priv;
163
164         if (!data) {
165                 _ERR("Invalid argument");
166                 return;
167         }
168
169         priv = data;
170         if (!strcmp(ev->keyname, KEY_BACK) ||
171                         !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
172                 switch (id) {
173                 case INPUT_HANDLER_TYPE_BTN:
174                 case INPUT_HANDLER_TYPE_ITEM:
175                         viewmgr_hide_view(VIEW_ACTION_MENU);
176                         break;
177                 case INPUT_HANDLER_TYPE_RESET:
178                 case INPUT_HANDLER_TYPE_DISCARD:
179                 case INPUT_HANDLER_TYPE_CANCEL:
180                         if (priv->popup)
181                                 _delete_popup(priv, obj);
182                         break;
183                 default:
184                         return;
185                 }
186         } else if (!strcmp(ev->keyname, KEY_ENTER) ||
187                         !strcmp(ev->keyname, KEY_ENTER_REMOTE)) {
188                 _select(id, data, obj);
189         }
190 }
191
192 static void _mouse_down(int id, void *data, Evas *e, Evas_Object *obj,
193                 Evas_Event_Mouse_Down *ev)
194 {
195         if (!data || !obj) {
196                 _ERR("Invalid argument");
197                 return;
198         }
199
200         _select(id, data, obj);
201 }
202
203 static Evas_Object *_add_item(Evas_Object *box, struct _priv *priv)
204 {
205         Evas_Object *item, *ic, *focus_ic, *lbl, *focus_lbl, *bg;
206
207         item = utils_add_layout(box, GRP_ACTION_MENU_TABLE_ITEM, true, NULL);
208         if (!item) {
209                 _ERR("failed to add item");
210                 evas_object_del(box);
211                 return false;
212         }
213
214         ic = utils_add_icon(item, IMAGE_ACTION_MENU_ICON_RESET,
215                         PART_ACTION_MENU_TABLE_ITEM_ICON);
216         if (!ic)
217                 goto err;
218
219         focus_ic = utils_add_icon(item, IMAGE_ACTION_MENU_ICON_RESET_FOCUS,
220                         PART_ACTION_MENU_TABLE_ITEM_ICON_FOCUS);
221         if (!focus_ic)
222                 goto err;
223
224         lbl = utils_add_label(item, ACTION_MENU_TITLE_RESET,
225                         STYLE_LABEL_ACTION_MENU_TITLE,
226                         PART_ACTION_MENU_TABLE_ITEM_TEXT);
227         if (!lbl)
228                 goto err;
229
230         focus_lbl = utils_add_label(item, ACTION_MENU_TITLE_RESET,
231                         STYLE_LABEL_ACTION_MENU_TITLE_FOCUS,
232                         PART_ACTION_MENU_TABLE_ITEM_TEXT_FOCUS);
233         if (!focus_lbl)
234                 goto err;
235
236         bg = utils_add_bg(item, COLOR_DEFAULT_R, COLOR_DEFAULT_G,
237                         COLOR_DEFAULT_B, COLOR_DEFAULT_A,
238                         PART_ACTION_MENU_TABLE_ITEM_BG);
239         if (!bg)
240                 goto err;
241
242         evas_object_show(item);
243         inputmgr_add_callback(item, INPUT_HANDLER_TYPE_ITEM, &handler, priv);
244
245         return item;
246 err:
247         evas_object_del(item);
248         return NULL;
249 }
250
251 static bool _add_menu(struct _priv *priv)
252 {
253         Evas_Object *btn, *box, *item;
254
255         btn = utils_add_layout(priv->base, GRP_ACTION_MENU_LIVETV, true,
256                         PART_ACTION_MENU_LIVETV);
257         if (!btn) {
258                 _ERR("failed to add btn");
259                 return false;
260         }
261         inputmgr_add_callback(btn, INPUT_HANDLER_TYPE_BTN, &handler, priv);
262         priv->btn = btn;
263
264         box = utils_add_box(priv->base, true);
265         if (!box) {
266                 _ERR("failed to add box");
267                 return false;
268         }
269         elm_object_part_content_set(priv->base, PART_ACTION_MENU_TABLE, box);
270         elm_box_align_set(box, 0.0, 0.5);
271
272         item = _add_item(box, priv);
273         if (!item) {
274                 _ERR("failed to add item");
275                 evas_object_del(box);
276                 return false;
277         }
278
279         elm_box_pack_start(box, item);
280         priv->item = item;
281
282         return true;
283 }
284
285 static Evas_Object *_create(Evas_Object *win, void *data)
286 {
287         struct _priv *priv;
288         Evas_Object *base;
289
290         priv = calloc(1, sizeof(*priv));
291         if (!priv) {
292                 _ERR("failed to calloc priv");
293                 return NULL;
294         }
295
296         base = utils_add_layout(win, GRP_ACTION_MENU, false, NULL);
297         if (!base) {
298                 _ERR("failed to create base");
299                 free(priv);
300                 return NULL;
301         }
302         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
303                         EVAS_HINT_EXPAND);
304         elm_win_resize_object_add(win, base);
305
306         priv->win = win;
307         priv->base = base;
308
309         if (!_add_menu(priv)) {
310                 _ERR("failed to add menu");
311                 free(priv);
312                 evas_object_del(base);
313                 return NULL;
314         }
315
316         viewmgr_set_view_data(VIEW_ACTION_MENU, priv);
317
318         return base;
319 }
320
321 static void _show(void *data)
322 {
323         struct _priv *priv;
324
325         if (!data) {
326                 _ERR("Invalid argument");
327                 return;
328         }
329
330         priv = data;
331
332         evas_object_show(priv->base);
333
334         if (priv->btn)
335                 elm_object_focus_set(priv->btn, EINA_TRUE);
336 }
337
338 static void _hide(void *data)
339 {
340         struct _priv *priv;
341
342         if (!data) {
343                 _ERR("Invalid argument");
344                 return;
345         }
346
347         priv = data;
348
349         evas_object_hide(priv->base);
350         priv->edited = false;
351 }
352
353 static void _destroy(void *data)
354 {
355         struct _priv *priv;
356
357         if (!data) {
358                 _ERR("Invalid argument");
359                 return;
360         }
361
362         priv = data;
363
364         inputmgr_remove_callback(priv->btn, &handler);
365         inputmgr_remove_callback(priv->item, &handler);
366
367         evas_object_del(priv->base);
368         free(priv);
369 }
370
371 static void _update(void *view_data, int update_type, void *data)
372 {
373         struct _priv *priv;
374
375         if (!view_data) {
376                 _ERR("Invalid argument");
377                 return;
378         }
379
380         priv = view_data;
381
382         switch (update_type) {
383         case UPDATE_TYPE_EDIT:
384                 priv->edited = *(bool *)data;
385                 break;
386         default:
387                 _ERR("Invalid type");
388                 return;
389         }
390 }
391
392 static view_class vclass = {
393         .view_id = VIEW_ACTION_MENU,
394         .create = _create,
395         .show = _show,
396         .hide = _hide,
397         .destroy = _destroy,
398         .update = _update
399 };
400
401 view_class *view_action_menu_get_vclass(void)
402 {
403         return &vclass;
404 }