2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <Elementary.h>
18 #include <media_content.h>
19 #include <app_debug.h>
20 #include <app_media.h>
25 #include "data/mediadata.h"
26 #include "util/listmgr.h"
27 #include "util/util.h"
29 #define MAX_GRID_WIDTH 1858
31 #define SCROLLER_STEP_SIZE(x) ((x) + 10)
44 Evas_Object *play_info;
47 Elm_Object_Item *focused_it;
48 Elm_Object_Item *selected_it;
51 struct listmgr_data *data;
53 Eina_Bool show_play_info;
54 Eina_Bool focus_state;
57 static void _key_down_cb(int id, void *data, Evas *e, Evas_Object *obj,
58 Evas_Event_Key_Down *ev)
61 struct grid_ops *gops;
63 if (!data || !obj || !ev)
70 if (!strcmp(ev->keyname, KEY_BACK) ||
71 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
72 elm_object_focus_next(obj, ELM_FOCUS_UP);
73 } else if (!strcmp(ev->keyname, KEY_DOWN)) {
77 if (lmgr->play_info == lmgr->focused)
80 grid = elm_object_part_content_get(lmgr->focused,
82 it = elm_gengrid_first_item_get(grid);
84 elm_object_item_focus_set(it, EINA_TRUE);
88 case LISTMGR_PLAY_INFO:
90 if (!strcmp(ev->keyname, KEY_BACK) ||
91 !strcmp(ev->keyname, KEY_BACK_REMOTE))
92 elm_object_focus_next(obj, ELM_FOCUS_UP);
94 gops = lmgr->data->gops;
95 if (gops->key_down_cb)
96 gops->key_down_cb(gops->ops_data,
97 lmgr->focused_it, ev);
106 static void _mouse_move_cb(int id, void *data, Evas *e, Evas_Object *obj,
107 Evas_Event_Mouse_Move *ev)
110 struct listmgr *lmgr;
112 if (!data || !obj || !ev)
119 case LISTMGR_PLAY_INFO:
120 if (!elm_object_focus_get(obj)) {
121 lmgr->focus_state = EINA_TRUE;
122 elm_object_focus_set(obj, EINA_TRUE);
127 it = elm_gengrid_at_xy_item_get(obj, ev->cur.canvas.x,
128 ev->cur.canvas.y, NULL, NULL);
133 if (!elm_object_item_focus_get(it)) {
134 lmgr->focus_state = EINA_TRUE;
135 elm_object_item_focus_set(it, EINA_TRUE);
144 static void _clicked_cb(int id, void *data, Evas_Object *obj)
150 case LISTMGR_PLAY_INFO:
151 elm_object_signal_emit(obj, SIG_BTN_CLICKED, SIG_SOURCE_SRC);
158 static void _focused_cb(int id, void *data, Evas_Object *obj,
162 struct listmgr *lmgr;
170 case LISTMGR_SCROLLER:
171 if (lmgr->focus_state)
174 btn = elm_object_part_content_get(lmgr->focused,
177 _ERR("failed to get button object");
181 lmgr->focus_state = EINA_TRUE;
182 elm_object_focus_set(btn, EINA_TRUE);
186 case LISTMGR_PLAY_INFO:
188 lmgr->focused = elm_object_parent_widget_get(obj);
189 elm_object_signal_emit(lmgr->data->menu_btn, SIG_BTN_SELECTED,
197 static void _grid_selected(void *data)
199 struct listmgr *lmgr;
200 struct grid_ops *gops;
203 _ERR("invalid argument");
209 gops = lmgr->data->gops;
211 if (gops->selected_cb)
212 gops->selected_cb(gops->ops_data, lmgr->selected_it);
215 static void _grid_selected_cb(int id, void *data, Evas_Object *obj,
218 struct listmgr *lmgr;
225 lmgr->selected_it = it;
227 ecore_job_add(_grid_selected, lmgr);
230 static void _play_info_selected_cb(void *data, Evas_Object *obj,
231 const char *emission, const char *source)
233 struct listmgr *lmgr;
234 struct play_info_ops *pops;
240 pops = lmgr->data->pops;
242 if (pops->selected_cb)
243 pops->selected_cb(pops->ops_data, obj);
246 static void _item_focused_cb(void *data, Elm_Object_Item *it,
247 const char *emission, const char *source)
249 struct listmgr *lmgr;
256 lmgr->focused_it = it;
259 static void _add_grid_item_callback(Elm_Object_Item *it, void *data)
261 elm_object_item_signal_callback_add(it, SIG_ITEM_FOCUSED,
262 SIG_SOURCE_EDC, _item_focused_cb, data);
265 static void _delete_grid_item_callback(Elm_Object_Item *it)
267 elm_object_item_signal_callback_del(it, SIG_ITEM_FOCUSED,
268 SIG_SOURCE_EDC, _item_focused_cb);
271 static void _realized_cb(int id, void *data, Evas_Object *obj,
274 struct listmgr *lmgr;
281 _add_grid_item_callback(it, lmgr);
284 static void _unrealized_cb(int id, void *data, Evas_Object *obj,
290 _delete_grid_item_callback(it);
293 static input_handler _grid_handler = {
294 .key_down = _key_down_cb,
295 .mouse_move = _mouse_move_cb,
296 .focused = _focused_cb,
297 .selected = _grid_selected_cb,
298 .realized = _realized_cb,
299 .unrealized = _unrealized_cb
302 static input_handler _handler = {
303 .key_down = _key_down_cb,
304 .mouse_move = _mouse_move_cb,
305 .clicked = _clicked_cb,
306 .focused = _focused_cb
309 static Evas_Object *_get_box_first_item(Evas_Object *box)
313 list = elm_box_children_get(box);
317 return (Evas_Object *)eina_list_nth(list, 0);
320 static int _get_grid_width(int count, int num_item, int item_x)
324 num_col = count / num_item;
325 if (count % num_item > 0)
328 width = num_col * item_x;
329 if (width > MAX_GRID_WIDTH)
330 width = MAX_GRID_WIDTH;
335 static bool _draw_play_info(struct listmgr *lmgr)
337 Evas_Object *ly, *index, *content;
338 struct play_info_ops *pops;
340 ly = elm_layout_add(lmgr->box);
342 _ERR("failed to create layout object");
346 elm_layout_file_set(ly, EDJEFILE, GRP_LIST_ITEM);
348 pops = lmgr->data->pops;
350 if (!pops->draw(pops->ops_data, ly)) {
351 _ERR("failed to draw play info item");
356 index = elm_object_part_content_get(ly, PART_ITEM_TITLE);
358 inputmgr_add_callback(index, LISTMGR_INDEX, &_handler, lmgr);
359 elm_object_focus_next_object_set(index, lmgr->data->menu_btn,
362 content = elm_object_part_content_get(ly, PART_ITEM_CONTENT);
364 elm_object_focus_next_object_set(content, index, ELM_FOCUS_UP);
366 inputmgr_add_callback(content, LISTMGR_PLAY_INFO, &_handler, lmgr);
367 elm_object_signal_callback_add(content, SIG_ITEM_SELECTED,
368 SIG_SOURCE_EDC, _play_info_selected_cb, lmgr);
370 lmgr->play_info = ly;
375 static Evas_Object *_draw_list_item(struct listmgr *lmgr, struct group_info *gi)
377 Evas_Object *ly, *btn, *grid;
378 struct listmgr_data *data;
384 ly = elm_layout_add(lmgr->box);
386 _ERR("failed to create layout object");
390 elm_layout_file_set(ly, EDJEFILE, GRP_LIST_ITEM);
392 btn = elm_button_add(ly);
394 _ERR("failed to create button object");
399 elm_object_style_set(btn, STYLE_BTN_INDEX);
401 snprintf(buf, sizeof(buf), " %s ", gi->name);
402 elm_object_text_set(btn, buf);
404 elm_object_focus_next_object_set(btn,
405 lmgr->data->menu_btn, ELM_FOCUS_UP);
407 inputmgr_add_callback(btn, LISTMGR_INDEX, &_handler, lmgr);
409 grid = util_add_gengrid(ly, data->grid_item_x,
410 data->grid_item_y, EINA_TRUE);
412 _ERR("failed to create gengrid object");
417 if (!gridmgr_add_grid(lmgr->gmgr, gi->name, grid, data->gops->gclass)) {
418 _ERR("failed to add grid");
423 width = _get_grid_width(eina_list_count(gi->list), data->grid_num_item,
426 evas_object_size_hint_min_set(grid, width,
427 data->grid_num_item * data->grid_item_y);
429 elm_object_focus_next_object_set(grid, btn, ELM_FOCUS_UP);
431 inputmgr_add_callback(grid, LISTMGR_GRID, &_grid_handler, lmgr);
433 elm_object_part_content_set(ly, PART_ITEM_TITLE, btn);
434 elm_object_part_content_set(ly, PART_ITEM_CONTENT, grid);
439 bool _focus_to_content(struct listmgr *lmgr, Evas_Object *base)
441 Evas_Object *content;
443 content = elm_object_part_content_get(base, PART_ITEM_CONTENT);
445 _ERR("failed to get content");
449 lmgr->focus_state = EINA_TRUE;
450 elm_object_focus_set(content, EINA_TRUE);
455 Elm_Object_Item *_get_grid_item(Evas_Object *grid, const char *id)
461 for (it = elm_gengrid_first_item_get(grid); it;
462 it = elm_gengrid_item_next_get(it)) {
463 am = elm_object_item_data_get(it);
467 mi = app_media_get_info(am);
471 if (!strcmp(id, mi->media_id))
478 void listmgr_set_focus_state(struct listmgr *lmgr, Eina_Bool state)
481 _ERR("failed to get listmgr");
485 lmgr->focus_state = state;
488 bool listmgr_focus_play_info(struct listmgr *lmgr)
491 _ERR("failed to get listmgr");
495 if (!_focus_to_content(lmgr, lmgr->play_info)) {
496 _ERR("failed to focus to content");
503 bool listmgr_focus_content_list(struct listmgr *lmgr, const char *id)
506 Evas_Object *ly, *grid;
510 _ERR("failed to get listmgr");
515 _ERR("invalid argument");
519 item = elm_box_children_get(lmgr->box);
523 EINA_LIST_FOREACH(item, l, ly) {
524 grid = elm_object_part_content_get(ly, PART_ITEM_CONTENT);
526 _ERR("failed to get grid object");
530 it = _get_grid_item(grid, id);
536 _ERR("failed to get current grid item");
540 elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_MIDDLE);
542 lmgr->focus_state = EINA_TRUE;
543 elm_object_item_focus_set(it, EINA_TRUE);
548 void _update_grid_realized_items(struct listmgr *lmgr, Eina_List *list)
553 EINA_LIST_FOREACH(list, l, it) {
554 _delete_grid_item_callback(it);
556 elm_gengrid_item_update(it);
557 _add_grid_item_callback(it, lmgr);
561 bool listmgr_update_content_item(struct listmgr *lmgr)
563 Eina_List *box_item, *grid_realized;
565 Evas_Object *ly, *grid;
568 _ERR("failed to get listmgr");
572 box_item = elm_box_children_get(lmgr->box);
574 EINA_LIST_FOREACH(box_item, l, ly) {
575 grid = elm_object_part_content_get(ly, PART_ITEM_CONTENT);
577 _ERR("failed to get grid object");
581 grid_realized = elm_gengrid_realized_items_get(grid);
582 _update_grid_realized_items(lmgr, grid_realized);
588 bool listmgr_update_content_list(struct listmgr *lmgr, Eina_List *list)
590 Evas_Object *ly, *btn, *grid;
592 struct group_info *gi;
595 _ERR("invalid argument");
600 EINA_LIST_FOREACH(list, l, gi) {
601 ly = _draw_list_item(lmgr, gi);
603 _ERR("failed to draw list item");
607 if (!gridmgr_append_list(lmgr->gmgr, gi->name, gi->list)) {
608 _ERR("failed to append list in grid");
612 evas_object_show(ly);
614 elm_box_pack_end(lmgr->box, ly);
617 btn = elm_object_part_content_get(ly, PART_ITEM_TITLE);
618 elm_object_focus_next_object_set(btn, btn, ELM_FOCUS_RIGHT);
620 grid = elm_object_part_content_get(ly, PART_ITEM_CONTENT);
621 elm_object_focus_next_object_set(grid, grid, ELM_FOCUS_RIGHT);
623 lmgr->focused = _get_box_first_item(lmgr->box);
625 elm_object_focus_allow_set(lmgr->scr, EINA_TRUE);
630 bool listmgr_update_play_info(struct listmgr *lmgr, app_media_info *info)
632 struct play_info_ops *pops;
635 _ERR("invalid argument");
640 if (lmgr->show_play_info) {
641 if (lmgr->play_info == lmgr->focused)
642 lmgr->focused = _get_box_first_item(lmgr->box);
644 elm_box_unpack(lmgr->box, lmgr->play_info);
645 evas_object_hide(lmgr->play_info);
646 lmgr->show_play_info = EINA_FALSE;
651 pops = lmgr->data->pops;
653 if (!pops->update(pops->ops_data, lmgr->play_info)) {
654 _ERR("failed to update play info");
658 if (!lmgr->show_play_info) {
659 elm_box_pack_start(lmgr->box, lmgr->play_info);
660 evas_object_size_hint_align_set(lmgr->play_info, 0.0, 0.0);
661 evas_object_show(lmgr->play_info);
663 lmgr->show_play_info = EINA_TRUE;
664 lmgr->focused = lmgr->play_info;
670 bool listmgr_draw_list_area(struct listmgr *lmgr)
672 Evas_Object *scr, *box;
673 struct listmgr_data *data;
676 _ERR("invalid argument");
682 scr = util_add_scroller(lmgr->base);
684 _ERR("failed to create scroller object");
688 elm_scroller_step_size_set(scr, SCROLLER_STEP_SIZE(
689 data->box_padding + data->grid_item_x), 0);
691 inputmgr_add_callback(scr, LISTMGR_SCROLLER, &_handler, lmgr);
693 box = util_add_box(scr);
695 _ERR("failed to create box object");
696 evas_object_del(scr);
700 elm_box_padding_set(box, data->box_padding, 0);
702 evas_object_show(box);
703 elm_object_content_set(scr, box);
705 elm_object_part_content_set(lmgr->base, PART_CONTENT, scr);
711 if (!_draw_play_info(lmgr)) {
712 _ERR("failed to draw play info");
713 evas_object_del(scr);
718 elm_object_focus_next_object_set(data->menu_btn, scr, ELM_FOCUS_DOWN);
720 elm_object_focus_allow_set(scr, EINA_FALSE);
725 struct listmgr *listmgr_create(Evas_Object *base, void *data)
727 struct gridmgr *gmgr;
728 struct listmgr *lmgr;
730 if (!base || !data) {
731 _ERR("invalid argument");
735 lmgr = calloc(1, sizeof(*lmgr));
737 _ERR("failed to allocate listmgr");
741 gmgr = gridmgr_create();
743 _ERR("failed to create gridmgr");
751 lmgr->show_play_info = EINA_FALSE;
752 lmgr->focus_state = EINA_FALSE;
757 void listmgr_destroy(struct listmgr *lmgr)
760 Evas_Object *ly, *btn, *content, *grid;
763 _ERR("invalid argument");
767 if (lmgr->play_info) {
768 btn = elm_object_part_content_get(lmgr->play_info,
770 content = elm_object_part_content_get(lmgr->play_info,
773 inputmgr_remove_callback(btn, &_handler);
774 inputmgr_remove_callback(content, &_handler);
776 elm_object_signal_callback_del(content, SIG_ITEM_SELECTED,
777 SIG_SOURCE_EDC, _play_info_selected_cb);
779 elm_box_unpack(lmgr->box, lmgr->play_info);
780 evas_object_del(lmgr->play_info);
783 item = elm_box_children_get(lmgr->box);
784 EINA_LIST_FOREACH(item, l, ly) {
785 btn = elm_object_part_content_get(ly, PART_ITEM_TITLE);
786 grid = elm_object_part_content_get(ly, PART_ITEM_CONTENT);
788 inputmgr_remove_callback(btn, &_handler);
789 inputmgr_remove_callback(grid, &_grid_handler);
792 inputmgr_remove_callback(lmgr->scr, &_handler);
794 gridmgr_destroy(lmgr->gmgr);