Tizen 2.1 release
[platform/core/uifw/e17.git] / src / bin / e_flowlayout.c
1 #include "e.h"
2
3 typedef struct _E_Smart_Data      E_Smart_Data;
4 typedef struct _E_Flowlayout_Item E_Flowlayout_Item;
5
6 struct _E_Smart_Data
7 {
8    Evas_Coord    x, y, w, h;
9    Evas_Object  *obj;
10    Evas_Object  *clip;
11    int           frozen;
12    unsigned char changed : 1;
13    unsigned char horizontal : 1;
14    unsigned char homogenous : 1;
15    unsigned char fill : 1;
16    unsigned char flowright : 1;
17    unsigned char flowbottom : 1;
18    Eina_List    *items;
19    struct
20    {
21       Evas_Coord w, h;
22    } min, max;
23    struct
24    {
25       double x, y;
26    } align;
27    int           rows;
28    int           cols;
29 };
30
31 struct _E_Flowlayout_Item
32 {
33    E_Smart_Data *sd;
34    unsigned char fill_w : 1;
35    unsigned char fill_h : 1;
36    unsigned char expand_w : 1;
37    unsigned char expand_h : 1;
38    struct
39    {
40       Evas_Coord w, h;
41    } min, max;
42    struct
43    {
44       double x, y;
45    } align;
46    Evas_Object  *obj;
47 };
48
49 /* local subsystem functions */
50 static E_Flowlayout_Item *_e_flowlayout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj);
51 static void               _e_flowlayout_smart_disown(Evas_Object *obj);
52 static void               _e_flowlayout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
53 static void               _e_flowlayout_smart_reconfigure(E_Smart_Data *sd);
54 static void               _e_flowlayout_smart_extents_calcuate(E_Smart_Data *sd);
55
56 static void               _e_flowlayout_smart_init(void);
57 static void               _e_flowlayout_smart_add(Evas_Object *obj);
58 static void               _e_flowlayout_smart_del(Evas_Object *obj);
59 static void               _e_flowlayout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
60 static void               _e_flowlayout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
61 static void               _e_flowlayout_smart_show(Evas_Object *obj);
62 static void               _e_flowlayout_smart_hide(Evas_Object *obj);
63 static void               _e_flowlayout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
64 static void               _e_flowlayout_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
65 static void               _e_flowlayout_smart_clip_unset(Evas_Object *obj);
66
67 /* local subsystem globals */
68 static Evas_Smart *_e_smart = NULL;
69
70 /* externally accessible functions */
71 EAPI Evas_Object *
72 e_flowlayout_add(Evas *evas)
73 {
74    _e_flowlayout_smart_init();
75    return evas_object_smart_add(evas, _e_smart);
76 }
77
78 EAPI int
79 e_flowlayout_freeze(Evas_Object *obj)
80 {
81    E_Smart_Data *sd;
82
83    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
84    sd = evas_object_smart_data_get(obj);
85    if (!sd) return 0;
86    sd->frozen++;
87    return sd->frozen;
88 }
89
90 EAPI int
91 e_flowlayout_thaw(Evas_Object *obj)
92 {
93    E_Smart_Data *sd;
94
95    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
96    sd = evas_object_smart_data_get(obj);
97    if (!sd) return 0;
98    sd->frozen--;
99    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
100    return sd->frozen;
101 }
102
103 EAPI void
104 e_flowlayout_orientation_set(Evas_Object *obj, int horizontal)
105 {
106    E_Smart_Data *sd;
107
108    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
109    sd = evas_object_smart_data_get(obj);
110    if (!sd) return;
111    if (((sd->horizontal) && (horizontal)) ||
112        ((!sd->horizontal) && (!horizontal))) return;
113    sd->horizontal = horizontal;
114    sd->changed = 1;
115    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
116 }
117
118 EAPI int
119 e_flowlayout_orientation_get(Evas_Object *obj)
120 {
121    E_Smart_Data *sd;
122
123    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
124    sd = evas_object_smart_data_get(obj);
125    if (!sd) return 0;
126    return sd->horizontal;
127 }
128
129 EAPI void
130 e_flowlayout_flowdirection_set(Evas_Object *obj, int right, int bottom)
131 {
132    E_Smart_Data *sd;
133
134    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
135    sd = evas_object_smart_data_get(obj);
136    if (!sd) return;
137    if ((((sd->flowbottom) && (bottom)) ||
138         ((!sd->flowbottom) && (!bottom))) &&
139        (((sd->flowright) && (right)) ||
140         ((!sd->flowright) && (!right)))) return;
141    sd->flowright = right;
142    sd->flowbottom = bottom;
143    sd->changed = 1;
144    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
145 }
146
147 EAPI void
148 e_flowlayout_flowdirection_get(Evas_Object *obj, int *right, int *bottom)
149 {
150    E_Smart_Data *sd;
151
152    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
153    sd = evas_object_smart_data_get(obj);
154    if (!sd) return;
155    if (right) *right = sd->flowright;
156    if (bottom) *bottom = sd->flowright;
157 }
158
159 EAPI void
160 e_flowlayout_homogenous_set(Evas_Object *obj, int homogenous)
161 {
162    E_Smart_Data *sd;
163
164    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
165    sd = evas_object_smart_data_get(obj);
166    if (!sd) return;
167    if (sd->homogenous == homogenous) return;
168    sd->homogenous = homogenous;
169    sd->changed = 1;
170    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
171 }
172
173 EAPI int
174 e_flowlayout_homogenous_get(Evas_Object *obj)
175 {
176    E_Smart_Data *sd;
177
178    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
179    sd = evas_object_smart_data_get(obj);
180    if (!sd) return 0;
181    return sd->homogenous;
182 }
183
184 EAPI void
185 e_flowlayout_fill_set(Evas_Object *obj, int fill)
186 {
187    E_Smart_Data *sd;
188
189    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
190    sd = evas_object_smart_data_get(obj);
191    if (!sd) return;
192    if (sd->fill == fill) return;
193    sd->fill = fill;
194    sd->changed = 1;
195    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
196 }
197
198 EAPI int
199 e_flowlayout_fill_get(Evas_Object *obj)
200 {
201    E_Smart_Data *sd;
202
203    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
204    sd = evas_object_smart_data_get(obj);
205    if (!sd) return 0;
206    return sd->fill;
207 }
208
209 EAPI int
210 e_flowlayout_pack_start(Evas_Object *obj, Evas_Object *child)
211 {
212    E_Smart_Data *sd;
213
214    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
215    sd = evas_object_smart_data_get(obj);
216    if (!sd) return 0;
217    _e_flowlayout_smart_adopt(sd, child);
218    sd->items = eina_list_prepend(sd->items, child);
219    sd->changed = 1;
220    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
221    return 0;
222 }
223
224 EAPI int
225 e_flowlayout_pack_end(Evas_Object *obj, Evas_Object *child)
226 {
227    E_Smart_Data *sd;
228
229    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
230    sd = evas_object_smart_data_get(obj);
231    if (!sd) return 0;
232    _e_flowlayout_smart_adopt(sd, child);
233    sd->items = eina_list_append(sd->items, child);
234    sd->changed = 1;
235    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
236    return eina_list_count(sd->items) - 1;
237 }
238
239 EAPI int
240 e_flowlayout_pack_before(Evas_Object *obj, Evas_Object *child, Evas_Object *before)
241 {
242    E_Smart_Data *sd;
243    int i = 0;
244    Eina_List *l;
245    Evas_Object *item;
246
247    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
248    sd = evas_object_smart_data_get(obj);
249    if (!sd) return 0;
250    _e_flowlayout_smart_adopt(sd, child);
251    sd->items = eina_list_prepend_relative(sd->items, child, before);
252    EINA_LIST_FOREACH(sd->items, l, item)
253      {
254         if (item == child) break;
255         i++;
256      }
257    sd->changed = 1;
258    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
259    return i;
260 }
261
262 EAPI int
263 e_flowlayout_pack_after(Evas_Object *obj, Evas_Object *child, Evas_Object *after)
264 {
265    E_Smart_Data *sd;
266    int i = 0;
267    Eina_List *l;
268    Evas_Object *item;
269
270    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
271    sd = evas_object_smart_data_get(obj);
272    if (!sd) return 0;
273    _e_flowlayout_smart_adopt(sd, child);
274    sd->items = eina_list_append_relative(sd->items, child, after);
275    EINA_LIST_FOREACH(sd->items, l, item)
276      {
277         if (item == child) break;
278         i++;
279      }
280    sd->changed = 1;
281    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
282    return i;
283 }
284
285 EAPI int
286 e_flowlayout_pack_count_get(Evas_Object *obj)
287 {
288    E_Smart_Data *sd;
289
290    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
291    sd = evas_object_smart_data_get(obj);
292    if (!sd) return 0;
293    return eina_list_count(sd->items);
294 }
295
296 EAPI Evas_Object *
297 e_flowlayout_pack_object_nth(Evas_Object *obj, int n)
298 {
299    E_Smart_Data *sd;
300
301    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
302    sd = evas_object_smart_data_get(obj);
303    if (!sd) return NULL;
304    return eina_list_nth(sd->items, n);
305 }
306
307 EAPI Evas_Object *
308 e_flowlayout_pack_object_first(Evas_Object *obj)
309 {
310    E_Smart_Data *sd;
311
312    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
313    sd = evas_object_smart_data_get(obj);
314    if (!sd) return NULL;
315    return eina_list_data_get(sd->items);
316 }
317
318 EAPI Evas_Object *
319 e_flowlayout_pack_object_last(Evas_Object *obj)
320 {
321    E_Smart_Data *sd;
322
323    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
324    sd = evas_object_smart_data_get(obj);
325    if (!sd) return NULL;
326    return eina_list_data_get(eina_list_last(sd->items));
327 }
328
329 EAPI Evas_Object *
330 e_flowlayout_pack_object_prev(Evas_Object *obj, Evas_Object *child)
331 {
332    E_Smart_Data *sd;
333    Evas_Object *o;
334    Eina_List *l;
335
336    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
337    sd = evas_object_smart_data_get(obj);
338    if (!sd) return NULL;
339    EINA_LIST_FOREACH(sd->items, l, o)
340      if (o == child) return eina_list_data_get(l->prev);
341    return NULL;
342 }
343
344 EAPI Evas_Object *
345 e_flowlayout_pack_object_next(Evas_Object *obj, Evas_Object *child)
346 {
347    E_Smart_Data *sd;
348    Evas_Object *o;
349    Eina_List *l;
350
351    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(NULL);
352    sd = evas_object_smart_data_get(obj);
353    if (!sd) return NULL;
354    EINA_LIST_FOREACH(sd->items, l, o)
355      if (o == child) return eina_list_data_get(l->next);
356    return NULL;
357 }
358
359 EAPI void
360 e_flowlayout_pack_options_set(Evas_Object *obj, int fill_w, int fill_h, int expand_w, int expand_h, double align_x, double align_y, Evas_Coord min_w, Evas_Coord min_h, Evas_Coord max_w, Evas_Coord max_h)
361 {
362    E_Flowlayout_Item *bi;
363
364    bi = evas_object_data_get(obj, "e_flowlayout_data");
365    if (!bi) return;
366    bi->fill_w = fill_w;
367    bi->fill_h = fill_h;
368    bi->expand_w = expand_w;
369    bi->expand_h = expand_h;
370    bi->align.x = align_x;
371    bi->align.y = align_y;
372    bi->min.w = min_w;
373    bi->min.h = min_h;
374    bi->max.w = max_w;
375    bi->max.h = max_h;
376    bi->sd->changed = 1;
377    if (bi->sd->frozen <= 0) _e_flowlayout_smart_reconfigure(bi->sd);
378 }
379
380 EAPI void
381 e_flowlayout_unpack(Evas_Object *obj)
382 {
383    E_Flowlayout_Item *bi;
384    E_Smart_Data *sd;
385
386    bi = evas_object_data_get(obj, "e_flowlayout_data");
387    if (!bi) return;
388    sd = bi->sd;
389    if (!sd) return;
390    sd->items = eina_list_remove(sd->items, obj);
391    _e_flowlayout_smart_disown(obj);
392    sd->changed = 1;
393    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
394 }
395
396 EAPI void
397 e_flowlayout_size_min_get(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh)
398 {
399    E_Smart_Data *sd;
400
401    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
402    sd = evas_object_smart_data_get(obj);
403    if (!sd) return;
404    if (sd->changed) _e_flowlayout_smart_extents_calcuate(sd);
405    if (minw) *minw = sd->min.w;
406    if (minh) *minh = sd->min.h;
407 }
408
409 EAPI void
410 e_flowlayout_size_max_get(Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *maxh)
411 {
412    E_Smart_Data *sd;
413
414    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
415    sd = evas_object_smart_data_get(obj);
416    if (!sd) return;
417    if (sd->changed) _e_flowlayout_smart_extents_calcuate(sd);
418    if (maxw) *maxw = sd->max.w;
419    if (maxh) *maxh = sd->max.h;
420 }
421
422 EAPI int
423 e_flowlayout_max_children(Evas_Object *obj)
424 {
425    E_Smart_Data *sd;
426
427    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERR(0);
428    sd = evas_object_smart_data_get(obj);
429    if (!sd) return -1;
430    if (!sd->homogenous) return -1;
431    return sd->rows * sd->cols;
432 }
433
434 EAPI void
435 e_flowlayout_align_get(Evas_Object *obj, double *ax, double *ay)
436 {
437    E_Smart_Data *sd;
438
439    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
440    sd = evas_object_smart_data_get(obj);
441    if (!sd) return;
442    if (ax) *ax = sd->align.x;
443    if (ay) *ay = sd->align.y;
444 }
445
446 EAPI void
447 e_flowlayout_align_set(Evas_Object *obj, double ax, double ay)
448 {
449    E_Smart_Data *sd;
450
451    if (evas_object_smart_smart_get(obj) != _e_smart) SMARTERRNR();
452    sd = evas_object_smart_data_get(obj);
453    if (!sd) return;
454    if ((sd->align.x == ax) && (sd->align.y == ay)) return;
455    sd->align.x = ax;
456    sd->align.y = ay;
457    sd->changed = 1;
458    if (sd->frozen <= 0) _e_flowlayout_smart_reconfigure(sd);
459 }
460
461 /* local subsystem functions */
462 static E_Flowlayout_Item *
463 _e_flowlayout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj)
464 {
465    E_Flowlayout_Item *bi;
466
467    bi = calloc(1, sizeof(E_Flowlayout_Item));
468    if (!bi) return NULL;
469    bi->sd = sd;
470    bi->obj = obj;
471    /* defaults */
472    bi->fill_w = 0;
473    bi->fill_h = 0;
474    bi->expand_w = 0;
475    bi->expand_h = 0;
476    bi->align.x = 0.5;
477    bi->align.y = 0.5;
478    bi->min.w = 0;
479    bi->min.h = 0;
480    bi->max.w = 0;
481    bi->max.h = 0;
482    evas_object_clip_set(obj, sd->clip);
483    evas_object_smart_member_add(obj, bi->sd->obj);
484    evas_object_data_set(obj, "e_flowlayout_data", bi);
485    evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
486                                   _e_flowlayout_smart_item_del_hook, NULL);
487    if ((!evas_object_visible_get(sd->clip)) &&
488        (evas_object_visible_get(sd->obj)))
489      evas_object_show(sd->clip);
490    return bi;
491 }
492
493 static void
494 _e_flowlayout_smart_disown(Evas_Object *obj)
495 {
496    E_Flowlayout_Item *bi;
497
498    bi = evas_object_data_get(obj, "e_flowlayout_data");
499    if (!bi) return;
500    if (!bi->sd->items)
501      {
502         if (evas_object_visible_get(bi->sd->clip))
503           evas_object_hide(bi->sd->clip);
504      }
505    evas_object_event_callback_del(obj,
506                                   EVAS_CALLBACK_FREE,
507                                   _e_flowlayout_smart_item_del_hook);
508    evas_object_smart_member_del(obj);
509    evas_object_clip_unset(obj);
510    evas_object_data_del(obj, "e_flowlayout_data");
511    free(bi);
512 }
513
514 static void
515 _e_flowlayout_smart_item_del_hook(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
516 {
517    e_flowlayout_unpack(obj);
518 }
519
520 static void
521 _e_flowlayout_smart_reconfigure(E_Smart_Data *sd)
522 {
523    Evas_Coord x, y, w, h, xx, yy, cr, cc;
524    Eina_List *l;
525    Evas_Object *obj;
526    int minw, minh;
527    int count, expand;
528
529    if (!sd->changed) return;
530
531    /* local variables */
532    x = sd->x;
533    y = sd->y;
534    w = sd->w;
535    h = sd->h;
536
537    /* Calculate extents */
538    _e_flowlayout_smart_extents_calcuate(sd);
539    minw = sd->min.w;
540    minh = sd->min.h;
541    count = eina_list_count(sd->items);
542    expand = 0;
543
544    /* Too small? move a little */
545    if (w < minw)
546      {
547         x = x + ((w - minw) * (1.0 - sd->align.x));
548         w = minw;
549      }
550    if (h < minh)
551      {
552         y = y + ((h - minh) * (1.0 - sd->align.y));
553         h = minh;
554      }
555
556    /* Some odd expanding counter */
557    EINA_LIST_FOREACH(sd->items, l, obj)
558      {
559         E_Flowlayout_Item *bi;
560
561         bi = evas_object_data_get(obj, "e_flowlayout_data");
562         if (bi)
563           {
564              if (sd->horizontal)
565                {
566                   if (bi->expand_w) expand++;
567                }
568              else
569                {
570                   if (bi->expand_h) expand++;
571                }
572           }
573      }
574
575    /* If no expansion, w is minw, h is minh */
576    if (expand == 0)
577      {
578         if (sd->horizontal)
579           {
580              x += (double)(w - minw) * sd->align.x;
581              w = minw;
582           }
583         else
584           {
585              y += (double)(h - minh) * sd->align.y;
586              h = minh;
587           }
588      }
589
590    /* Some calculations */
591    if (sd->flowright)
592      xx = x;
593    else
594      xx = x + w;
595    if (sd->flowbottom)
596      yy = y;
597    else
598      yy = y + h;
599    cr = 0;
600    cc = 0;
601
602    /* Now for the real deal */
603    EINA_LIST_FOREACH(sd->items, l, obj)
604      {
605         E_Flowlayout_Item *bi;
606
607         bi = evas_object_data_get(obj, "e_flowlayout_data");
608         if (bi)
609           {
610              /* Horiziontal */
611              if (sd->horizontal)
612                {
613                   /* Homogenous */
614                   if (sd->homogenous)
615                     {
616                        Evas_Coord ww, hh, ow, oh;
617                        ww = w / sd->cols;
618                        hh = h / sd->rows;
619                        if (sd->fill)
620                          {
621                             int num = count - (cr) * (sd->cols);
622                             if (num < sd->cols)
623                               {
624                                  ww = w / num;
625                               }
626                          }
627                        ow = bi->min.w;
628                        if (bi->fill_w) ow = ww;
629                        if ((bi->max.w >= 0) && (bi->max.w < ow)) ow = bi->max.w;
630                        oh = bi->min.h;
631                        if (bi->fill_h) oh = hh;
632                        if ((bi->max.h >= 0) && (bi->max.h < oh)) oh = bi->max.h;
633                        if (sd->flowright)
634                          {
635                             if (sd->flowbottom)
636                               {
637                                  evas_object_move(obj,
638                                                   xx + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
639                                                   yy + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
640                               }
641                             else
642                               {
643                                  evas_object_move(obj,
644                                                   xx + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
645                                                   yy - hh + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
646                               }
647                             evas_object_resize(obj, ow, oh);
648                             xx += ww;
649                          }
650                        else
651                          {
652                             if (sd->flowbottom)
653                               {
654                                  evas_object_move(obj,
655                                                   xx - ww + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
656                                                   yy + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
657                               }
658                             else
659                               {
660                                  evas_object_move(obj,
661                                                   xx - ww + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
662                                                   yy - hh + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
663                               }
664                             evas_object_resize(obj, ow, oh);
665                             xx -= ww;
666                          }
667                        cc++;
668                        if (cc >= sd->cols)
669                          {
670                             cc = 0;
671                             cr++;
672                             if (sd->flowright)
673                               xx = x;
674                             else
675                               xx = x + w;
676                             if (sd->flowbottom)
677                               yy += hh;
678                             else
679                               yy -= hh;
680                          }
681                     }
682                   /* TODO Nonhomogenous Horizontal */
683                   else
684                     {
685                     }
686                }
687              /* Vertical */
688              else
689                {
690                   if (sd->homogenous)
691                     {
692                        Evas_Coord ww, hh, ow, oh;
693                        ww = w / sd->cols;
694                        hh = h / sd->rows;
695                        if (sd->fill)
696                          {
697                             int num = count - (cc) * (sd->rows);
698                             if (num < sd->rows)
699                               {
700                                  hh = h / num;
701                               }
702                          }
703                        oh = bi->min.h;
704                        if (bi->fill_h) oh = hh;
705                        if ((bi->max.h >= 0) && (bi->max.h < oh)) oh = bi->max.h;
706                        ow = bi->min.w;
707                        if (bi->fill_w) ow = ww;
708                        if ((bi->max.w >= 0) && (bi->max.w < ow)) ow = bi->max.w;
709                        if (sd->flowbottom)
710                          {
711                             if (sd->flowright)
712                               {
713                                  evas_object_move(obj,
714                                                   xx + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
715                                                   yy + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
716                               }
717                             else
718                               {
719                                  evas_object_move(obj,
720                                                   xx - ww + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
721                                                   yy + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
722                               }
723                             evas_object_resize(obj, ow, oh);
724                             yy += hh;
725                          }
726                        else
727                          {
728                             if (sd->flowright)
729                               {
730                                  evas_object_move(obj,
731                                                   xx + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
732                                                   yy - hh + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
733                               }
734                             else
735                               {
736                                  evas_object_move(obj,
737                                                   xx - ww + (Evas_Coord)(((double)(ww - ow)) * bi->align.x),
738                                                   yy - hh + (Evas_Coord)(((double)(hh - oh)) * bi->align.y));
739                               }
740                             evas_object_resize(obj, ow, oh);
741                             yy -= hh;
742                          }
743                        cr++;
744                        if (cr >= sd->rows)
745                          {
746                             cr = 0;
747                             cc++;
748                             if (sd->flowbottom)
749                               yy = y;
750                             else
751                               yy = y + h;
752                             if (sd->flowright)
753                               xx += ww;
754                             else
755                               xx -= ww;
756                          }
757                     }
758                   /* TODO Nonhomogeneous Vertical */
759                   else
760                     {
761                     }
762                }
763           }
764      }
765    sd->changed = 0;
766 }
767
768 static void
769 _e_flowlayout_smart_extents_calcuate(E_Smart_Data *sd)
770 {
771    Eina_List *l;
772    Evas_Object *obj;
773    int minw, minh, count;
774
775    /* FIXME: need to calc max */
776    sd->max.w = -1; /* max < 0 == unlimited */
777    sd->max.h = -1;
778
779    minw = 1;
780    minh = 1;
781    if (sd->homogenous)
782      {
783         EINA_LIST_FOREACH(sd->items, l, obj)
784           {
785              E_Flowlayout_Item *bi;
786
787              bi = evas_object_data_get(obj, "e_flowlayout_data");
788              if (bi)
789                {
790                   if (sd->horizontal)
791                     {
792                        if (minh < bi->min.h) minh = bi->min.h;
793                        if (minw < bi->min.w) minw = bi->min.w;
794                     }
795                   else
796                     {
797                        if (minw < bi->min.w) minw = bi->min.w;
798                        if (minh < bi->min.h) minh = bi->min.h;
799                     }
800                }
801           }
802         if (sd->horizontal)
803           {
804              sd->rows = sd->h / minh;
805              if (sd->rows < 1)
806                sd->rows = 1;
807              count = eina_list_count(sd->items);
808              sd->cols = sd->w / minw;
809              if (count < sd->cols) sd->cols = count;
810              sd->rows = 0;
811              if (sd->cols > 0)
812                {
813                   while (count > 0)
814                     {
815                        count -= sd->cols;
816                        sd->rows++;
817                     }
818                }
819           }
820         else
821           {
822              sd->cols = sd->w / minw;
823              if (sd->cols < 1)
824                sd->cols = 1;
825              count = eina_list_count(sd->items);
826              sd->rows = sd->h / minh;
827              if (count < sd->cols) sd->rows = count;
828              sd->cols = 0;
829              if (sd->rows > 0)
830                {
831                   while (count > 0)
832                     {
833                        count -= sd->rows;
834                        sd->cols++;
835                     }
836                }
837           }
838
839         minw *= sd->cols;
840         minh *= sd->rows;
841      }
842    /* TODO nonhomogenous */
843    else
844      {
845         EINA_LIST_FOREACH(sd->items, l, obj)
846           {
847              E_Flowlayout_Item *bi;
848
849              bi = evas_object_data_get(obj, "e_flowlayout_data");
850              if (bi)
851                {
852                   if (sd->horizontal)
853                     {
854                        if (minh < bi->min.h) minh = bi->min.h * sd->rows;
855                        minw += bi->min.w;
856                     }
857                   else
858                     {
859                        if (minw < bi->min.w) minw = bi->min.w * sd->cols;
860                        minh += bi->min.h;
861                     }
862                }
863           }
864         if (sd->horizontal)
865           {
866              sd->rows = sd->h / minh;
867              minh *= sd->rows;
868              sd->cols = -1;
869              minw = minw / sd->cols + 0.2 * minw;
870           }
871         else
872           {
873              sd->cols = sd->w / minw;
874              minw *= sd->cols;
875              sd->rows = -1;
876              minh = minh / sd->cols + 0.2 * minh;
877           }
878      }
879    sd->min.w = minw;
880    sd->min.h = minh;
881    if (sd->rows < 1)
882      sd->rows = 1;
883    if (sd->cols < 1)
884      sd->cols = 1;
885 }
886
887 static void
888 _e_flowlayout_smart_init(void)
889 {
890    if (_e_smart) return;
891    {
892       static const Evas_Smart_Class sc =
893       {
894          "e_flowlayout",
895          EVAS_SMART_CLASS_VERSION,
896          _e_flowlayout_smart_add,
897          _e_flowlayout_smart_del,
898          _e_flowlayout_smart_move,
899          _e_flowlayout_smart_resize,
900          _e_flowlayout_smart_show,
901          _e_flowlayout_smart_hide,
902          _e_flowlayout_smart_color_set,
903          _e_flowlayout_smart_clip_set,
904          _e_flowlayout_smart_clip_unset,
905          NULL,
906          NULL,
907          NULL,
908          NULL,
909          NULL,
910          NULL,
911          NULL
912       };
913       _e_smart = evas_smart_class_new(&sc);
914    }
915 }
916
917 static void
918 _e_flowlayout_smart_add(Evas_Object *obj)
919 {
920    E_Smart_Data *sd;
921
922    sd = calloc(1, sizeof(E_Smart_Data));
923    if (!sd) return;
924    sd->obj = obj;
925    sd->x = 0;
926    sd->y = 0;
927    sd->w = 0;
928    sd->h = 0;
929    sd->align.x = 0.5;
930    sd->align.y = 0.5;
931    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
932    evas_object_smart_member_add(sd->clip, obj);
933    evas_object_move(sd->clip, -100004, -100004);
934    evas_object_resize(sd->clip, 200008, 200008);
935    evas_object_color_set(sd->clip, 255, 255, 255, 255);
936    evas_object_smart_data_set(obj, sd);
937 }
938
939 static void
940 _e_flowlayout_smart_del(Evas_Object *obj)
941 {
942    E_Smart_Data *sd;
943
944    sd = evas_object_smart_data_get(obj);
945    if (!sd) return;
946    /* FIXME: this gets into an infinite loop when changin basic->advanced on
947     * ibar config dialog
948     */
949    while (sd->items)
950      {
951         Evas_Object *child;
952
953         child = eina_list_data_get(sd->items);
954         e_flowlayout_unpack(child);
955      }
956    evas_object_del(sd->clip);
957    free(sd);
958 }
959
960 static void
961 _e_flowlayout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
962 {
963    E_Smart_Data *sd;
964
965    sd = evas_object_smart_data_get(obj);
966    if (!sd) return;
967    if ((x == sd->x) && (y == sd->y)) return;
968    {
969       Eina_List *l;
970       Evas_Object *item;
971       Evas_Coord dx, dy;
972
973       dx = x - sd->x;
974       dy = y - sd->y;
975       EINA_LIST_FOREACH(sd->items, l, item)
976         {
977            Evas_Coord ox, oy;
978
979            evas_object_geometry_get(item, &ox, &oy, NULL, NULL);
980            evas_object_move(item, ox + dx, oy + dy);
981         }
982    }
983    sd->x = x;
984    sd->y = y;
985 }
986
987 static void
988 _e_flowlayout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
989 {
990    E_Smart_Data *sd;
991
992    sd = evas_object_smart_data_get(obj);
993    if (!sd) return;
994    if ((w == sd->w) && (h == sd->h)) return;
995    sd->w = w;
996    sd->h = h;
997    sd->changed = 1;
998    _e_flowlayout_smart_reconfigure(sd);
999 }
1000
1001 static void
1002 _e_flowlayout_smart_show(Evas_Object *obj)
1003 {
1004    E_Smart_Data *sd;
1005
1006    sd = evas_object_smart_data_get(obj);
1007    if (!sd) return;
1008    if (sd->items) evas_object_show(sd->clip);
1009 }
1010
1011 static void
1012 _e_flowlayout_smart_hide(Evas_Object *obj)
1013 {
1014    E_Smart_Data *sd;
1015
1016    sd = evas_object_smart_data_get(obj);
1017    if (!sd) return;
1018    evas_object_hide(sd->clip);
1019 }
1020
1021 static void
1022 _e_flowlayout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
1023 {
1024    E_Smart_Data *sd;
1025
1026    sd = evas_object_smart_data_get(obj);
1027    if (!sd) return;
1028    evas_object_color_set(sd->clip, r, g, b, a);
1029 }
1030
1031 static void
1032 _e_flowlayout_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
1033 {
1034    E_Smart_Data *sd;
1035
1036    sd = evas_object_smart_data_get(obj);
1037    if (!sd) return;
1038    evas_object_clip_set(sd->clip, clip);
1039 }
1040
1041 static void
1042 _e_flowlayout_smart_clip_unset(Evas_Object *obj)
1043 {
1044    E_Smart_Data *sd;
1045
1046    sd = evas_object_smart_data_get(obj);
1047    if (!sd) return;
1048    evas_object_clip_unset(sd->clip);
1049 }
1050