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