Edje calc: Fix textblock size calculation logic
authorYoungbok Shin <youngb.shin@samsung.com>
Thu, 1 Sep 2016 11:45:36 +0000 (20:45 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Thu, 17 Nov 2016 07:54:18 +0000 (16:54 +0900)
Summary:
In singleline textblock, using "text.min: 1 0" and min, max width,
Edje allows to use expandable text with ellipsis. It shows ellipsis
when only text's width reach the max width.
But, Edje couldn't support same feature on multiline textblock.
Edje dose not use max height or text.max properly if ellipsis is enabled.
This feature is very useful to make a layout with dynamically aligned text.
@fix

Reviewers: cedric, tasn, woohyun, raster, herdsman

Subscribers: z-wony, eagleeye, jpeg

Differential Revision: https://phab.enlightenment.org/D3595

Change-Id: I0b63ffe07c01c0b6a5fec1df712c99d5dba709e4

src/lib/edje/edje_calc.c
src/lib/edje/edje_util.c

index bfa31a2..0d24a0c 100644 (file)
@@ -1477,6 +1477,8 @@ _edje_part_recalc_single_textblock(FLOAT_T sc,
                                    int *minw, int *minh,
                                    int *maxw, int *maxh)
 {
+   int min_calc_w = 0, min_calc_h = 0;
+
    if ((ep->type != EDJE_RP_TYPE_TEXT) ||
        (!ep->typedata.text))
      return;
@@ -1490,6 +1492,11 @@ _edje_part_recalc_single_textblock(FLOAT_T sc,
    if (!ep->typedata.text->text_enabled) ep->typedata.text->text_enabled = EINA_TRUE;
    //
 
+   /* min_calc_* values need to save calculated minumum size
+    * for maximum size calculation */
+   if (minw) min_calc_w = *minw;
+   if (minh) min_calc_h = *minh;
+
    if (chosen_desc)
      {
         Evas_Coord tw, th, ins_l, ins_r, ins_t, ins_b;
@@ -1665,57 +1672,287 @@ _edje_part_recalc_single_textblock(FLOAT_T sc,
                }
              if ((chosen_desc->text.min_x) || (chosen_desc->text.min_y))
                {
-                  int mw = 0, mh = 0;
+                  evas_object_textblock_style_insets_get(ep->object, &ins_l,
+                                                         &ins_r, &ins_t, &ins_b);
 
                   tw = th = 0;
                   if (!chosen_desc->text.min_x)
                     {
-                       eo_do(ep->object,
-                             efl_gfx_size_set(TO_INT(params->eval.w), TO_INT(params->eval.h)),
-                             evas_obj_textblock_size_formatted_get(&tw, &th));
+                       /* text.min: 0 1
+                        * text.max: X X */
+                       int temp_h = TO_INT(params->eval.h);
+                       int temp_w = TO_INT(params->eval.w);
+
+                       if (min_calc_w > temp_w)
+                         temp_w = min_calc_w;
+                       if ((!chosen_desc->text.max_x) &&
+                           maxw && (*maxw > -1) && (*maxw < temp_w))
+                         temp_w = *maxw;
+
+                       if (chosen_desc->text.max_y)
+                         {
+                            /* text.min: 0 1
+                             * text.max: X 1 */
+                            temp_h = INT_MAX / 10000;
+                         }
+                       else if (maxh && (*maxh > TO_INT(params->eval.h)))
+                         {
+                            /* text.min: 0 1
+                             * text.max: X 0
+                             * And there is a limit for height. */
+                            temp_h = *maxh;
+                         }
+
+                       /* If base width for calculation is 0,
+                        * don't get meaningless height for multiline */
+                       if (temp_w > 0)
+                         {
+                            eo_do(ep->object,
+                                  efl_gfx_size_set(temp_w, temp_h),
+                                  evas_obj_textblock_size_formatted_get(&tw, &th));
+
+                            tw += ins_l + ins_r;
+                            th += ins_t + ins_b;
+                         }
+                       else
+                         {
+                            eo_do(ep->object, evas_obj_textblock_size_native_get(NULL, &th));
+
+                            th += ins_t + ins_b;
+                         }
                     }
                   else
-                    evas_object_textblock_size_native_get(ep->object, &tw, &th);
-                  evas_object_textblock_style_insets_get(ep->object, &ins_l,
-                                                         &ins_r, &ins_t, &ins_b);
-                  mw = ins_l + tw + ins_r;
-                  mh = ins_t + th + ins_b;
-                  if (minw && chosen_desc->text.min_x)
                     {
-                       if (mw > *minw) *minw = mw;
+                       /* text.min: 1 X
+                        * text.max: X X */
+                       if (chosen_desc->text.min_y && (!chosen_desc->text.max_x) &&
+                           maxw && (*maxw > -1))
+                         {
+                            /* text.min: 1 1
+                             * text.max: 0 X */
+                            int temp_w, temp_h;
+
+                            temp_w = *maxw;
+                            temp_h = INT_MAX / 10000;
+
+                            if (min_calc_w > temp_w)
+                              temp_w = min_calc_w;
+
+                            if ((!chosen_desc->text.max_y) && maxh && (*maxh > -1))
+                              {
+                                 /* text.min: 1 1
+                                  * text.max: 0 0
+                                  * There is limit for height. */
+                                 temp_h = *maxh;
+                              }
+
+                            /* If base width for calculation is 0,
+                             * don't get meaningless height for multiline */
+                            if (temp_w > 0)
+                              {
+                                 eo_do(ep->object,
+                                       efl_gfx_size_set(temp_w, temp_h),
+                                       evas_obj_textblock_size_formatted_get(&tw, &th));
+
+                                 tw += ins_l + ins_r;
+                                 th += ins_t + ins_b;
+                              }
+                            else
+                              {
+                                 eo_do(ep->object, evas_obj_textblock_size_native_get(NULL, &th));
+
+                                 th += ins_t + ins_b;
+                              }
+                         }
+                       else
+                         {
+                            /* text.min: 1 X
+                             * text.max: 1 X
+                             * Or,
+                             * text.min: 1 X
+                             * text.max: 0 X without max width.
+                             * It is a singleline Textblock. */
+                            eo_do(ep->object, evas_obj_textblock_size_native_get(&tw, &th));
+
+                            tw += ins_l + ins_r;
+                            th += ins_t + ins_b;
+
+                            if (!chosen_desc->text.max_x &&
+                                (maxw && (*maxw > -1) && (*maxw < tw)))
+                              {
+                                 /* text.min: 1 0
+                                  * text.max: 0 X */
+                                 tw = *maxw;
+                              }
+                         }
+                    }
+
+                  if (chosen_desc->text.min_x)
+                    {
+                       if (tw > min_calc_w) min_calc_w = tw;
                     }
-                  if (minh && chosen_desc->text.min_y)
+                  if (chosen_desc->text.min_y)
                     {
-                       if (mh > *minh) *minh = mh;
+                       if (th > min_calc_h) min_calc_h = th;
                     }
+
+                  if (minw) *minw = min_calc_w;
+                  if (minh) *minh = min_calc_h;
                }
           }
 
         if ((chosen_desc->text.max_x) || (chosen_desc->text.max_y))
           {
-             int mw = 0, mh = 0;
+             evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r,
+                                                    &ins_t, &ins_b);
 
              tw = th = 0;
              if (!chosen_desc->text.max_x)
                {
-                  eo_do(ep->object,
-                        efl_gfx_size_set(TO_INT(params->eval.w), TO_INT(params->eval.h)),
-                        evas_obj_textblock_size_formatted_get(&tw, &th));
+                  /* text.min: X X
+                   * text.max: 0 1 */
+                  int temp_w, temp_h;
+
+                  if (chosen_desc->text.min_y)
+                    {
+                       /* text.min: X 1
+                        * text.max: 0 1
+                        * Already calculated in text for height. */
+                       tw = TO_INT(params->eval.w);
+                       if (min_calc_w > tw)
+                         tw = min_calc_w;
+
+                       th = min_calc_h;
+                    }
+                  else
+                    {
+                       /* text.min: X 0
+                        * text.max: 0 1 */
+                       temp_w = TO_INT(params->eval.w);
+                       temp_h = TO_INT(params->eval.h);
+
+                       if (min_calc_w > temp_w)
+                         temp_w = min_calc_w;
+                       if (maxw && (*maxw > -1) && (*maxw < temp_w))
+                         temp_w = *maxw;
+                       if (min_calc_h > temp_h)
+                         temp_h = min_calc_h;
+
+                       /* If base width for calculation is 0,
+                        * don't get meaningless height for multiline */
+                       if (temp_w > 0)
+                         {
+                            eo_do(ep->object,
+                                  efl_gfx_size_set(temp_w, temp_h),
+                                  evas_obj_textblock_size_formatted_get(&tw, &th));
+
+                            tw += ins_l + ins_r;
+                            th += ins_t + ins_b;
+                         }
+                       else
+                         {
+                            eo_do(ep->object, evas_obj_textblock_size_native_get(NULL, &th));
+
+                            th += ins_t + ins_b;
+                         }
+                    }
                }
              else
-               evas_object_textblock_size_native_get(ep->object, &tw, &th);
-             evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r,
-                                                    &ins_t, &ins_b);
-             mw = ins_l + tw + ins_r;
-             mh = ins_t + th + ins_b;
+               {
+                  /* text.max: 1 X */
+                  if (chosen_desc->text.min_x)
+                    {
+                       /* text.min: 1 X
+                        * text.max: 1 X
+                        * Singleline. */
+                       eo_do(ep->object, evas_obj_textblock_size_native_get(&tw, &th));
+
+                       tw += ins_l + ins_r;
+                       th += ins_t + ins_b;
+                    }
+                  else
+                    {
+                       /* text.min: 0 X
+                        * text.max: 1 X */
+                       if (chosen_desc->text.max_y)
+                         {
+                            /* text.min: 0 X
+                             * text.max: 1 1 */
+                            int temp_w, temp_h;
+
+                            temp_w = TO_INT(params->eval.w);
+                            temp_h = TO_INT(params->eval.h);
+
+                            if (min_calc_w > temp_w)
+                              temp_w = min_calc_w;
+                            if (min_calc_h > temp_h)
+                              temp_h = min_calc_h;
+
+                            if (chosen_desc->text.min_y)
+                              {
+                                 /* text.min: 0 1
+                                  * text.max: 1 1
+                                  * There is no need to calculate it again. */
+                                 tw = temp_w;
+                                 th = min_calc_h;
+                              }
+                            else
+                              {
+                                 /* text.min: 0 0
+                                  * text.max: 1 1 */
+
+                                 /* If base width for calculation is 0,
+                                  * don't get meaningless height for multiline */
+                                 if (temp_w > 0)
+                                   {
+                                      eo_do(ep->object,
+                                            efl_gfx_size_set(temp_w, temp_h),
+                                            evas_obj_textblock_size_formatted_get(&tw, &th));
+
+                                      tw += ins_l + ins_r;
+                                      th += ins_t + ins_b;
+                                   }
+                                 else
+                                   {
+                                      eo_do(ep->object, evas_obj_textblock_size_native_get(&tw, &th));
+
+                                      th += ins_t + ins_b;
+                                   }
+                              }
+                         }
+                       else
+                         {
+                            /* text.min: 0 X
+                             * text.max: 1 0 */
+                            int temp_w, temp_h;
+
+                            temp_w = TO_INT(params->eval.w);
+                            if (min_calc_w > temp_w)
+                              temp_w = min_calc_w;
+
+                            /* If base width for calculation is 0,
+                             * don't get meaningless height for multiline */
+                            if (temp_w > 0)
+                              {
+                                 eo_do(ep->object,
+                                       efl_gfx_size_get(NULL, &temp_h),
+                                       efl_gfx_size_set(temp_w, temp_h),
+                                       evas_obj_textblock_size_formatted_get(&tw, &th));
+
+                                 tw += ins_l + ins_r;
+                                 th += ins_t + ins_b;
+                              }
+                         }
+                    }
+               }
              if (maxw && chosen_desc->text.max_x)
                {
-                  if (mw > *maxw) *maxw = mw;
+                  if (tw > *maxw) *maxw = tw;
                   if (minw && (*maxw < *minw)) *maxw = *minw;
                }
              if (maxh && chosen_desc->text.max_y)
                {
-                  if (mh > *maxh) *maxh = mh;
+                  if (th > *maxh) *maxh = th;
                   if (minh && (*maxh < *minh)) *maxh = *minh;
                }
           }
index b4c848d..7fda1ba 100644 (file)
@@ -4038,7 +4038,6 @@ _edje_object_size_min_restricted_calc(Eo *obj EINA_UNUSED, Edje *ed, Evas_Coord
    Eina_Bool repeat_w, repeat_h;
    Eina_Bool reset_max = EINA_TRUE;
    Edje_Real_Part *pep = NULL;
-   Eina_Bool has_fixed_tb;
 
    if ((!ed) || (!ed->collection))
      {
@@ -4082,13 +4081,11 @@ again:
           }
 
         pep = NULL;
-        has_fixed_tb = EINA_TRUE;
 
         //for parts
         for (i = 0; i < ed->table_parts_size; i++)
           {
              Edje_Real_Part *ep = ed->table_parts[i];
-             Evas_Coord ins_l, ins_r;
 
              if (!ep->chosen_description) continue;
 
@@ -4096,49 +4093,21 @@ again:
              int over_w = (ep->w - ep->req.w);
              int over_h = (ep->h - ep->req.h);
 
-             Eina_Bool skip_h = EINA_FALSE;
-
              //width
-             if (!ep->chosen_description->fixed.w)
+             if ((!ep->chosen_description->fixed.w) &&
+                 (over_w > max_over_w))
                {
-                  //We care textblock width size specially.
-                  if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
-                    {
-                       Evas_Coord tb_mw;
-                       evas_object_textblock_size_formatted_get(ep->object,
-                                                                &tb_mw, NULL);
-                       evas_object_textblock_style_insets_get(ep->object, &ins_l, &ins_r, NULL, NULL);
-                       tb_mw = ins_l + tb_mw + ins_r;
-                       tb_mw -= ep->req.w;
-                       if (tb_mw > over_w) over_w = tb_mw;
-                       has_fixed_tb = EINA_FALSE;
-                    }
-
-                  if (over_w > max_over_w)
-                    {
-                       max_over_w = over_w;
-                       repeat_w = EINA_TRUE;
-                       pep = ep;
-                       skip_h = EINA_TRUE;
-                    }
+                  max_over_w = over_w;
+                  repeat_w = EINA_TRUE;
+                  pep = ep;
                }
              //height
-             if (!ep->chosen_description->fixed.h)
+             if ((!ep->chosen_description->fixed.h) &&
+                 (over_h > max_over_h))
                {
-                  if ((ep->part->type != EDJE_PART_TYPE_TEXTBLOCK) ||
-                      ((Edje_Part_Description_Text *)ep->chosen_description)->text.min_x ||
-                      !skip_h)
-                    {
-                       if (over_h > max_over_h)
-                         {
-                            max_over_h = over_h;
-                            repeat_h = EINA_TRUE;
-                            pep = ep;
-                         }
-                    }
-
-                  if (ep->part->type == EDJE_PART_TYPE_TEXTBLOCK)
-                    has_fixed_tb = EINA_FALSE;
+                  max_over_h = over_h;
+                  repeat_h = EINA_TRUE;
+                  pep = ep;
                }
           }
         if (repeat_w)
@@ -4163,18 +4132,15 @@ again:
             ((ed->w > MIN_LIMIT) || (ed->h > MIN_LIMIT)))
         /* END */
           {
-             /* Only print it if we have a non-fixed textblock.
-              * We should possibly avoid all of this if in this case, but in
+             /* We should possibly avoid all of this if in this case, but in
               * the meanwhile, just doing this. */
-             if (!has_fixed_tb)
-               {
-                  if (pep)
-                    ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
-                        ed->path, ed->group, pep->part->name);
-                  else
-                    ERR("file %s, group %s runs infinite minimum calculation loops.Continuing discarding faulty parts.",
-                        ed->path, ed->group);
-               }
+             if (pep)
+               ERR("file %s, group %s has a non-fixed part '%s'. Adding 'fixed: 1 1;' to source EDC may help. Continuing discarding faulty part.",
+                   ed->path, ed->group, pep->part->name);
+             else
+               ERR("file %s, group %s overflowed %dx%d with minimum size of %dx%d. Continuing discarding faulty parts.",
+                   ed->path, ed->group, MIN_LIMIT, MIN_LIMIT,
+                   ed->w, ed->h);
 
              reset_max = EINA_FALSE;
              goto again;