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