2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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>
22 #include "live_scroller.h"
26 #define FOCAL_DIST 800
27 #define FLICK_COND 100
30 int (*cb)(Evas_Object *sc, void *data);
42 Ecore_Idler *bg_changer;
46 void scroller_lock(Evas_Object *sc)
48 struct scroll_info *scinfo;
50 scinfo = evas_object_data_get(sc, "scinfo");
52 ErrPrint("scinfo is not valid\n");
57 live_scroller_freeze(sc);
62 void scroller_unlock(Evas_Object *sc)
64 struct scroll_info *scinfo;
66 scinfo = evas_object_data_get(sc, "scinfo");
68 ErrPrint("scinfo is not valid\n");
72 if (scinfo->locked == 0)
77 if (scinfo->locked == 0)
78 live_scroller_thaw(sc);
81 static void sc_anim_stop(void *data, Evas_Object *obj, void *event_info)
86 struct scroll_info *scinfo;
88 scinfo = evas_object_data_get(obj, "scinfo");
90 ErrPrint("scinfo is not valid\n");
95 * Do what you want at here when the scroller is stopped
98 scinfo->scrolling = EINA_FALSE;
99 EINA_LIST_FOREACH_SAFE(scinfo->cb_list, l, tmp, item) {
100 if (item->cb(obj, item->data) == ECORE_CALLBACK_CANCEL) {
101 if (eina_list_data_find(scinfo->cb_list, item)) {
102 scinfo->cb_list = eina_list_remove(scinfo->cb_list, item);
109 static inline void sc_drag_start(void *data, Evas_Object *obj, void *event_info)
111 struct scroll_info *scinfo;
113 scinfo = evas_object_data_get(obj, "scinfo");
115 ErrPrint("scinfo is not valid\n");
119 scinfo->scrolling = EINA_TRUE;
122 static inline void sc_drag_stop(void *data, Evas_Object *scroller, void *event_info)
124 struct live_sc_drag_info *info;
130 if (info->dx > FLICK_COND)
132 else if (info->dx < -FLICK_COND)
135 ret = live_scroller_anim_to(scroller, 0.016f, offset);
137 struct scroll_info *scinfo;
138 scinfo = evas_object_data_get(scroller, "scinfo");
140 scinfo->scrolling = EINA_FALSE;
144 static Eina_Bool bg_change_cb(void *data)
146 Evas_Object *sc = data;
147 struct scroll_info *scinfo;
149 scinfo = evas_object_data_get(sc, "scinfo");
151 scinfo->bg_changer = NULL;
156 * Filename of background image handling code is only
157 * used to demonstrates UX concept and estimates its perfomance.
158 * So, I'll change this if it should be appled to
161 DbgPrint("Change the background image (%p)\n", sc);
162 return ECORE_CALLBACK_CANCEL;
165 static void sc_anim_start(void *data, Evas_Object *obj, void *event_info)
167 struct scroll_info *scinfo;
169 scinfo = evas_object_data_get(obj, "scinfo");
171 ErrPrint("scinfo is not valid\n");
178 * anim start can be invoked by the scroller_anim_to
180 scinfo->scrolling = EINA_TRUE;
182 if (scinfo->bg_changer)
183 ecore_idler_del(scinfo->bg_changer);
185 scinfo->bg_changer = ecore_idler_add(bg_change_cb, obj);
186 if (!scinfo->bg_changer)
187 DbgPrint("Failed to add an idler\n");
190 static void sc_item_moved(void *data, Evas_Object *obj, void *event_info)
192 struct live_sc_move_info *evt = event_info;
195 Evas_Coord y, sx, sw;
197 struct scroll_info *scinfo;
199 scinfo = evas_object_data_get(obj, "scinfo");
201 ErrPrint("Has no scinfo\n");
205 ftmp = fabsl(evt->relx);
207 evas_object_map_enable_set(evt->item, EINA_FALSE);
208 evas_object_hide(evt->item);
212 color = 255 * (1.0f - ftmp);
217 focal = scinfo->focal;
220 evas_object_map_enable_set(evt->item, EINA_FALSE);
221 evas_object_hide(evt->item);
225 focal = -ftmp * 200.0f + scinfo->focal;
228 evas_object_geometry_get(data, &sx, NULL, &sw, NULL);
231 evas_map_point_coord_set(scinfo->map, 0, evt->x, evt->y, 0);
232 evas_map_point_image_uv_set(scinfo->map, 0, 0, 0);
233 evas_map_point_color_set(scinfo->map, 0, color, color, color, color);
236 evas_map_point_coord_set(scinfo->map, 1, evt->x + evt->w, evt->y, 0);
237 evas_map_point_image_uv_set(scinfo->map, 1, evt->w, 0);
238 evas_map_point_color_set(scinfo->map, 1, color, color, color, color);
241 evas_map_point_coord_set(scinfo->map, 2, evt->x + evt->w, evt->y + evt->h, 0);
242 evas_map_point_image_uv_set(scinfo->map, 2, evt->w, evt->h);
243 evas_map_point_color_set(scinfo->map, 2, color, color, color, color);
246 evas_map_point_coord_set(scinfo->map, 3, evt->x, evt->y + evt->h, 0);
247 evas_map_point_image_uv_set(scinfo->map, 3, 0, evt->h);
248 evas_map_point_color_set(scinfo->map, 3, color, color, color, color);
250 y = evt->y + (evt->h >> 1);
251 evas_map_util_3d_rotate(scinfo->map, 0.0f, -30.0f * evt->relx, 0.0f, evt->x + (evt->w >> 1), y, 0);
252 evas_map_util_3d_perspective(scinfo->map, sx + (sw >> 1), y, focal, FOCAL_DIST);
253 evas_object_map_set(evt->item, scinfo->map);
254 evas_object_map_enable_set(evt->item, EINA_TRUE);
255 evas_object_show(evt->item);
259 static void sc_page_changed(void *data, Evas_Object *obj, void *event_info)
261 DbgPrint("Page is changed %d\n", (int)event_info);
264 int scroller_add_stop_cb(Evas_Object *scroller,
265 int (*cb)(Evas_Object *sc, void *data), void *data)
267 struct cb_item *item;
268 struct scroll_info *scinfo;
270 scinfo = evas_object_data_get(scroller, "scinfo");
272 ErrPrint("scinfo is not valid\n");
276 item = calloc(1, sizeof(*item));
278 ErrPrint("Error: %s\n", strerror(errno));
285 scinfo->cb_list = eina_list_append(scinfo->cb_list, item);
289 void scroller_del_stop_cb(Evas_Object *scroller,
290 int (*cb)(Evas_Object *sc, void *data), void *data)
292 struct cb_item *item;
295 struct scroll_info *scinfo;
297 scinfo = evas_object_data_get(scroller, "scinfo");
299 ErrPrint("Failed to get scinfo\n");
303 EINA_LIST_FOREACH_SAFE(scinfo->cb_list, l, tmp, item) {
304 if (item->cb == cb && item->data == data) {
305 scinfo->cb_list = eina_list_remove(scinfo->cb_list, item);
312 Evas_Object *scroller_create(Evas_Object *ctrl)
315 struct scroll_info *scinfo;
317 scinfo = calloc(1, sizeof(*scinfo));
319 ErrPrint("Heap: %s\n", strerror(errno));
323 sc = live_scroller_add(ctrl);
325 DbgPrint("Failed to create flip object\n");
330 evas_object_data_set(sc, "scinfo", scinfo);
332 scinfo->map = evas_map_new(4);
334 ErrPrint("Failed to create a map object\n");
340 evas_map_smooth_set(scinfo->map, EINA_TRUE);
341 evas_map_alpha_set(scinfo->map, EINA_TRUE);
343 evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
344 evas_object_smart_callback_add(sc, "drag,start", sc_drag_start, NULL);
345 evas_object_smart_callback_add(sc, "drag,stop", sc_drag_stop, NULL);
346 evas_object_smart_callback_add(sc, "anim,stop", sc_anim_stop, NULL);
347 evas_object_smart_callback_add(sc, "anim,start", sc_anim_start, NULL);
348 evas_object_smart_callback_add(sc, "page,changed", sc_page_changed, NULL);
349 evas_object_smart_callback_add(sc, "item,moved", sc_item_moved, NULL);
350 live_scroller_loop_set(sc, EINA_TRUE);
351 evas_object_show(sc);
356 int scroller_append(Evas_Object *sc, Evas_Object *child)
358 return live_scroller_append(sc, child);
361 int scroller_get_page_index(Evas_Object *sc, Evas_Object *page)
363 return live_scroller_get_item_index(sc, page);
366 Evas_Object *scroller_get_page(Evas_Object *sc, int idx)
368 return live_scroller_get_item(sc, idx);
371 Evas_Object *scroller_peek_by_idx(Evas_Object *sc, int idx)
373 return live_scroller_remove(sc, idx);
376 int scroller_peek_by_obj(Evas_Object *sc, Evas_Object *page)
378 return live_scroller_remove_by_obj(sc, page);
381 int scroller_get_current_idx(Evas_Object *sc)
383 return live_scroller_get_current(sc);
386 int scroller_is_scrolling(Evas_Object *sc)
388 struct scroll_info *scinfo;
390 scinfo = evas_object_data_get(sc, "scinfo");
392 ErrPrint("scinfo is not valid\n");
396 return scinfo->scrolling;
399 int scroller_get_page_count(Evas_Object *sc)
401 return live_scroller_get_item_count(sc);
404 int scroller_scroll_to(Evas_Object *sc, int idx)
411 struct scroll_info *scinfo;
413 scinfo = evas_object_data_get(sc, "scinfo");
415 ErrPrint("scinfo is not valid\n");
419 if (scinfo->scrolling) {
420 DbgPrint("Scroller is scrolling\n");
424 curidx = live_scroller_get_current(sc);
425 cnt = live_scroller_get_item_count(sc);
429 while (i != idx && i >= 0 && i < cnt) {
439 while (i != idx && i >= 0 && i < cnt) {
447 idx = next_offset < -prev_offset ? next_offset : prev_offset;
448 live_scroller_anim_to(sc, 0.016f, idx);
452 int scroller_jump_to(Evas_Object *sc, int idx)
454 live_scroller_go_to(sc, idx);
458 int scroller_destroy(Evas_Object *sc)
461 struct scroll_info *scinfo;
462 struct cb_item *item;
464 scinfo = evas_object_data_del(sc, "scinfo");
468 if (scinfo->bg_changer)
469 ecore_idler_del(scinfo->bg_changer);
471 EINA_LIST_FREE(scinfo->cb_list, item) {
475 cnt = live_scroller_get_item_count(sc);
477 DbgPrint("Children is not cleared (%d)\n", cnt);
480 evas_map_free(scinfo->map);
485 int scroller_update(Evas_Object *sc, void *data)
487 struct scroll_info *scinfo;
489 scinfo = evas_object_data_get(sc, "scinfo");
491 ErrPrint("scinfo is not valid\n");
495 scinfo->focal = (int)data;
496 live_scroller_update(sc);
500 int scroller_fast_scroll(Evas_Object *sc, int idx)
502 idx -= scroller_get_current_idx(sc);
503 live_scroller_anim_to(sc, 0.016f, idx);
507 void scroller_loop_set(Evas_Object *sc, Eina_Bool val)
509 live_scroller_loop_set(sc, val);
512 void scroller_quick_navi(Evas_Object *sc, Eina_Bool val)
514 struct scroll_info *scinfo;
515 scinfo = evas_object_data_get(sc, "scinfo");
517 ErrPrint("scinfo is not valid\n");