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