Tizen 2.1 base
[apps/core/preloaded/quickpanel.git] / daemon / notifications / noti_gridbox.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 #include <Ecore_X.h>
18
19 #include "quickpanel-ui.h"
20 #include "common.h"
21 #include "list_util.h"
22 #include "quickpanel_theme_def.h"
23 #include "noti_gridbox.h"
24 #include "noti_box.h"
25
26 #define E_DATA_LAYOUT_PORTRAIT "layout_portrait"
27 #define E_DATA_LAYOUT_LANDSCAPE "layout_landscape"
28 #define E_DATA_CB_DELETE_ITEM "cb_delete_item"
29 #define E_DATA_CB_REMOVED "cb_removed"
30 #define E_DATA_APP_DATA "app_data"
31
32 typedef struct _gridbox_info_layout {
33         int n_per_rows;
34         int padding_top;
35         int padding_left;
36         int padding_right;
37         int padding_bottom;
38         int padding_between;
39         int child_w;
40         int child_h;
41         double scale;
42 } gridbox_info_layout;
43
44 typedef struct _gridbox_info_animation {
45         Evas_Object *gridbox;
46         Evas_Object *item;
47
48         void (*update_cb)(Evas_Object *list, void *data, int is_prepend);
49         Evas_Object *container;
50         void *noti;
51         int pos;
52 } gridbox_info_animation;
53
54 static void _gridbox_layout_get_pos(int order, int *x, int *y, void *data) {
55         gridbox_info_layout *info_layout = data;
56
57         retif(data == NULL, , "invalid parameter");
58         retif(x == NULL, , "invalid parameter");
59         retif(y == NULL, , "invalid parameter");
60
61         int n_per_row = info_layout->n_per_rows;
62
63         int row = (order - 1) / n_per_row;
64         int column = (order - 1) - (row * n_per_row);
65
66         //DBG("order:%d r:%d c:%d", order, row, column);
67
68         int row_x = info_layout->padding_left
69                         + ((info_layout->child_w + info_layout->padding_between) * column);
70
71         int row_y = info_layout->padding_top
72                         + ((info_layout->child_h + info_layout->padding_between) * row);
73
74         *x = row_x;
75         *y = row_y;
76 }
77
78 static void _gridbox_layout(Evas_Object *o, Evas_Object_Box_Data *priv,
79                 void *data) {
80         int n_children;
81         int x, y, w, h;
82         int off_x = 0, off_y = 0;
83         Eina_List *l;
84         Eina_List *l_next;
85         Evas_Object_Box_Option *opt;
86         int child_w, child_h;
87
88         retif(o == NULL, , "invalid parameter");
89         retif(priv == NULL, , "invalid parameter");
90         retif(data == NULL, , "invalid parameter");
91
92         gridbox_info_layout *info_layout = (gridbox_info_layout *) data;
93
94         n_children = eina_list_count(priv->children);
95         DBG("layout function:%d", n_children);
96         DBG("ref count:%p(%d)",o, evas_object_ref_get(o));
97         if (!n_children) {
98                 return;
99         }
100
101         //box geometry
102         evas_object_geometry_get(o, &x, &y, &w, &h);
103
104         //set info about children
105         opt = eina_list_data_get(priv->children);
106         evas_object_size_hint_min_get(opt->obj, &child_w, &child_h);
107
108         info_layout->child_w = child_w;
109         info_layout->child_h = child_h;
110
111         DBG("grid layout children:%d %d", child_w, child_h);
112
113         int order_children = 1;
114         EINA_LIST_FOREACH_SAFE(priv->children, l, l_next, opt)
115         {
116                 _gridbox_layout_get_pos(order_children, &off_x, &off_y, info_layout);
117                 evas_object_move(opt->obj, x + off_x, y + off_y);
118                 evas_object_resize(opt->obj, info_layout->child_w,
119                                 info_layout->child_h);
120                 order_children++;
121         }
122
123         evas_object_size_hint_min_set(o, -1,
124                         off_y + info_layout->child_h + info_layout->padding_bottom);
125 }
126
127 Evas_Object *gridbox_create(Evas_Object *parent, void *data) {
128
129         retif(parent == NULL, NULL, "invalid parameter");
130         retif(data == NULL, NULL, "invalid parameter");
131         struct appdata *ad = data;
132         Evas_Object *gridbox = NULL;
133
134         gridbox_info_layout *info_layout_portrait = NULL;
135         gridbox_info_layout *info_layout_landscape = NULL;
136
137         info_layout_portrait = (gridbox_info_layout *) malloc(
138                         sizeof(gridbox_info_layout));
139         retif(info_layout_portrait == NULL, NULL, "memory allocation failed");
140         info_layout_portrait->padding_between = 12 * ad->scale;
141         info_layout_portrait->padding_top = 0;
142         info_layout_portrait->padding_left = 14 * ad->scale;
143         info_layout_portrait->padding_bottom = 12 * ad->scale;
144         info_layout_portrait->n_per_rows = 2;
145         info_layout_portrait->child_w = 0; //340;
146         info_layout_portrait->child_h = 0; //400;
147         info_layout_portrait->scale = ad->scale;
148
149         info_layout_landscape = (gridbox_info_layout *) malloc(
150                         sizeof(gridbox_info_layout));
151         retif(info_layout_landscape == NULL, NULL, "memory allocation failed");
152         info_layout_landscape->padding_between = 12 * ad->scale;
153         info_layout_landscape->padding_top = 0;
154         info_layout_landscape->padding_left = 14 * ad->scale;
155         info_layout_landscape->padding_bottom = 12 * ad->scale;
156         info_layout_landscape->n_per_rows = 3;
157         info_layout_landscape->child_w = 0; //409;
158         info_layout_landscape->child_h = 0; //400;
159         info_layout_landscape->scale = ad->scale;
160
161         gridbox = elm_box_add(parent);
162         evas_object_size_hint_weight_set(gridbox, EVAS_HINT_EXPAND,
163                         EVAS_HINT_EXPAND);
164         evas_object_size_hint_align_set(gridbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
165
166         if (ad->angle == 270 || ad->angle == 90)
167                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_landscape,
168                                 NULL);
169         else
170                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_portrait,
171                                 NULL);
172
173         evas_object_ref(gridbox);
174         evas_object_show(gridbox);
175
176         evas_object_data_set(gridbox, E_DATA_LAYOUT_PORTRAIT, info_layout_portrait);
177         evas_object_data_set(gridbox, E_DATA_LAYOUT_LANDSCAPE,
178                         info_layout_landscape);
179         evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, NULL);
180         evas_object_data_set(gridbox, E_DATA_APP_DATA, ad);
181
182         return gridbox;
183 }
184
185 void gridbox_remove(Evas_Object *gridbox) {
186
187         retif(gridbox == NULL, , "invalid parameter");
188
189         gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox,
190                         E_DATA_LAYOUT_PORTRAIT);
191         gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox,
192                         E_DATA_LAYOUT_LANDSCAPE);
193
194         gridbox_remove_all_item(gridbox, 0);
195         evas_object_data_del(gridbox, E_DATA_LAYOUT_PORTRAIT);
196         evas_object_data_del(gridbox, E_DATA_LAYOUT_LANDSCAPE);
197         evas_object_data_del(gridbox, E_DATA_CB_DELETE_ITEM);
198         evas_object_data_del(gridbox, E_DATA_APP_DATA);
199         evas_object_unref(gridbox);
200         evas_object_del(gridbox);
201
202         if (info_layout_portrait != NULL)
203                 free(info_layout_portrait);
204         if (info_layout_landscape != NULL)
205                 free(info_layout_landscape);
206 }
207
208 void gridbox_set_item_deleted_cb(Evas_Object *gridbox,
209                 void(*deleted_cb)(void *data, Evas_Object *obj)) {
210         retif(gridbox == NULL, , "invalid parameter");
211         retif(deleted_cb == NULL, , "invalid parameter");
212
213         evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, deleted_cb);
214 }
215
216 static void _gridbox_call_item_deleted_cb(Evas_Object *gridbox, void *data,
217                 Evas_Object *obj) {
218         retif(gridbox == NULL, , "invalid parameter");
219
220         void (*deleted_cb)(void *data, Evas_Object *obj) = NULL;
221
222         deleted_cb = evas_object_data_get(gridbox, E_DATA_CB_DELETE_ITEM);
223
224         if (deleted_cb != NULL) {
225                 deleted_cb(data, obj);
226         }
227 }
228
229 void gridbox_add_item(Evas_Object *gridbox, Evas_Object *item, int is_prepend) {
230         const char *signal = NULL;
231
232         retif(gridbox == NULL, , "invalid parameter");
233         retif(item == NULL, , "invalid parameter");
234
235         struct appdata *ad = evas_object_data_get(gridbox, E_DATA_APP_DATA);
236
237         if (ad != NULL) {
238                 if (ad->angle == 270 || ad->angle == 90) {
239                         signal = "box.landscape";
240                 } else {
241                         signal = "box.portrait";
242                 }
243         }
244
245         DBG("set to %s, %x", signal, item);
246
247         elm_object_signal_emit(item, signal, "box.prog");
248         edje_object_message_signal_process(_EDJ(item));
249         elm_layout_sizing_eval(item);
250
251         if (is_prepend == GRIDBOX_PREPEND)
252                 elm_box_pack_start(gridbox, item);
253         else
254                 elm_box_pack_end(gridbox, item);
255 }
256
257 static void _gridbox_remove_item_anim_cb(void *data, Elm_Transit *transit) {
258         DBG("");
259         retif(data == NULL, , "invalid parameter");
260         retif(transit == NULL, , "invalid parameter");
261
262         gridbox_info_animation *info_animation = data;
263
264         retif(info_animation->gridbox == NULL, , "invalid parameter");
265         retif(info_animation->item == NULL, , "invalid parameter");
266
267         DBG("remove:%p", info_animation->item);
268
269         elm_box_unpack(info_animation->gridbox, info_animation->item);
270
271         _gridbox_call_item_deleted_cb(info_animation->gridbox,
272                         noti_box_node_get(info_animation->item), info_animation->item);
273         noti_box_remove(info_animation->item);
274
275         if (info_animation->update_cb != NULL) {
276                 retif(info_animation->container == NULL, , "invalid parameter");
277                 retif(info_animation->noti == NULL, , "invalid parameter");
278
279                 info_animation->update_cb(info_animation->container,
280                                 info_animation->noti, info_animation->pos);
281         }
282
283         free(info_animation);
284         info_animation = NULL;
285 }
286
287 void gridbox_remove_item(Evas_Object *gridbox, Evas_Object *item, int with_animation) {
288         DBG("remove:%p", item);
289         retif(gridbox == NULL, , "invalid parameter");
290         retif(item == NULL, , "invalid parameter");
291
292         if (noti_box_get_status(item) == STATE_DELETING) {
293                 return ;
294         }
295         noti_box_set_status(item, STATE_DELETING);
296
297         if (with_animation == 1) {
298                 gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc(
299                                 sizeof(gridbox_info_animation));
300                 if (info_animation == NULL)
301                         return;
302                 info_animation->gridbox = gridbox;
303                 info_animation->item = item;
304                 info_animation->update_cb = NULL;
305                 info_animation->container = NULL;
306                 info_animation->noti = NULL;
307                 info_animation->pos = 0;
308
309                 Elm_Transit *transit = elm_transit_add();
310                 //Fade in and out with layout object.
311                 elm_transit_object_add(transit, item);
312                 elm_transit_effect_fade_add(transit);
313                 elm_transit_duration_set(transit, 0.7);
314                 elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb,
315                                 info_animation);
316                 elm_transit_go(transit);
317         } else {
318                 _gridbox_call_item_deleted_cb(gridbox,
319                                 noti_box_node_get(item), item);
320                 elm_box_unpack(gridbox, item);
321                 noti_box_remove(item);
322         }
323 }
324
325 void gridbox_remove_all_item(Evas_Object *gridbox, int with_animation) {
326         DBG("");
327         retif(gridbox == NULL, , "invalid parameter");
328
329         Eina_List *l;
330         Eina_List *l_next;
331         Evas_Object *obj;
332         Eina_List *item_list = elm_box_children_get(gridbox);
333
334         EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj)
335         {
336                 if (obj != NULL) {
337                         // call deleted callback
338                         gridbox_remove_item(gridbox, obj, with_animation);
339                 }
340         }
341 }
342
343 void gridbox_update_item(Evas_Object *gridbox, Evas_Object *item) {
344
345         retif(gridbox == NULL, , "invalid parameter");
346         retif(item == NULL, , "invalid parameter");
347 }
348
349 void gridbox_remove_and_add_item(Evas_Object *gridbox, Evas_Object *item
350                 ,void (*update_cb)(Evas_Object *list, void *data, int is_prepend)
351                 ,void *container, void *data, int pos) {
352
353         retif(gridbox == NULL, , "invalid parameter");
354         retif(item == NULL, , "invalid parameter");
355         retif(update_cb == NULL, , "invalid parameter");
356         retif(container == NULL, , "invalid parameter");
357         retif(data == NULL, , "invalid parameter");
358
359         if (noti_box_get_status(item) == STATE_DELETING) {
360                 return ;
361         }
362         noti_box_set_status(item, STATE_DELETING);
363
364         gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc(
365                         sizeof(gridbox_info_animation));
366         if (info_animation == NULL)
367                 return;
368         info_animation->gridbox = gridbox;
369         info_animation->item = item;
370         info_animation->update_cb = update_cb;
371         info_animation->container = container;
372         info_animation->noti = data;
373         info_animation->pos = pos;
374
375         Elm_Transit *transit = elm_transit_add();
376         //Fade in and out with layout object.
377         elm_transit_object_add(transit, item);
378         elm_transit_effect_fade_add(transit);
379         elm_transit_duration_set(transit, 0.4);
380         elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb,
381                         info_animation);
382         elm_transit_go(transit);
383 }
384
385 void gridbox_finalize_rotation_cb(void *data) {
386         retif(data == NULL, , "invalid parameter");
387         Evas_Object *gridbox = data;
388
389         elm_box_recalculate(gridbox);
390 }
391
392 void gridbox_rotation(Evas_Object *gridbox, int angle) {
393         const char *signal = NULL;
394
395         retif(gridbox == NULL, , "invalid parameter");
396
397         gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox,
398                         E_DATA_LAYOUT_PORTRAIT);
399         gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox,
400                         E_DATA_LAYOUT_LANDSCAPE);
401
402         retif(info_layout_portrait == NULL || info_layout_landscape == NULL, ,
403                         "gridbox is crashed");
404
405         Eina_List *l;
406         Eina_List *l_next;
407         Evas_Object *obj;
408         Eina_List *item_list = elm_box_children_get(gridbox);
409
410         if (angle == 270 || angle == 90) {
411                 signal = "box.landscape";
412         } else {
413                 signal = "box.portrait";
414         }
415
416         DBG("all count:%d", eina_list_count (item_list));
417
418         EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj)
419         {
420                 if (obj != NULL) {
421                         elm_object_signal_emit(obj, signal, "box.prog");
422                         edje_object_message_signal_process(_EDJ(obj));
423                         elm_layout_sizing_eval(obj);
424                         DBG("set to %s, %x", signal, obj);
425                 }
426         }
427
428         if (angle == 270 || angle == 90) {
429                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_landscape,
430                                 NULL);
431
432 #if 0
433                 layout_data = elm_box_transition_new(0.0, _gridbox_layout,
434                                 info_layout_portrait, NULL, _gridbox_layout,
435                                 info_layout_landscape, NULL, gridbox_finalize_rotation_cb,
436                                 gridbox);
437 #endif
438         } else {
439                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_portrait,
440                                 NULL);
441 #if 0
442                 layout_data = elm_box_transition_new(0.0, _gridbox_layout,
443                                 info_layout_landscape, NULL, _gridbox_layout,
444                                 info_layout_portrait, NULL, gridbox_finalize_rotation_cb,
445                                 gridbox);
446 #endif
447         }
448
449 #if 0
450         elm_box_layout_set(gridbox, elm_box_layout_transition, layout_data,
451                         elm_box_transition_free);
452 #endif
453         DBG("Angle  Rotation  is %d", angle);
454 }