diff options
Diffstat (limited to 'src/scroller.c')
-rwxr-xr-x | src/scroller.c | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/src/scroller.c b/src/scroller.c new file mode 100755 index 0000000..fa0bea4 --- /dev/null +++ b/src/scroller.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <Elementary.h> + +#include "share_panel.h" +#include "share_panel_internal.h" +#include "conf.h" +#include "grid.h" +#include "log.h" +#include "page.h" +#include "scroller.h" + +#define PRIVATE_SCROLLER_IS_SCROLLING "p_is_sc" +#define PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST "pdkec" + + +struct _event_cb { + int event_type; + void (*event_cb)(Evas_Object *scroller, int event_type, void *event_info, void *user_data); + void *user_data; +}; +typedef struct _event_cb event_cb_s; + + +static void __anim_start_cb(void *data, Evas_Object *scroller, void *event_info) +{ + _D("start the scroller(%p) animation", scroller); + evas_object_data_set(scroller, PRIVATE_SCROLLER_IS_SCROLLING, (void *)1); +} + + +static void __anim_stop_cb(void *data, Evas_Object *scroller, void *event_info) +{ + _D("stop the scroller(%p) animation", scroller); + evas_object_data_del(scroller, PRIVATE_SCROLLER_IS_SCROLLING); +} + + +static void __drag_start_cb(void *data, Evas_Object *scroller, void *event_info) +{ + _D("start to drag the scroller(%p)", scroller); +} + + +static void __drag_stop_cb(void *data, Evas_Object *scroller, void *event_info) +{ + _D("stop to drag the scroller(%p) animation", scroller); +} + + +static void __scroll_cb(void *data, Evas_Object *scroller, void *event_info) +{ + share_panel_h share_panel = data; + Eina_List *event_cb_list = NULL; + const Eina_List *l = NULL; + const Eina_List *ln = NULL; + event_cb_s *event_cb_info = NULL; + + ret_if(!share_panel); + ret_if(!scroller); + + event_cb_list = evas_object_data_get(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST); + ret_if(!event_cb_list); + + EINA_LIST_FOREACH_SAFE(event_cb_list, l, ln, event_cb_info) { + if (SCROLLER_EVENT_TYPE_SCROLL == event_cb_info->event_type) { + if (event_cb_info->event_cb) { + event_cb_info->event_cb(scroller, SCROLLER_EVENT_TYPE_SCROLL, NULL, event_cb_info->user_data); + } + } + } +} + + +Evas_Object *_scroller_create(Evas_Object *ui_manager, share_panel_h share_panel) +{ + Evas_Object *box = NULL; + Evas_Object *scroller = NULL; + + retv_if(!ui_manager, NULL); + retv_if(!share_panel, NULL); + + scroller = elm_scroller_add(ui_manager); + retv_if(!scroller, NULL); + + elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_FALSE); + elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + elm_scroller_page_scroll_limit_set(scroller, 1, 1); + elm_scroller_content_min_limit(scroller, EINA_FALSE, EINA_TRUE); + elm_scroller_single_direction_set(scroller, ELM_SCROLLER_SINGLE_DIRECTION_HARD); + + elm_scroller_page_size_set(scroller, share_panel->page_width, -1); + + elm_object_style_set(scroller, "effect"); + evas_object_show(scroller); + elm_object_scroll_lock_y_set(scroller, EINA_TRUE); + + evas_object_smart_callback_add(scroller, "scroll,anim,start", __anim_start_cb, NULL); + evas_object_smart_callback_add(scroller, "scroll,anim,stop", __anim_stop_cb, NULL); + evas_object_smart_callback_add(scroller, "scroll,drag,start", __drag_start_cb, NULL); + evas_object_smart_callback_add(scroller, "scroll,drag,stop", __drag_stop_cb, share_panel); + evas_object_smart_callback_add(scroller, "scroll", __scroll_cb, share_panel); + + box = elm_box_add(scroller); + goto_if(!box, ERROR); + + elm_box_horizontal_set(box, EINA_TRUE); + elm_box_align_set(box, 0.5, 0.5); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(box); + + elm_object_content_set(scroller, box); + + return scroller; + +ERROR: + if (scroller) { + evas_object_del(scroller); + } + return NULL; +} + + +void _scroller_destroy(Evas_Object *scroller) +{ + Evas_Object *box = NULL; + Eina_List *list = NULL; + ret_if(!scroller); + + box = elm_object_content_unset(scroller); + if (box) { + list = elm_box_children_get(box); + if (list) { + _scroller_remove_list(scroller, list); + eina_list_free(list); + } + evas_object_del(box); + } + + evas_object_del(scroller); +} + + +void _scroller_append_page(Evas_Object *scroller, Evas_Object *page) +{ + Evas_Object *box = NULL; + Eina_List *event_cb_list = NULL; + const Eina_List *l = NULL; + const Eina_List *ln = NULL; + event_cb_s *event_cb_info = NULL; + + box = elm_object_content_get(scroller); + ret_if(!box); + + elm_box_pack_end(box, page); + + event_cb_list = evas_object_data_get(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST); + ret_if(!event_cb_list); + + EINA_LIST_FOREACH_SAFE(event_cb_list, l, ln, event_cb_info) { + if (SCROLLER_EVENT_TYPE_APPEND_PAGE == event_cb_info->event_type) { + if (event_cb_info->event_cb) { + event_cb_info->event_cb(scroller, SCROLLER_EVENT_TYPE_APPEND_PAGE, NULL, event_cb_info->user_data); + } + } + } +} + +void _scroller_append_list(Evas_Object *scroller, Eina_List *list, int page_width, int page_height) +{ + Evas_Object *page = NULL; + Evas_Object *grid = NULL; + int count = 0; + int i; + + ret_if(!scroller); + ret_if(!list); + + /* We'll implement this part */ + count = eina_list_count(list); + if (!count) { + _D("no apps"); + return; + } + + _D("list count is %d", count); + + for (i = 0; i < count; i++) { + Evas_Object *item = NULL; + if (i % 8 == 0) { + page = _page_create(scroller, page_width, page_height); + ret_if(!page); + _scroller_append_page(scroller, page); + grid = _grid_create(page); + ret_if(!grid); + elm_object_part_content_set(page, "grid", grid); + } + item = _grid_append_item(grid, eina_list_nth(list, i)); + ret_if(!item); + } +} + + +void _scroller_remove_list(Evas_Object *scroller, Eina_List *list) +{ + Evas_Object *page = NULL; + Evas_Object *grid = NULL; + const Eina_List *l, *ln; + + ret_if(!scroller); + ret_if(!list); + + EINA_LIST_FOREACH_SAFE(list, l, ln, page) { + grid = elm_object_part_content_unset(page, "grid"); + continue_if(!grid); + _grid_destroy(grid); + _page_destroy(page); + } +} + + +int _scroller_get_region_index(Evas_Object *scroller) +{ + int index = 0; + int x = 0; + int page_w = 0; + + retv_if(!scroller, 0); + + elm_scroller_region_get(scroller, &x, NULL, NULL, NULL); + elm_scroller_page_size_get(scroller, &page_w, NULL); + + index = x / page_w; + x = x % page_w; + if (x > (page_w / 2)) { + index++; + } + + return index; +} + + +unsigned int _scroller_count(Evas_Object *scroller) +{ + Evas_Object *box = NULL; + Eina_List *list = NULL; + int count = 0; + + retv_if(!scroller, 0); + + box = elm_object_content_get(scroller); + retv_if(!box, 0); + + list = elm_box_children_get(box); + retv_if(!list, 0); + + count = eina_list_count(list); + eina_list_free(list); + + return count; +} + +int _scroller_register_event_cb(Evas_Object *scroller, int event_type, void (*event_cb)(Evas_Object *scroller, int event_type, void *event_info, void *user_data), void *user_data) +{ + Eina_List *event_cb_list = NULL; + event_cb_s *event_cb_info = NULL; + + retv_if(!scroller, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(event_type <= SCROLLER_EVENT_TYPE_INVALID, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(event_type >= SCROLLER_EVENT_TYPE_MAX, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(!event_cb, SHARE_PANEL_ERROR_INVALID_PARAMETER); + + event_cb_info = calloc(1, sizeof(event_cb_s)); + retv_if(!event_cb_info, SHARE_PANEL_ERROR_OUT_OF_MEMORY); + + event_cb_info->event_type = event_type; + event_cb_info->event_cb = event_cb; + event_cb_info->user_data = user_data; + + event_cb_list = evas_object_data_get(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST); + event_cb_list = eina_list_append(event_cb_list, event_cb_info); + evas_object_data_set(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST, event_cb_list); + + return SHARE_PANEL_ERROR_NONE; +} + + +int _scroller_unregister_event_cb(Evas_Object *scroller, int event_type, void (*event_cb)(Evas_Object *scroller, int event_type, void *event_info, void *user_data)) +{ + Eina_List *event_cb_list = NULL; + const Eina_List *l = NULL; + const Eina_List *ln = NULL; + event_cb_s *event_cb_info = NULL; + + retv_if(!scroller, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(event_type <= SCROLLER_EVENT_TYPE_INVALID, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(event_type >= SCROLLER_EVENT_TYPE_MAX, SHARE_PANEL_ERROR_INVALID_PARAMETER); + retv_if(!event_cb, SHARE_PANEL_ERROR_INVALID_PARAMETER); + + event_cb_list = evas_object_data_get(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST); + retv_if(!event_cb_list, SHARE_PANEL_ERROR_NOT_INITIALIZED); + + EINA_LIST_FOREACH_SAFE(event_cb_list, l, ln, event_cb_info) { + if (event_cb_info->event_type == event_type + && event_cb_info->event_cb == event_cb) { + event_cb_list = eina_list_remove(event_cb_list, event_cb_info); + break; + } + } + + evas_object_data_set(scroller, PRIVATE_DATA_KEY_EVENT_CALLBACK_LIST, event_cb_list); + + return SHARE_PANEL_ERROR_NONE; +} |