Add a task to copy configuration files to user's HOME dir from data dir for multi...
[platform/core/uifw/e17.git] / src / bin / e_layout.c
1 #include "e.h"
2
3 /* FIXME: something is weird here - i had to reverse all stacking logic to make
4  * it work... */
5
6 typedef struct _E_Smart_Data E_Smart_Data;
7 typedef struct _E_Layout_Item E_Layout_Item;
8
9 struct _E_Smart_Data
10 {
11    Evas_Coord       x, y, w, h;
12    Evas_Coord       vw, vh;
13    Evas_Object     *obj;
14    Evas_Object     *clip;
15    int              frozen;
16    unsigned char    changed : 1;
17    Eina_List       *items;
18 };
19
20 struct _E_Layout_Item
21 {
22    E_Smart_Data    *sd;
23    Evas_Coord       x, y, w, h;
24    Evas_Object     *obj;
25 };
26
27 /* local subsystem functions */
28 static E_Layout_Item *_e_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj);
29 static void        _e_layout_smart_disown(Evas_Object *obj);
30 static void        _e_layout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
31 static void        _e_layout_smart_reconfigure(E_Smart_Data *sd);
32 static void        _e_layout_smart_move_resize_item(E_Layout_Item *li);
33
34 static void _e_layout_smart_init(void);
35 static void _e_layout_smart_add(Evas_Object *obj);
36 static void _e_layout_smart_del(Evas_Object *obj);
37 static void _e_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
38 static void _e_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
39 static void _e_layout_smart_show(Evas_Object *obj);
40 static void _e_layout_smart_hide(Evas_Object *obj);
41 static void _e_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
42 static void _e_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
43 static void _e_layout_smart_clip_unset(Evas_Object *obj);
44
45 /* local subsystem globals */
46 static Evas_Smart *_e_smart = NULL;
47
48 /* externally accessible functions */
49 EAPI Evas_Object *
50 e_layout_add(Evas *evas)
51 {
52    _e_layout_smart_init();
53    return evas_object_smart_add(evas, _e_smart);
54 }
55
56 EAPI int
57 e_layout_freeze(Evas_Object *obj)
58 {
59    E_Smart_Data *sd;
60
61    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
62    sd = evas_object_smart_data_get(obj);
63    sd->frozen++;
64    return sd->frozen;
65 }
66
67 EAPI int
68 e_layout_thaw(Evas_Object *obj)
69 {
70    E_Smart_Data *sd;
71
72    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
73    sd = evas_object_smart_data_get(obj);
74    sd->frozen--;
75    if (sd->frozen <= 0) _e_layout_smart_reconfigure(sd);
76    return sd->frozen;
77 }
78
79 EAPI void
80 e_layout_virtual_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
81 {
82    E_Smart_Data *sd;
83
84    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
85    sd = evas_object_smart_data_get(obj);
86    if (w < 1) w = 1;
87    if (h < 1) h = 1;
88    if ((sd->vw == w) && (sd->vh == h)) return;
89    sd->vw = w;
90    sd->vh = h;
91    sd->changed = 1;
92    if (sd->frozen <= 0) _e_layout_smart_reconfigure(sd);
93 }
94
95 EAPI void
96 e_layout_virtual_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
97 {
98    E_Smart_Data *sd;
99
100    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
101    sd = evas_object_smart_data_get(obj);
102    if (w) *w = sd->vw;
103    if (h) *h = sd->vh;
104 }
105
106 EAPI void
107 e_layout_coord_canvas_to_virtual(Evas_Object *obj, Evas_Coord cx, Evas_Coord cy, Evas_Coord *vx, Evas_Coord *vy)
108 {
109    E_Smart_Data *sd;
110
111    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
112    sd = evas_object_smart_data_get(obj);
113
114    if (vx) *vx = (cx - sd->x) * ((double)(sd->vw) / sd->w);
115    if (vy) *vy = (cy - sd->y) * ((double)(sd->vh) / sd->h);
116 }
117
118 EAPI void
119 e_layout_coord_virtual_to_canvas(Evas_Object *obj, Evas_Coord vx, Evas_Coord vy, Evas_Coord *cx, Evas_Coord *cy)
120 {
121    E_Smart_Data *sd;
122
123    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
124    sd = evas_object_smart_data_get(obj);
125
126    if (cx) *cx = vx * ((double)(sd->w) / sd->vw) + sd->x;
127    if (cy) *cy = vy * ((double)(sd->h) / sd->vh) + sd->y;
128 }
129
130 EAPI void
131 e_layout_pack(Evas_Object *obj, Evas_Object *child)
132 {
133    E_Smart_Data *sd;
134    E_Layout_Item *li;
135
136    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
137    sd = evas_object_smart_data_get(obj);
138    _e_layout_smart_adopt(sd, child);
139    sd->items = eina_list_append(sd->items, child);
140    li = evas_object_data_get(child, "e_layout_data");
141    _e_layout_smart_move_resize_item(li);
142 }
143
144 EAPI void
145 e_layout_child_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
146 {
147    E_Layout_Item *li;
148
149    li = evas_object_data_get(obj, "e_layout_data");
150    if (!li) return;
151    if ((li->x == x) && (li->y == y)) return;
152    li->x = x;
153    li->y = y;
154    _e_layout_smart_move_resize_item(li);
155 }
156
157 EAPI void
158 e_layout_child_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
159 {
160    E_Layout_Item *li;
161
162    li = evas_object_data_get(obj, "e_layout_data");
163    if (!li) return;
164    if (w < 0) w = 0;
165    if (h < 0) h = 0;
166    if ((li->w == w) && (li->h == h)) return;
167    li->w = w;
168    li->h = h;
169    _e_layout_smart_move_resize_item(li);
170 }
171
172 EAPI void
173 e_layout_child_lower(Evas_Object *obj)
174 {
175    E_Layout_Item *li;
176
177    li = evas_object_data_get(obj, "e_layout_data");
178    if (!li) return;
179    if (!eina_list_data_find(li->sd->items, obj)) return;
180    if ((li->sd->items) && eina_list_next(li->sd->items))
181      {
182         li->sd->items = eina_list_remove(li->sd->items, obj);
183         evas_object_lower(obj);
184         li->sd->items = eina_list_prepend(li->sd->items, obj);
185      }
186 }
187
188 EAPI void
189 e_layout_child_raise(Evas_Object *obj)
190 {
191    E_Layout_Item *li;
192
193    li = evas_object_data_get(obj, "e_layout_data");
194    if (!li) return;
195    if (!eina_list_data_find(li->sd->items, obj)) return;
196    if ((li->sd->items) && eina_list_next(li->sd->items))
197      {
198         li->sd->items = eina_list_remove(li->sd->items, obj);
199         evas_object_raise(obj);
200         li->sd->items = eina_list_append(li->sd->items, obj);
201      }
202 }
203
204 EAPI void
205 e_layout_child_lower_below(Evas_Object *obj, Evas_Object *below)
206 {
207    E_Layout_Item *li;
208
209    li = evas_object_data_get(obj, "e_layout_data");
210    if (!li) return;
211    if (!eina_list_data_find(li->sd->items, below)) return;
212    if (!eina_list_data_find(li->sd->items, obj)) return;
213    if ((li->sd->items) && eina_list_next(li->sd->items))
214      {
215         li->sd->items = eina_list_remove(li->sd->items, obj);
216         evas_object_stack_below(obj, below);
217         li->sd->items = eina_list_prepend_relative(li->sd->items, obj, below);
218      }
219 }
220
221 EAPI void
222 e_layout_child_raise_above(Evas_Object *obj, Evas_Object *above)
223 {
224    E_Layout_Item *li;
225
226    li = evas_object_data_get(obj, "e_layout_data");
227    if (!li) return;
228    if (!eina_list_data_find(li->sd->items, above)) return;
229    if (!eina_list_data_find(li->sd->items, obj)) return;
230    if ((li->sd->items) && eina_list_next(li->sd->items))
231      {
232         li->sd->items = eina_list_remove(li->sd->items, obj);
233         evas_object_stack_above(obj, above);
234         li->sd->items = eina_list_append_relative(li->sd->items, obj, above);
235      }
236 }
237
238 EAPI void
239 e_layout_child_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
240 {
241    E_Layout_Item *li;
242
243    li = evas_object_data_get(obj, "e_layout_data");
244    if (!li) return;
245
246    if (x) *x = li->x;
247    if (y) *y = li->y;
248    if (w) *w = li->w;
249    if (h) *h = li->h;
250 }
251
252 EAPI void
253 e_layout_unpack(Evas_Object *obj)
254 {
255    E_Layout_Item *li;
256    E_Smart_Data *sd;
257
258    li = evas_object_data_get(obj, "e_layout_data");
259    if (!li) return;
260    sd = li->sd;
261    sd->items = eina_list_remove(sd->items, obj);
262    _e_layout_smart_disown(obj);
263 }
264
265 /* local subsystem functions */
266 static E_Layout_Item *
267 _e_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj)
268 {
269    E_Layout_Item *li;
270
271    li = evas_object_data_get(obj, "e_layout_data");
272    if (li) e_layout_unpack(obj);
273    li = calloc(1, sizeof(E_Layout_Item));
274    if (!li) return NULL;
275    li->sd = sd;
276    li->obj = obj;
277    /* defaults */
278    li->x = 0;
279    li->y = 0;
280    li->w = 0;
281    li->h = 0;
282    evas_object_clip_set(obj, sd->clip);
283    evas_object_smart_member_add(obj, li->sd->obj);
284    evas_object_data_set(obj, "e_layout_data", li);
285    evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
286                                   _e_layout_smart_item_del_hook, NULL);
287    if ((!evas_object_visible_get(sd->clip)) &&
288        (evas_object_visible_get(sd->obj)))
289      evas_object_show(sd->clip);
290    return li;
291 }
292
293 static void
294 _e_layout_smart_disown(Evas_Object *obj)
295 {
296    E_Layout_Item *li;
297
298    li = evas_object_data_get(obj, "e_layout_data");
299    if (!li) return;
300    if (!li->sd->items)
301      {
302         if (evas_object_visible_get(li->sd->clip))
303           evas_object_hide(li->sd->clip);
304      }
305    evas_object_event_callback_del(obj,
306                                   EVAS_CALLBACK_FREE,
307                                   _e_layout_smart_item_del_hook);
308    evas_object_smart_member_del(obj);
309    evas_object_data_del(obj, "e_layout_data");
310    free(li);
311 }
312
313 static void
314 _e_layout_smart_item_del_hook(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
315 {
316    e_layout_unpack(obj);
317 }
318
319 static void
320 _e_layout_smart_reconfigure(E_Smart_Data *sd)
321 {
322    Eina_List *l;
323    Evas_Object *obj;
324
325    if (!sd->changed) return;
326
327    EINA_LIST_FOREACH(sd->items, l, obj)
328      {
329         E_Layout_Item *li;
330         li = evas_object_data_get(obj, "e_layout_data");
331         _e_layout_smart_move_resize_item(li);
332      }
333    sd->changed = 0;
334 }
335
336 static void
337 _e_layout_smart_move_resize_item(E_Layout_Item *li)
338 {
339    evas_object_move(li->obj,
340                     li->sd->x + ((li->x * li->sd->w) / li->sd->vw),
341                     li->sd->y + ((li->y * li->sd->h) / li->sd->vh));
342    evas_object_resize(li->obj,
343                       (li->w * li->sd->w) / li->sd->vw,
344                       (li->h * li->sd->h) / li->sd->vh);
345 }
346
347 static void
348 _e_layout_smart_init(void)
349 {
350    if (_e_smart) return;
351      {
352         static const Evas_Smart_Class sc =
353           {
354              "e_layout",
355                EVAS_SMART_CLASS_VERSION,
356                _e_layout_smart_add,
357                _e_layout_smart_del,
358                _e_layout_smart_move,
359                _e_layout_smart_resize,
360                _e_layout_smart_show,
361                _e_layout_smart_hide,
362                _e_layout_smart_color_set,
363                _e_layout_smart_clip_set,
364                _e_layout_smart_clip_unset,
365                NULL,
366                NULL,
367                NULL,
368                NULL,
369                NULL,
370                NULL,
371                NULL
372           };
373         _e_smart = evas_smart_class_new(&sc);
374      }
375 }
376
377 static void
378 _e_layout_smart_add(Evas_Object *obj)
379 {
380    E_Smart_Data *sd;
381
382    sd = calloc(1, sizeof(E_Smart_Data));
383    if (!sd) return;
384    sd->obj = obj;
385    sd->x = 0;
386    sd->y = 0;
387    sd->w = 0;
388    sd->h = 0;
389    sd->vw = 1;
390    sd->vh = 1;
391    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
392    evas_object_smart_member_add(sd->clip, obj);
393    evas_object_move(sd->clip, -100001, -100001);
394    evas_object_resize(sd->clip, 200002, 200002);
395    evas_object_color_set(sd->clip, 255, 255, 255, 255);
396    evas_object_smart_data_set(obj, sd);
397 }
398
399 static void
400 _e_layout_smart_del(Evas_Object *obj)
401 {
402    E_Smart_Data *sd;
403
404    sd = evas_object_smart_data_get(obj);
405    if (!sd) return;
406    while (sd->items)
407      {
408         Evas_Object *child;
409
410         child = eina_list_data_get(sd->items);
411         e_layout_unpack(child);
412      }
413    evas_object_del(sd->clip);
414    free(sd);
415 }
416
417 static void
418 _e_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
419 {
420    E_Smart_Data *sd;
421    Evas_Object *item;
422
423    sd = evas_object_smart_data_get(obj);
424    if (!sd) return;
425    if ((x == sd->x) && (y == sd->y)) return;
426      {
427         Eina_List *l;
428         Evas_Coord dx, dy;
429
430         dx = x - sd->x;
431         dy = y - sd->y;
432         EINA_LIST_FOREACH(sd->items, l, item)
433           {
434              Evas_Coord ox, oy;
435
436              evas_object_geometry_get(item, &ox, &oy, NULL, NULL);
437              evas_object_move(item, ox + dx, oy + dy);
438           }
439      }
440    sd->x = x;
441    sd->y = y;
442 }
443
444 static void
445 _e_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
446 {
447    E_Smart_Data *sd;
448
449    sd = evas_object_smart_data_get(obj);
450    if (!sd) return;
451    if ((w == sd->w) && (h == sd->h)) return;
452    sd->w = w;
453    sd->h = h;
454    sd->changed = 1;
455    _e_layout_smart_reconfigure(sd);
456 }
457
458 static void
459 _e_layout_smart_show(Evas_Object *obj)
460 {
461    E_Smart_Data *sd;
462
463    sd = evas_object_smart_data_get(obj);
464    if (!sd) return;
465    if (sd->items) evas_object_show(sd->clip);
466 }
467
468 static void
469 _e_layout_smart_hide(Evas_Object *obj)
470 {
471    E_Smart_Data *sd;
472
473    sd = evas_object_smart_data_get(obj);
474    if (!sd) return;
475    evas_object_hide(sd->clip);
476 }
477
478 static void
479 _e_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
480 {
481    E_Smart_Data *sd;
482
483    sd = evas_object_smart_data_get(obj);
484    if (!sd) return;
485    evas_object_color_set(sd->clip, r, g, b, a);
486 }
487
488 static void
489 _e_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
490 {
491    E_Smart_Data *sd;
492
493    sd = evas_object_smart_data_get(obj);
494    if (!sd) return;
495    evas_object_clip_set(sd->clip, clip);
496 }
497
498 static void
499 _e_layout_smart_clip_unset(Evas_Object *obj)
500 {
501    E_Smart_Data *sd;
502
503    sd = evas_object_smart_data_get(obj);
504    if (!sd) return;
505    evas_object_clip_unset(sd->clip);
506 }