91980a536aec9714bd2a2c4dd934c5ac8dda2c87
[apps/home/quickpanel.git] / daemon / page / pager.c
1 /*
2  * Copyright (c) 2009-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
18
19 #include "pager.h"
20 #include "pager_common.h"
21 #include "quickpanel_def.h"
22
23 static int _init(void *data);
24 static void _init_job_cb(void *data);
25 static int _fini(void *data);
26 static int _resume(void *data);
27 static void _opened(void *data);
28 static void _closed(void *data);
29 static void _refresh(void *data);
30 static inline void _page_mapbuf_enable_set(Evas_Object *box, int is_enable);
31
32 #define ENABLE_MAPBUF 0
33
34 typedef enum _qp_pager_state_type {
35         PAGER_STATE_NOT_READY = 0,
36         PAGER_STATE_IDLE,
37         PAGER_STATE_WILL_SCROLL,
38         PAGER_STATE_SCROLLING,
39         PAGER_STATE_FINISHED_SCROLLING,
40 } qp_pager_state_type;
41
42 QP_Module pager = {
43         .name = "pager",
44         .init = _init,
45         .init_job_cb = _init_job_cb,
46         .fini = _fini,
47         .resume = _resume,
48         .qp_opened = _opened,
49         .qp_closed = _closed,
50         .refresh = _refresh,
51 };
52
53 static struct info {
54         qp_pager_state_type state;
55         int last_page;
56         int is_in_edge;
57
58         Evas_Object *view_scroller;
59         Evas_Object *view_box;
60
61         Ecore_Event_Handler *hdl_move;
62         Ecore_Event_Handler *hdl_up;
63         Ecore_Event_Handler *hdl_down;
64
65         Ecore_Timer *timer_scroll_adj;
66
67         int scroll_start_from;
68 } s_info = {
69         .state = PAGER_STATE_NOT_READY,
70         .last_page = PAGE_IDX_MAIN,
71         .is_in_edge = 0,
72
73         .view_scroller = NULL,
74         .view_box = NULL,
75
76         .hdl_move = NULL,
77         .hdl_up = NULL,
78         .hdl_down = NULL,
79
80         .timer_scroll_adj = NULL,
81
82         .scroll_start_from = -1,
83 };
84
85 static inline void _set_state(qp_pager_state_type state) {
86         if (state == PAGER_STATE_IDLE) {
87                 _page_mapbuf_enable_set(s_info.view_box, 0);
88         } else  if (state == PAGER_STATE_WILL_SCROLL || state == PAGER_STATE_SCROLLING) {
89                 _page_mapbuf_enable_set(s_info.view_box, 1);
90         }
91         s_info.state = state;
92 }
93
94 static inline qp_pager_state_type _get_state(void) {
95         return s_info.state;
96 }
97
98 static inline int _last_page_get(void) {
99         return s_info.last_page;
100 }
101
102 static inline void _page_show(int page_index) {
103         elm_scroller_page_show(s_info.view_scroller, page_index, 0);
104         s_info.last_page = page_index;
105 }
106
107 static Eina_Bool _page_adjust_timer_cb(void *data)
108 {
109         int index = 0;
110
111         if (s_info.timer_scroll_adj != NULL) {
112                 ecore_timer_del(s_info.timer_scroll_adj);
113                 s_info.timer_scroll_adj = NULL;
114         }
115
116         elm_scroller_current_page_get(s_info.view_scroller, &index, NULL);
117         elm_scroller_page_bring_in(s_info.view_scroller, index, 0);
118         s_info.last_page = index;
119
120         return ECORE_CALLBACK_CANCEL;
121 }
122
123 static inline void _page_adjust(int is_use_timer) {
124         if (s_info.timer_scroll_adj != NULL) {
125                 ecore_timer_del(s_info.timer_scroll_adj);
126                 s_info.timer_scroll_adj = NULL;
127         }
128
129         if (is_use_timer) {
130                 s_info.timer_scroll_adj =
131                                 ecore_timer_add(0.1, _page_adjust_timer_cb, NULL);
132         } else {
133                 _page_adjust_timer_cb(NULL);
134         }
135 }
136
137 static inline int _current_page_index_get(void) {
138         int index = 0;
139
140         elm_scroller_current_page_get(s_info.view_scroller, &index, NULL);
141
142         return index;
143 }
144
145 static inline Evas_Object *_current_page_get(void) {
146         int index = 0;
147         int list_cnt = 0;
148         Eina_List *list = NULL;
149         static int last_page = -1;
150         Evas_Object *obj = NULL;
151
152         elm_scroller_current_page_get(s_info.view_scroller, &index, NULL);
153
154         if (last_page != index) {
155                 DBG("current selected page:%d", index);
156                 last_page = index;
157         }
158
159         list = elm_box_children_get(s_info.view_box);
160         if (list != NULL) {
161                 list_cnt = eina_list_count(list);
162
163                 if (index < list_cnt) {
164                         obj = (Evas_Object *)eina_list_nth(list, index);
165                 }
166                 eina_list_free(list);
167         }
168
169         return obj;
170 }
171
172 #if ENABLE_MAPBUF
173 static void _mapbuf_job_cb(void *data)
174 {
175         Eina_List *list = NULL;
176         Eina_List *l;
177         Eina_List *l_next;
178         Evas_Object *box = s_info.view_box;
179         Evas_Object *item = NULL;
180         int is_enable = (int)data;
181         QP_Page_Handler *page_handler = NULL;
182         retif(box == NULL, , "invalid parameter");
183
184         list = elm_box_children_get(box);
185         retif(list == NULL, , "empty box");
186
187         SDBG("mapbuf enable:%d", is_enable);
188
189         EINA_LIST_FOREACH_SAFE(list, l, l_next, item)
190         {
191                 page_handler = quickpanel_page_handler_get(item);
192                 if (page_handler != NULL) {
193                         if (page_handler->mapbuf_enable_set != NULL) {
194                                 if (elm_config_access_get() == EINA_FALSE) {
195                                         if (is_enable == 1) {
196                                                 page_handler->mapbuf_enable_set(EINA_TRUE);
197                                         } else {
198                                                 page_handler->mapbuf_enable_set(EINA_FALSE);
199                                         }
200                                 } else {
201                                         page_handler->mapbuf_enable_set(EINA_FALSE);
202                                 }
203                         }
204                 }
205         }
206
207         eina_list_free(list);
208 }
209 #endif
210
211 static inline void _page_mapbuf_enable_set(Evas_Object *box, int is_enable) {
212 #if ENABLE_MAPBUF
213         ecore_job_add(_mapbuf_job_cb, (void *)is_enable);
214 #endif
215 }
216
217 static inline void _page_resize(Evas_Object *box, int width, int height, const char *signal) {
218         Eina_List *list = NULL;
219         Eina_List *l;
220         Eina_List *l_next;
221         Evas_Object *item = NULL;
222         QP_Page_Handler *page_handler = NULL;
223         retif(box == NULL, , "invalid parameter");
224
225         list = elm_box_children_get(box);
226         retif(list == NULL, , "empty box");
227
228         EINA_LIST_FOREACH_SAFE(list, l, l_next, item)
229         {
230                 page_handler = quickpanel_page_handler_get(item);
231
232                 if (page_handler != NULL) {
233                         if (page_handler->content_resize != NULL) {
234                                 page_handler->content_resize(width, height, signal);
235                         }
236                 }
237         }
238
239         eina_list_free(list);
240 }
241
242 static inline void _page_rotation(void *data) {
243         struct appdata *ad = (struct appdata *)data;
244         retif(ad == NULL, , "Invalid parameter!");
245
246         if (ad->angle == 90 || ad->angle == 270)
247         {
248                 _page_resize(s_info.view_box, ad->win_height, ad->win_width - ELM_SCALE_SIZE((QP_DATE_H + QP_HANDLE_H)), "landscape");
249         }
250         else
251         {
252                 _page_resize(s_info.view_box, ad->win_width, ad->win_height - ELM_SCALE_SIZE((QP_DATE_H + QP_HANDLE_H)), "portrait");
253         }
254 }
255
256 static Eina_Bool _up_cb(void *data, int type, void *event) {
257         Evas_Object *page = _current_page_get();
258         QP_Page_Handler *page_handler = NULL;
259         retif(page == NULL, EINA_FALSE, "Invalid parameter!");
260
261         if (_get_state() == PAGER_STATE_WILL_SCROLL) {
262                 _set_state(PAGER_STATE_SCROLLING);
263                 _page_adjust(1);
264         }
265
266         page_handler = quickpanel_page_handler_get(page);
267         retif(page_handler == NULL, EINA_FALSE, "no page handler found");
268
269         if (page_handler->up_cb != NULL) {
270                 page_handler->up_cb(event, NULL);
271         }
272
273         if (_get_state() == PAGER_STATE_SCROLLING) {
274                 _page_adjust(1);
275         }
276
277         return EINA_TRUE;
278 }
279
280 static Eina_Bool _down_cb(void *data, int type, void *event) {
281         Evas_Object *page = _current_page_get();
282         QP_Page_Handler *page_handler = NULL;
283         retif(page == NULL, EINA_FALSE, "Invalid parameter!");
284
285         page_handler = quickpanel_page_handler_get(page);
286         retif(page_handler == NULL, EINA_FALSE, "no page handler found");
287
288         if (page_handler->down_cb != NULL) {
289                 page_handler->down_cb(event, NULL);
290         }
291
292         return EINA_TRUE;
293 }
294
295 static void _scroller_anim_start_cb(void *data, Evas_Object *scroller,
296                 void *event_info) {
297         Evas_Object *page = _current_page_get();
298         QP_Page_Handler *page_handler = NULL;
299         retif(page == NULL, , "Invalid parameter!");
300
301         s_info.scroll_start_from = _current_page_index_get();
302
303         if (_get_state() == PAGER_STATE_IDLE) {
304                 _set_state(PAGER_STATE_WILL_SCROLL);
305
306                 page_handler = quickpanel_page_handler_get(page);
307                 retif(page_handler == NULL, , "no page handler found");
308
309                 if (page_handler->scroll_start_cb != NULL) {
310                         page_handler->scroll_start_cb(event_info, NULL);
311                 }
312         }
313 }
314
315 static void _scroller_anim_stop_cb(void *data, Evas_Object *scroller,
316                 void *event_info) {
317         Evas_Object *page = _current_page_get();
318         QP_Page_Handler *page_handler = NULL;
319         retif(page == NULL, , "Invalid parameter!");
320
321         if (s_info.is_in_edge == 1 || _get_state() == PAGER_STATE_FINISHED_SCROLLING) {
322                 _set_state(PAGER_STATE_IDLE);
323
324                 page_handler = quickpanel_page_handler_get(page);
325                 retif(page_handler == NULL, , "no page handler found");
326
327                 if (page_handler->scroll_done_cb != NULL) {
328                         page_handler->scroll_done_cb(event_info, NULL);
329                 }
330
331                 _page_mapbuf_enable_set(s_info.view_box, 0);
332         }
333 }
334
335 static void _scroller_edge_cb(void *data, Evas_Object *scroller,
336                 void *event_info) {
337         if (_get_state() == PAGER_STATE_WILL_SCROLL
338                         || _get_state() == PAGER_STATE_SCROLLING) {
339                 _set_state(PAGER_STATE_FINISHED_SCROLLING);
340                 s_info.is_in_edge = 1;
341                 _page_adjust(0);
342         }
343 }
344
345 static void _scroller_scroll_cb(void *data, Evas_Object *scroller,
346                 void *event_info) {
347         s_info.is_in_edge = 0;
348 }
349
350 /*****************************************************************************
351  *
352  * Util functions
353  *
354  *****************************************************************************/
355 static int _init(void *data)
356 {
357         struct appdata *ad = (struct appdata *)data;
358         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
359         retif(s_info.view_scroller == NULL, QP_FAIL, "Invalid parameter!");
360
361         s_info.hdl_up = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _up_cb
362                         , s_info.view_scroller);
363         s_info.hdl_down = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _down_cb
364                         , s_info.view_scroller);
365
366         evas_object_smart_callback_add(s_info.view_scroller, "scroll,drag,start",
367                         _scroller_anim_start_cb, s_info.view_scroller);
368         evas_object_smart_callback_add(s_info.view_scroller, "scroll,anim,stop",
369                         _scroller_anim_stop_cb, s_info.view_scroller);
370         evas_object_smart_callback_add(s_info.view_scroller, "scroll,drag,stop",
371                         _scroller_anim_stop_cb, s_info.view_scroller);
372         evas_object_smart_callback_add(s_info.view_scroller, "scroll",
373                         _scroller_scroll_cb, s_info.view_scroller);
374
375         evas_object_smart_callback_add(s_info.view_scroller, "edge,left",
376                         _scroller_edge_cb, s_info.view_scroller);
377         evas_object_smart_callback_add(s_info.view_scroller, "edge,right",
378                         _scroller_edge_cb, s_info.view_scroller);
379
380         _set_state(PAGER_STATE_IDLE);
381
382         return QP_OK;
383 }
384
385 static void _init_job_cb(void *data)
386 {
387         struct appdata *ad = (struct appdata *)data;
388         retif(ad == NULL, , "Invalid parameter!");
389         retif(s_info.view_scroller == NULL, , "Invalid parameter!");
390
391         _page_rotation(ad);
392
393         _page_show(PAGE_IDX_MAIN);
394         evas_object_show(s_info.view_scroller);
395 }
396
397 static int _fini(void *data)
398 {
399         struct appdata *ad = (struct appdata *)data;
400         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
401
402         if (s_info.hdl_up != NULL) {
403                 ecore_event_handler_del(s_info.hdl_up);
404         }
405         if (s_info.hdl_down != NULL) {
406                 ecore_event_handler_del(s_info.hdl_down);
407         }
408
409         return QP_OK;
410 }
411
412 static int _resume(void *data)
413 {
414         struct appdata *ad = data;
415         retif(ad == NULL, QP_FAIL, "Invalid parameter!");
416
417         return QP_OK;
418 }
419
420 static void _opened(void *data)
421 {
422         struct appdata *ad = data;
423         retif(ad == NULL, , "Invalid parameter!");
424
425         _page_mapbuf_enable_set(s_info.view_box, 0);
426
427         quickpanel_page_editing_icon_visible_status_update();
428 }
429
430 static void _closed(void *data)
431 {
432         struct appdata *ad = data;
433         retif(ad == NULL, , "Invalid parameter!");
434         retif(s_info.view_scroller == NULL, , "Invalid parameter!");
435
436         _page_show(PAGE_IDX_MAIN);
437         _page_mapbuf_enable_set(s_info.view_box, 0);
438
439         quickpanel_page_editing_icon_visible_status_update();
440 }
441
442 static void _refresh(void *data) {
443         struct appdata *ad = data;
444         retif(ad == NULL, , "Invalid parameter!");
445         retif(s_info.view_box == NULL, , "Invalid parameter!");
446         retif(s_info.view_scroller == NULL, , "Invalid parameter!");
447
448         _page_rotation(ad);
449 }
450
451 static void _scroller_resized_cb(void *data, Evas * e,
452         Evas_Object * obj, void *event_info)
453 {
454         _page_show(PAGE_IDX_MAIN);
455         evas_object_event_callback_del(s_info.view_scroller,
456                         EVAS_CALLBACK_RESIZE, _scroller_resized_cb);
457 }
458
459 HAPI Evas_Object *quickpanel_pager_new(Evas_Object *parent, void *data) {
460         Evas_Object *box = NULL;
461         Evas_Object *scroller = NULL;
462
463         retif(parent == NULL, NULL, "failed to memory allocation");
464
465         if (s_info.view_scroller != NULL && s_info.view_box != NULL)
466                 return s_info.view_scroller;
467
468         scroller = elm_scroller_add(parent);
469         retif(!scroller, NULL, "fail to add scroller");
470         elm_scroller_bounce_set(scroller, EINA_TRUE, EINA_TRUE);
471         elm_scroller_propagate_events_set(scroller, EINA_FALSE);
472         elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
473         evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
474         evas_object_size_hint_fill_set(scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
475         elm_scroller_page_relative_set (scroller, 1.0, 0.0);
476
477         box = elm_box_add(scroller);
478         if (!box) {
479                 ERR("fail to add box");
480                 if (scroller != NULL) {
481                         evas_object_del(scroller);
482                         scroller = NULL;
483                 }
484                 return EINA_FALSE;
485         }
486         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
487         evas_object_size_hint_fill_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
488         elm_box_horizontal_set(box, EINA_TRUE);
489         evas_object_show(box);
490
491         elm_object_content_set(scroller, box);
492
493         s_info.view_scroller = scroller;
494         s_info.view_box = box;
495
496         evas_object_event_callback_add(s_info.view_scroller, EVAS_CALLBACK_RESIZE,
497                         _scroller_resized_cb, NULL);
498
499         return scroller;
500 }
501
502 HAPI void quickpanel_pager_destroy(void) {
503         if (s_info.view_box != NULL) {
504                 elm_box_unpack_all(s_info.view_box);
505                 evas_object_del(s_info.view_box);
506                 s_info.view_box = NULL;
507         }
508         if (s_info.view_scroller != NULL) {
509                 evas_object_del(s_info.view_scroller);
510                 s_info.view_scroller = NULL;
511         }
512 }
513
514 HAPI Evas_Object *quickpanel_pager_view_get(const char *view_name) {
515         retif(view_name == NULL, NULL, "invalid parameter");
516
517         if (strcmp(view_name, "SCROLLER") == 0) {
518                 return s_info.view_scroller;
519
520         } else if (strcmp(view_name, "BOX") == 0) {
521                 return s_info.view_box;
522         }
523
524         return NULL;
525 }
526
527 HAPI int quickpanel_pager_current_page_get(void) {
528         int index = 0;
529
530         elm_scroller_current_page_get(s_info.view_scroller, &index, NULL);
531
532         return index;
533 }
534
535 HAPI void quickpanel_pager_page_set(int page_index, int need_resize) {
536         struct appdata *ad = quickpanel_get_app_data();
537         retif(ad == NULL, , "invalid parameter");
538
539         if (need_resize) {
540                 _page_rotation(ad);
541         }
542         _page_show(page_index);
543
544         evas_object_show(s_info.view_scroller);
545 }
546
547 HAPI void quickpanel_pager_mapbuf_set(int is_enable) {
548         _page_mapbuf_enable_set(s_info.view_box, is_enable);
549 }