[Task-mgr] Fixed scale and long size name issues
[apps/core/preloaded/taskmanager.git] / src / scroller.c
1 /*
2  *  Task Manager
3  *
4  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20  #include <Elementary.h>
21
22  #include "conf.h"
23  #include "item.h"
24  #include "list.h"
25  #include "log.h"
26  #include "main.h"
27  #include "scroller.h"
28  #include "util.h"
29
30 #define PRIVATE_DATA_KEY_DRAG "pri_drag"
31 #define PRIVATE_DATA_KEY_MOUSE_DOWN "pri_m_dw"
32 #define PRIVATE_DATA_KEY_POP_ALL_TIMER "pri_pop_tm"
33 #define PRIVATE_DATA_KEY_REVERSE_LIST "pri_re_li"
34 #define PRIVATE_DATA_KEY_TERMINATE "pri_tm"
35
36
37
38 extern task_mgr_error_e scroller_push_item(Evas_Object *scroller, Evas_Object *item)
39 {
40         _D("");
41         retv_if(!scroller, TASK_MGR_ERROR_INVALID_PARAMETER);
42         retv_if(!item, TASK_MGR_ERROR_INVALID_PARAMETER);
43
44         Evas_Object *box_layout = NULL;
45         Evas_Object *box = NULL;
46         Eina_List *list = NULL;
47
48         box_layout = elm_object_content_get(scroller);
49         retv_if(!box_layout, TASK_MGR_ERROR_FAIL);
50
51         list = elm_box_children_get(box_layout);
52         retv_if(!list, TASK_MGR_ERROR_FAIL);
53
54         box = eina_list_nth(list, 0);
55         retv_if(!box, TASK_MGR_ERROR_FAIL);
56
57         eina_list_free(list);
58
59         elm_box_pack_end(box, item);
60
61         return TASK_MGR_ERROR_NONE;
62 }
63
64
65
66 extern void scroller_pop_item(Evas_Object *scroller, Evas_Object *item, int terminate)
67 {
68         ret_if(!scroller);
69         ret_if(!item);
70
71         Evas_Object *box_layout = NULL;
72         Evas_Object *box = NULL;
73
74         Eina_List *box_list = NULL;
75         Eina_List *list = NULL;
76
77         box_layout = elm_object_content_get(scroller);
78         ret_if(!box_layout);
79
80         box_list = elm_box_children_get(box_layout);
81         ret_if(!box_list);
82
83         box = eina_list_nth(box_list, 0);
84         ret_if(!box);
85
86         eina_list_free(box_list);
87
88         if (terminate) item_terminate(item);
89
90         elm_box_unpack(box, item);
91         item_destroy(item);
92 }
93
94
95
96 extern task_mgr_error_e scroller_push_all_item(Evas_Object *scroller, Eina_List *list)
97 {
98         const Eina_List *l = NULL;
99         const Eina_List *ln = NULL;
100         list_type_default_s *info = NULL;
101         Evas_Object *item = NULL;
102
103         if (!list) {
104                 _D("No app in the history list");
105                 return TASK_MGR_ERROR_NONE;
106         }
107
108         EINA_LIST_FOREACH_SAFE(list, l, ln, info) {
109                 if (!info) continue;
110                 item = item_create(scroller, info);
111                 continue_if(!item);
112                 scroller_push_item(scroller, item);
113         }
114
115         return TASK_MGR_ERROR_NONE;
116 }
117
118
119
120 static Eina_Bool _pop_all_item_cb(void *data)
121 {
122         Evas_Object *scroller = data;
123         Evas_Object *item = NULL;
124         Eina_List *list = NULL;
125         static int i = 0;
126         int count = 0;
127         int terminate = (int) evas_object_data_get(scroller, PRIVATE_DATA_KEY_TERMINATE);
128
129         list = evas_object_data_get(scroller, PRIVATE_DATA_KEY_REVERSE_LIST);
130         goto_if(!list, END);
131
132         count = eina_list_count(list);
133         _D("remove list count(include clear button) : %d", count);
134         if (i >= count-1) goto END;
135
136         item = eina_list_nth(list, i);
137         i++;
138         goto_if(!item, END);
139
140         scroller_pop_item(scroller, item, terminate);
141         return ECORE_CALLBACK_RENEW;
142
143 END:
144         i = 0;
145         eina_list_free(list);
146         evas_object_data_del(scroller, PRIVATE_DATA_KEY_REVERSE_LIST);
147         evas_object_data_del(scroller, PRIVATE_DATA_KEY_TERMINATE);
148         evas_object_data_del(scroller, PRIVATE_DATA_KEY_POP_ALL_TIMER);
149         item_clear_set_disable(scroller);
150
151         return ECORE_CALLBACK_CANCEL;
152 }
153
154
155
156 extern void scroller_pop_all_item(Evas_Object *scroller, int terminate)
157 {
158         Evas_Object *box_layout = NULL;
159         Evas_Object *box = NULL;
160         Eina_List *box_list = NULL;
161         Eina_List *list = NULL;
162         Eina_List *reverse_list = NULL;
163         Ecore_Timer *timer = NULL;
164
165         ret_if(!scroller);
166
167         timer = evas_object_data_del(scroller, PRIVATE_DATA_KEY_POP_ALL_TIMER);
168         if (timer) {
169                 _D("There is already a timer for popping all items.");
170                 return;
171         }
172
173         /* An user tap the end all button, all items have to be terminated even if paused. */
174         if (!evas_object_data_get(scroller, PRIVATE_DATA_KEY_TERMINATE)) {
175                 evas_object_data_set(scroller, PRIVATE_DATA_KEY_TERMINATE, (void *) terminate);
176         }
177
178         box_layout = elm_object_content_get(scroller);
179         ret_if(!box_layout);
180
181         box_list = elm_box_children_get(box_layout);
182         ret_if(!box_list);
183
184         box = eina_list_nth(box_list, 0);
185         ret_if(!box);
186
187         eina_list_free(box_list);
188
189         list = elm_box_children_get(box);
190         if (!list) return;
191
192         /* This reverse list should be freed in the timer */
193         reverse_list = eina_list_reverse_clone(list);
194         eina_list_free(list);
195         ret_if(!reverse_list);
196         evas_object_data_set(scroller, PRIVATE_DATA_KEY_REVERSE_LIST, reverse_list);
197
198         timer = ecore_timer_add(0.01f, _pop_all_item_cb, scroller);
199         if (!timer) {
200                 _E("Cannot add a timer");
201                 evas_object_data_del(scroller, PRIVATE_DATA_KEY_REVERSE_LIST);
202                 evas_object_data_del(scroller, PRIVATE_DATA_KEY_TERMINATE);
203                 eina_list_free(reverse_list);
204                 return;
205         }
206
207         evas_object_data_set(scroller, PRIVATE_DATA_KEY_POP_ALL_TIMER, timer);
208 }
209
210
211
212 extern int scroller_count(Evas_Object *scroller)
213 {
214         Evas_Object *box_layout = NULL;
215         Evas_Object *box = NULL;
216         Eina_List *box_list = NULL;
217         Eina_List *list = NULL;
218
219         retv_if(!scroller, 0);
220
221         box_layout = elm_object_content_get(scroller);
222         retv_if(!box_layout, 0);
223
224         box_list = elm_box_children_get(box_layout);
225         retv_if(!box_list, 0);
226
227         box = eina_list_nth(box_list, 0);
228         retv_if(!box, 0);
229
230         eina_list_free(box_list);
231
232         list = elm_box_children_get(box);
233         if (!list) {
234                 _D("list is null");
235                 return 0;
236         }
237
238         return eina_list_count(list);
239 }
240
241
242
243 extern Eina_Bool scroller_is_scrolling(Evas_Object *scroller)
244 {
245         return evas_object_data_get(scroller, DATA_KEY_IS_SCROLLING)? EINA_TRUE:EINA_FALSE;
246 }
247
248
249
250 extern void scroller_freeze(Evas_Object *scroller)
251 {
252         Evas_Object *box_layout = NULL;
253         Evas_Object *box = NULL;
254         Eina_List *list = NULL;
255
256         ret_if(!scroller);
257
258         box_layout = elm_object_content_get(scroller);
259         ret_if(!box_layout);
260
261         list = elm_box_children_get(box_layout);
262         ret_if(!list);
263
264         box = eina_list_nth(list, 0);
265         ret_if(!box);
266
267         eina_list_free(list);
268
269         elm_object_scroll_freeze_push(box);
270 }
271
272
273
274 extern void scroller_unfreeze(Evas_Object *scroller)
275 {
276         Evas_Object *box_layout = NULL;
277         Evas_Object *box = NULL;
278         Eina_List *list = NULL;
279
280         ret_if(!scroller);
281
282         box_layout = elm_object_content_get(scroller);
283         ret_if(!box_layout);
284
285         list = elm_box_children_get(box_layout);
286         ret_if(!list);
287
288         box = eina_list_nth(list, 0);
289         ret_if(!box);
290
291         eina_list_free(list);
292
293         while (elm_object_scroll_freeze_get(box)) {
294                 elm_object_scroll_freeze_pop(box);
295         }
296 }
297
298
299
300 static void _mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
301 {
302         _D("Mouse is down");
303         evas_object_data_set(obj, PRIVATE_DATA_KEY_MOUSE_DOWN, (void *) 1);
304 }
305
306
307
308 static void _mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
309 {
310         _D("Mouse is up");
311         evas_object_data_del(obj, PRIVATE_DATA_KEY_MOUSE_DOWN);
312         if (evas_object_data_get(obj, PRIVATE_DATA_KEY_DRAG)) return;
313         evas_object_data_del(obj, DATA_KEY_IS_SCROLLING);
314 }
315
316
317
318 static void _anim_start_cb(void *data, Evas_Object *scroller, void *event_info)
319 {
320         _D("start the scroller animation");
321         evas_object_data_set(scroller, DATA_KEY_IS_SCROLLING, (void *) 1);
322 }
323
324
325
326 static void _anim_stop_cb(void *data, Evas_Object *scroller, void *event_info)
327 {
328         _D("stop the scroller animation");
329         if (evas_object_data_get(scroller, PRIVATE_DATA_KEY_MOUSE_DOWN)) return;
330         evas_object_data_del(scroller, DATA_KEY_IS_SCROLLING);
331 }
332
333
334
335 static void _drag_start_cb(void *data, Evas_Object *scroller, void *event_info)
336 {
337         _D("start to drag the scroller animation");
338         evas_object_data_set(scroller, PRIVATE_DATA_KEY_DRAG, (void *) 1);
339 }
340
341
342
343 static void _drag_stop_cb(void *data, Evas_Object *scroller, void *event_info)
344 {
345         _D("stop to drag the scroller animation");
346         evas_object_data_del(scroller, PRIVATE_DATA_KEY_DRAG);
347 }
348
349
350
351 static void _scroll_cb(void *data, Evas_Object *scroller, void *event_info)
352 {
353         evas_object_data_set(scroller, DATA_KEY_IS_SCROLLING, (void *) 1);
354 }
355
356
357
358 static void __resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
359 {
360         Evas_Object *scroller = obj;
361
362         int x, y, w, h;
363
364         ret_if(!scroller);
365
366         evas_object_geometry_get(scroller, &x, &y, &w, &h);
367         _D("%s resize(%d, %d, %d, %d)", data, x, y, w, h);
368 }
369
370
371
372 extern Evas_Object *scroller_create(Evas_Object *layout)
373 {
374         retv_if(!layout, NULL);
375
376         Evas_Object *box = NULL;
377         Evas_Object *box_layout = NULL;
378         Evas_Object *rect = NULL;
379         Evas_Object *scroller = NULL;
380
381         scroller = elm_scroller_add(layout);
382         retv_if(!scroller, NULL);
383
384         elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_FALSE);
385         elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
386         elm_object_style_set(scroller, "effect");
387
388         elm_object_part_content_set(layout, "scroller", scroller);
389         evas_object_show(scroller);
390         evas_object_size_hint_align_set(scroller, 0.5, 1.0);
391
392         evas_object_event_callback_add(scroller, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, NULL);
393         evas_object_event_callback_add(scroller, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, NULL);
394         evas_object_smart_callback_add(scroller, "scroll,anim,start", _anim_start_cb, NULL);
395         evas_object_smart_callback_add(scroller, "scroll,anim,stop", _anim_stop_cb, NULL);
396         evas_object_smart_callback_add(scroller, "scroll,drag,start", _drag_start_cb, NULL);
397         evas_object_smart_callback_add(scroller, "scroll,drag,stop", _drag_stop_cb, NULL);
398         evas_object_smart_callback_add(scroller, "scroll", _scroll_cb, NULL);
399
400         /* Because change an align in box, use the another box betweein box and scroller. */
401         box_layout = elm_box_add(scroller);
402         if (!box_layout) {
403                 _E("Fail to create box layout");
404                 evas_object_del(scroller);
405                 return NULL;
406         }
407         elm_box_horizontal_set(box_layout, EINA_FALSE);
408         elm_box_align_set(box_layout, 0.5, 1.0);
409         evas_object_size_hint_align_set(box_layout, 0.5, 1.0);
410         evas_object_size_hint_weight_set(box_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
411         elm_object_content_set(scroller, box_layout);
412         evas_object_show(box_layout);
413
414         box = elm_box_add(scroller);
415         if (!box) {
416                 _E("Fail to create box");
417                 evas_object_del(box_layout);
418                 evas_object_del(scroller);
419                 return NULL;
420         }
421         elm_box_horizontal_set(box, EINA_FALSE);
422         elm_box_align_set(box, 0.5, 1.0);
423         evas_object_size_hint_align_set(box, 0.5, 1.0);
424         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
425         elm_box_pack_end(box_layout, box);
426         evas_object_show(box);
427         main_get_info()->box = box;
428
429         evas_object_event_callback_add(scroller, EVAS_CALLBACK_RESIZE, __resize_cb, "scroller");
430         evas_object_event_callback_add(box_layout, EVAS_CALLBACK_RESIZE, __resize_cb, "box_layout");
431         evas_object_event_callback_add(box, EVAS_CALLBACK_RESIZE, __resize_cb, "box");
432
433         return scroller;
434 }
435
436
437
438 void scroller_destroy(Evas_Object *scroller)
439 {
440         ret_if(!scroller);
441
442         Evas_Object *item = NULL;
443         Evas_Object *box_layout = NULL;
444         Evas_Object *box = NULL;
445         Evas_Object *rect = NULL;
446         Eina_List *box_list = NULL;
447         Eina_List *list = NULL;
448
449         ret_if(!scroller);
450
451         box_layout = elm_object_content_get(scroller);
452         ret_if(!box_layout);
453
454         box_list = elm_box_children_get(box_layout);
455         ret_if(!box_list);
456
457         box = eina_list_nth(box_list, 0);
458         ret_if(!box);
459         eina_list_free(box_list);
460
461         list = elm_box_children_get(box);
462         if (!list) {
463                 _D("list is empty");
464                 return;
465         }
466
467         EINA_LIST_FREE(list, item) {
468                 if (!item) break;
469                 elm_box_unpack(box, item);
470                 item_destroy(item);
471         }
472
473         evas_object_del(box);
474         evas_object_del(box_layout);
475
476         evas_object_event_callback_del(scroller, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb);
477         evas_object_event_callback_del(scroller, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb);
478         evas_object_smart_callback_del(scroller, "scroll,anim,start", _anim_start_cb);
479         evas_object_smart_callback_del(scroller, "scroll,anim,stop", _anim_stop_cb);
480         evas_object_smart_callback_del(scroller, "scroll,drag,start", _drag_start_cb);
481         evas_object_smart_callback_del(scroller, "scroll,drag,stop", _drag_stop_cb);
482         evas_object_smart_callback_del(scroller, "scroll", _scroll_cb);
483
484         evas_object_del(scroller);
485 }
486
487
488
489 /* End of the file */