sync with private git
[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_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         if (!n_children) {
97                 evas_object_size_hint_min_set(o, -1, 0);
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 HAPI 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_show(gridbox);
174
175         evas_object_data_set(gridbox, E_DATA_LAYOUT_PORTRAIT, info_layout_portrait);
176         evas_object_data_set(gridbox, E_DATA_LAYOUT_LANDSCAPE,
177                         info_layout_landscape);
178         evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, NULL);
179         evas_object_data_set(gridbox, E_DATA_APP_DATA, ad);
180
181         qp_item_data *qid
182                 = quickpanel_list_util_item_new(QP_ITEM_TYPE_NOTI, NULL);
183         quickpanel_list_util_item_set_tag(gridbox, qid);
184
185         return gridbox;
186 }
187
188 HAPI void gridbox_remove(Evas_Object *gridbox) {
189
190         retif(gridbox == NULL, , "invalid parameter");
191
192         gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox,
193                         E_DATA_LAYOUT_PORTRAIT);
194         gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox,
195                         E_DATA_LAYOUT_LANDSCAPE);
196
197         gridbox_remove_all_item(gridbox, 0);
198         evas_object_data_del(gridbox, E_DATA_LAYOUT_PORTRAIT);
199         evas_object_data_del(gridbox, E_DATA_LAYOUT_LANDSCAPE);
200         evas_object_data_del(gridbox, E_DATA_CB_DELETE_ITEM);
201         evas_object_data_del(gridbox, E_DATA_APP_DATA);
202         quickpanel_list_util_item_del_tag(gridbox);
203         evas_object_del(gridbox);
204
205         if (info_layout_portrait != NULL)
206                 free(info_layout_portrait);
207         if (info_layout_landscape != NULL)
208                 free(info_layout_landscape);
209 }
210
211 HAPI void gridbox_set_item_deleted_cb(Evas_Object *gridbox,
212                 void(*deleted_cb)(void *data, Evas_Object *obj)) {
213         retif(gridbox == NULL, , "invalid parameter");
214         retif(deleted_cb == NULL, , "invalid parameter");
215
216         evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, deleted_cb);
217 }
218
219 static void _gridbox_call_item_deleted_cb(Evas_Object *gridbox, void *data,
220                 Evas_Object *obj) {
221         retif(gridbox == NULL, , "invalid parameter");
222
223         void (*deleted_cb)(void *data, Evas_Object *obj) = NULL;
224
225         deleted_cb = evas_object_data_get(gridbox, E_DATA_CB_DELETE_ITEM);
226
227         if (deleted_cb != NULL) {
228                 deleted_cb(data, obj);
229         }
230 }
231
232 HAPI void gridbox_add_item(Evas_Object *gridbox, Evas_Object *item, int is_prepend) {
233         const char *signal = NULL;
234
235         retif(gridbox == NULL, , "invalid parameter");
236         retif(item == NULL, , "invalid parameter");
237
238         struct appdata *ad = evas_object_data_get(gridbox, E_DATA_APP_DATA);
239
240         if (ad != NULL) {
241                 if (ad->angle == 270 || ad->angle == 90) {
242                         signal = "box.landscape";
243                 } else {
244                         signal = "box.portrait";
245                 }
246         }
247
248         DBG("set to %s, %x", signal, item);
249
250         elm_object_signal_emit(item, signal, "box.prog");
251         edje_object_message_signal_process(_EDJ(item));
252         elm_layout_sizing_eval(item);
253
254         if (is_prepend == GRIDBOX_PREPEND)
255                 elm_box_pack_start(gridbox, item);
256         else
257                 elm_box_pack_end(gridbox, item);
258 }
259
260 static void _gridbox_remove_item_anim_cb(void *data, Elm_Transit *transit) {
261         DBG("");
262         retif(data == NULL, , "invalid parameter");
263         retif(transit == NULL, , "invalid parameter");
264
265         gridbox_info_animation *info_animation = data;
266
267         retif(info_animation->gridbox == NULL, , "invalid parameter");
268         retif(info_animation->item == NULL, , "invalid parameter");
269
270         DBG("remove:%p", info_animation->item);
271
272         void *node = noti_box_node_get(info_animation->item);
273         elm_box_unpack(info_animation->gridbox, info_animation->item);
274         noti_box_remove(info_animation->item);
275         _gridbox_call_item_deleted_cb(info_animation->gridbox,
276                         node, NULL);
277
278         if (info_animation->update_cb != NULL) {
279                 retif(info_animation->container == NULL, , "invalid parameter");
280                 retif(info_animation->noti == NULL, , "invalid parameter");
281
282                 info_animation->update_cb(info_animation->container,
283                                 info_animation->noti, info_animation->pos);
284         }
285
286         free(info_animation);
287         info_animation = NULL;
288 }
289
290 HAPI void gridbox_remove_item(Evas_Object *gridbox, Evas_Object *item, int with_animation) {
291         DBG("remove:%p", item);
292         retif(gridbox == NULL, , "invalid parameter");
293         retif(item == NULL, , "invalid parameter");
294
295         if (noti_box_get_status(item) == STATE_DELETING) {
296                 return ;
297         }
298         noti_box_set_status(item, STATE_DELETING);
299
300         if (with_animation == 1) {
301                 gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc(
302                                 sizeof(gridbox_info_animation));
303                 if (info_animation == NULL)
304                         return;
305                 info_animation->gridbox = gridbox;
306                 info_animation->item = item;
307                 info_animation->update_cb = NULL;
308                 info_animation->container = NULL;
309                 info_animation->noti = NULL;
310                 info_animation->pos = 0;
311
312                 Elm_Transit *transit = elm_transit_add();
313                 //Fade in and out with layout object.
314                 elm_transit_object_add(transit, item);
315                 elm_transit_effect_fade_add(transit);
316                 elm_transit_duration_set(transit, 0.7);
317                 elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb,
318                                 info_animation);
319                 elm_transit_go(transit);
320         } else {
321                 void *node = noti_box_node_get(item);
322                 elm_box_unpack(gridbox, item);
323                 noti_box_remove(item);
324                 _gridbox_call_item_deleted_cb(gridbox,
325                                 node, NULL);
326         }
327 }
328
329 HAPI void gridbox_remove_all_item(Evas_Object *gridbox, int with_animation) {
330         DBG("");
331         retif(gridbox == NULL, , "invalid parameter");
332
333         Eina_List *l;
334         Eina_List *l_next;
335         Evas_Object *obj;
336         Eina_List *item_list = elm_box_children_get(gridbox);
337
338         EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj)
339         {
340                 if (obj != NULL) {
341                         // call deleted callback
342                         gridbox_remove_item(gridbox, obj, with_animation);
343                 }
344         }
345 }
346
347 HAPI void gridbox_update_item(Evas_Object *gridbox, Evas_Object *item) {
348
349         retif(gridbox == NULL, , "invalid parameter");
350         retif(item == NULL, , "invalid parameter");
351 }
352
353 HAPI void gridbox_remove_and_add_item(Evas_Object *gridbox, Evas_Object *item
354                 ,void (*update_cb)(Evas_Object *list, void *data, int is_prepend)
355                 ,void *container, void *data, int pos) {
356
357         retif(gridbox == NULL, , "invalid parameter");
358         retif(item == NULL, , "invalid parameter");
359         retif(update_cb == NULL, , "invalid parameter");
360         retif(container == NULL, , "invalid parameter");
361         retif(data == NULL, , "invalid parameter");
362
363         if (noti_box_get_status(item) == STATE_DELETING) {
364                 return ;
365         }
366         noti_box_set_status(item, STATE_DELETING);
367
368         gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc(
369                         sizeof(gridbox_info_animation));
370         if (info_animation == NULL)
371                 return;
372         info_animation->gridbox = gridbox;
373         info_animation->item = item;
374         info_animation->update_cb = update_cb;
375         info_animation->container = container;
376         info_animation->noti = data;
377         info_animation->pos = pos;
378
379         Elm_Transit *transit = elm_transit_add();
380         //Fade in and out with layout object.
381         elm_transit_object_add(transit, item);
382         elm_transit_effect_fade_add(transit);
383         elm_transit_duration_set(transit, 0.4);
384         elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb,
385                         info_animation);
386         elm_transit_go(transit);
387 }
388
389 HAPI void gridbox_finalize_rotation_cb(void *data) {
390         retif(data == NULL, , "invalid parameter");
391         Evas_Object *gridbox = data;
392
393         elm_box_recalculate(gridbox);
394 }
395
396 HAPI void gridbox_rotation(Evas_Object *gridbox, int angle) {
397         const char *signal = NULL;
398
399         retif(gridbox == NULL, , "invalid parameter");
400
401         gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox,
402                         E_DATA_LAYOUT_PORTRAIT);
403         gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox,
404                         E_DATA_LAYOUT_LANDSCAPE);
405
406         retif(info_layout_portrait == NULL || info_layout_landscape == NULL, ,
407                         "gridbox is crashed");
408
409         Eina_List *l;
410         Eina_List *l_next;
411         Evas_Object *obj;
412         Eina_List *item_list = elm_box_children_get(gridbox);
413
414         if (angle == 270 || angle == 90) {
415                 signal = "box.landscape";
416         } else {
417                 signal = "box.portrait";
418         }
419
420         DBG("all count:%d", eina_list_count (item_list));
421
422         EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj)
423         {
424                 if (obj != NULL) {
425                         elm_object_signal_emit(obj, signal, "box.prog");
426                         edje_object_message_signal_process(_EDJ(obj));
427                         elm_layout_sizing_eval(obj);
428                         DBG("set to %s, %x", signal, obj);
429                 }
430         }
431
432         if (angle == 270 || angle == 90) {
433                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_landscape,
434                                 NULL);
435
436 #if 0
437                 layout_data = elm_box_transition_new(0.0, _gridbox_layout,
438                                 info_layout_portrait, NULL, _gridbox_layout,
439                                 info_layout_landscape, NULL, gridbox_finalize_rotation_cb,
440                                 gridbox);
441 #endif
442         } else {
443                 elm_box_layout_set(gridbox, _gridbox_layout, info_layout_portrait,
444                                 NULL);
445 #if 0
446                 layout_data = elm_box_transition_new(0.0, _gridbox_layout,
447                                 info_layout_landscape, NULL, _gridbox_layout,
448                                 info_layout_portrait, NULL, gridbox_finalize_rotation_cb,
449                                 gridbox);
450 #endif
451         }
452
453 #if 0
454         elm_box_layout_set(gridbox, elm_box_layout_transition, layout_data,
455                         elm_box_transition_free);
456 #endif
457         DBG("Angle  Rotation  is %d", angle);
458 }