From: 장효영 <hyoyoung.chang@samsung.com>
author장효영 <hyoyoung.chang@samsung.com>
Fri, 16 Jul 2010 05:50:45 +0000 (05:50 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Fri, 16 Jul 2010 05:50:45 +0000 (05:50 +0000)
I've added elm_label features. That are fontsize, color, background color and
ellipsis (cutting text to fit widget size) features. Most of the property
setting API is wrapping to label tag set.

The rllipsis feature checks part size and cuts character to fit its size.

SVN revision: 50275

data/themes/default.edc
src/lib/Elementary.h.in
src/lib/elm_label.c

index 3eb8309..5a80182 100644 (file)
@@ -527,18 +527,27 @@ collections {
 
 ///////////////////////////////////////////////////////////////////////////////
    group { name: "elm/label/base/default";
-      styles
-       {
-          style { name: "textblock_style";
-             base: "font=Sans font_size=10 align=left color=#000 wrap=word";
-
-             tag:  "br" "\n";
-             tag:  "hilight" "+ font=Sans:style=Bold";
-             tag:  "b" "+ font=Sans:style=Bold";
-             tag:  "tab" "\t";
+      data.item: "default_font_size" "24";
+      data.item: "min_font_size" "8";
+      data.item: "max_font_size" "60";
+      styles {
+         style { name: "textblock_style";
+            base: "font=Sans font_size=10 align=left color=#000 wrap=word";
+            tag:  "br" "\n";
+            tag:  "hilight" "+ font=Sans:style=Bold";
+            tag:  "b" "+ font=Sans:style=Bold";
+            tag:  "tab" "\t";
           }
        }
       parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
         part { name: "elm.text";
            type: TEXTBLOCK;
            mouse_events: 0;
@@ -554,7 +563,18 @@ collections {
    }
 
    group { name: "elm/label/base_wrap/default";
+      data.item: "default_font_size" "24";
+      data.item: "min_font_size" "8";
+      data.item: "max_font_size" "60";
       parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
         part { name: "elm.text";
            type: TEXTBLOCK;
            mouse_events: 0;
@@ -570,18 +590,27 @@ collections {
    }
 
    group { name: "elm/label/base/marker";
-      styles
-       {
-          style { name: "textblock_style2";
-             base: "font=Sans:style=Bold font_size=10 align=center color=#fff wrap=word";
-
-             tag:  "br" "\n";
-             tag:  "hilight" "+ color=#ffff";
-             tag:  "b" "+ color=#ffff";
-             tag:  "tab" "\t";
-          }
-       }
+      data.item: "default_font_size" "24";
+      data.item: "min_font_size" "8";
+      data.item: "max_font_size" "60";
+      styles {
+         style { name: "textblock_style2";
+          base: "font=Sans:style=Bold font_size=10 align=center color=#fff wrap=word";
+           tag:  "br" "\n";
+          tag:  "hilight" "+ color=#ffff";
+          tag:  "b" "+ color=#ffff";
+          tag:  "tab" "\t";
+        }
+      }
       parts {
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
         part { name: "elm.text";
            type: TEXTBLOCK;
            mouse_events: 0;
@@ -597,8 +626,19 @@ collections {
    }
 
    group { name: "elm/label/base_wrap/marker";
+      data.item: "default_font_size" "24";
+      data.item: "min_font_size" "8";
+      data.item: "max_font_size" "60";
       parts {
-        part { name: "elm.text";
+         part { name: "label.swallow.background";
+            type: SWALLOW;
+            description { state: "default" 0.0;
+               visible: 1;
+               rel1 { relative: 0 0; to: "elm.text"; }
+               rel2 { relative: 1 1; to: "elm.text"; }
+            }
+         }
+         part { name: "elm.text";
            type: TEXTBLOCK;
            mouse_events: 0;
            scale: 1;
index fc60876..128f9df 100644 (file)
@@ -531,6 +531,11 @@ extern "C" {
    EAPI Eina_Bool    elm_label_line_wrap_get(const Evas_Object *obj);
    EAPI void         elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w);
    EAPI Evas_Coord   elm_label_wrap_width_get(const Evas_Object *obj);
+   EAPI void         elm_label_fontsize_set(Evas_Object *obj, int fontsize);
+   EAPI void         elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a);
+   EAPI void         elm_label_text_align_set(Evas_Object *obj, const char *alignmode);
+   EAPI void         elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a);
+   EAPI void         elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis);
    /* available styles:
     * default
     * marker
index ad2b37b..296d040 100644 (file)
@@ -13,18 +13,26 @@ typedef struct _Widget_Data Widget_Data;
 struct _Widget_Data
 {
    Evas_Object *lbl;
+   Evas_Object *bg;
    const char *label;
    Evas_Coord lastw;
    Ecore_Job *deferred_recalc_job;
    Evas_Coord wrap_w;
    Eina_Bool linewrap : 1;
    Eina_Bool changed : 1;
+   Eina_Bool bgcolor : 1;
+   Eina_Bool ellipsis : 1;
 };
 
 static const char *widtype = NULL;
 static void _del_hook(Evas_Object *obj);
 static void _theme_hook(Evas_Object *obj);
 static void _sizing_eval(Evas_Object *obj);
+static int _get_value_in_key_string(const char *oldstring, char *key, char **value);
+static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag);
+static int _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag);
+static int _is_width_over(Evas_Object *obj);
+static void _ellipsis_label_to_width(Evas_Object *obj);
 
 static void
 _elm_win_recalc_job(void *data)
@@ -62,6 +70,7 @@ _del_hook(Evas_Object *obj)
    if (!wd) return;
    if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
    if (wd->label) eina_stringshare_del(wd->label);
+   if (wd->bg) evas_object_del(wd->bg);
    free(wd);
 }
 
@@ -105,6 +114,9 @@ _sizing_eval(Evas_Object *obj)
         evas_object_size_hint_min_set(obj, minw, minh);
         maxh = minh;
         evas_object_size_hint_max_set(obj, maxw, maxh);
+
+        if (wd->ellipsis && _is_width_over(obj) == 1) 
+          _ellipsis_label_to_width(obj);
      }
 }
 
@@ -115,6 +127,287 @@ _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event
    if (!wd) return;
    if (wd->linewrap) _sizing_eval(data);
 }
+
+static int
+_get_value_in_key_string(const char *oldstring, char *key, char **value)
+{
+   char *curlocater, *starttag, *endtag;
+   int firstindex = 0, foundflag = -1;
+
+   curlocater = strstr(oldstring, key);
+   if (curlocater)
+     {
+        starttag = curlocater;
+        endtag = curlocater + strlen(key);
+        if (endtag == NULL || *endtag != '=') 
+          {
+            foundflag = 0;
+            return -1;
+          }
+
+        firstindex = abs(oldstring - curlocater);
+        firstindex += strlen(key)+1; // strlen("key") + strlen("=")
+        *value = (char*)oldstring + firstindex;
+
+        while (oldstring != starttag)
+          {
+            if (*starttag == '>')
+              {
+                foundflag = 0;
+                break;
+              }
+            if (*starttag == '<') 
+              break;
+            else 
+              starttag--;
+            if (starttag == NULL) break;
+          }
+
+        while (NULL != endtag)
+          {
+            if (*endtag == '<')
+              {
+                foundflag = 0;
+                break;
+              }
+            if (*endtag == '>') 
+              break;
+            else 
+              endtag++;
+            if (endtag == NULL) break;
+          }
+
+        if (foundflag != 0 && *starttag == '<' && *endtag == '>') 
+          foundflag = 1;
+        else 
+          foundflag = 0;
+     }
+   else
+     {
+       foundflag = 0;
+     }
+
+   if (foundflag == 1) return 0;
+
+   return -1;
+}
+
+
+static int
+_strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag)
+{
+   const char *srcstring = NULL;
+   Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
+   char *curlocater, *replocater;
+   char *starttag, *endtag;
+   int tagtxtlen = 0, insertflag = 0;
+
+   srcstring = eina_strbuf_string_get(srcbuf);
+   curlocater = strstr(srcstring, key);
+
+   if (curlocater == NULL)
+     {
+       insertflag = 1;
+     }
+   else
+     {
+       do 
+         {
+           starttag = strchr(srcstring, '<');
+           endtag = strchr(srcstring, '>');
+           tagtxtlen = endtag - starttag;
+           if (tagtxtlen <= 0) tagtxtlen = 0;
+           if (starttag < curlocater && curlocater < endtag) break;
+           if (endtag != NULL && endtag+1 != NULL)
+             srcstring = endtag+1;
+           else
+             break;
+         } while (strlen(srcstring) > 1);
+
+       if (starttag && endtag && tagtxtlen > strlen(key))
+         {
+           repbuf = eina_strbuf_new();
+           diffbuf = eina_strbuf_new();
+           eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
+           srcstring = eina_strbuf_string_get(repbuf);
+           curlocater = strstr(srcstring, key);
+           if (curlocater != NULL)
+             {
+               replocater = curlocater + strlen(key) + 1;
+               while (*replocater != '=' && replocater != NULL)
+                 replocater++;
+               if (replocater != NULL)
+                 {
+                   replocater++;
+                   while (*replocater != ' ' && *replocater != '>' && replocater == NULL)
+                     replocater++;
+                 }
+               if (replocater != NULL)
+                 {
+                   replocater--;
+                   eina_strbuf_append_n(diffbuf, curlocater, replocater-curlocater);
+                 }
+               else
+                 insertflag = 1;
+             }
+           else
+             {
+               insertflag = 1;
+             }
+           eina_strbuf_reset(repbuf);
+         }
+       else
+         {
+           insertflag = 1; 
+         }
+     }
+
+   if (repbuf == NULL) repbuf = eina_strbuf_new();
+   if (diffbuf == NULL) diffbuf = eina_strbuf_new();
+
+   if (insertflag)
+     {
+       eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
+       eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
+     }
+   else
+     {
+        if (deleteflag)
+          {
+            eina_strbuf_prepend(diffbuf, "<");
+            eina_strbuf_append(diffbuf, ">");
+            eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
+          }
+        else
+          {
+            eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
+            eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
+          }
+     }
+
+   if (repbuf) eina_strbuf_free(repbuf);
+   if (diffbuf) eina_strbuf_free(diffbuf);
+  
+   return 0;           
+}
+
+static int
+_stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag)
+{
+   Eina_Strbuf *sharebuf = NULL;   
+   
+   sharebuf = eina_strbuf_new();
+   eina_strbuf_append(sharebuf, *srcstring);
+   _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
+   eina_stringshare_del(*srcstring);
+   *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
+   eina_strbuf_free(sharebuf);
+
+   return 0;
+}
+
+static int
+_is_width_over(Evas_Object *obj)
+{
+   Evas_Coord x, y, w, h;
+   Evas_Coord vx, vy, vw, vh;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *ellipsis_string = "...";
+   size_t ellen = strlen(ellipsis_string)+1;
+
+   if (!wd) return 0;
+
+   edje_object_part_geometry_get(wd->lbl,"elm.text",&x,&y,&w,&h);
+
+   evas_object_geometry_get (obj, &vx,&vy,&vw,&vh);
+
+   if (x >= 0 && y >= 0) return 0;
+
+   if (ellen < wd->wrap_w && w > wd->wrap_w) return 1;
+
+   return 0;
+}
+
+static void
+_ellipsis_label_to_width(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   int cur_fontsize = 0, len, showcount;
+   Eina_Strbuf *fontbuf = NULL, *txtbuf = NULL;
+   char **kvalue = NULL;
+   const char *minfont, *deffont, *maxfont;
+   const char *ellipsis_string = "...";
+   int minfontsize, maxfontsize, minshowcount;
+
+   minshowcount = strlen(ellipsis_string) + 1;
+   minfont = edje_object_data_get(wd->lbl, "min_font_size");
+   if (minfont) minfontsize = atoi(minfont);
+   else minfontsize = 1;
+   maxfont = edje_object_data_get(wd->lbl, "max_font_size");
+   if (maxfont) maxfontsize = atoi(maxfont);
+   else maxfontsize = 1;
+   deffont = edje_object_data_get(wd->lbl, "default_font_size");
+   if (deffont) cur_fontsize = atoi(deffont);
+   else cur_fontsize = 1;
+   if (minfontsize == maxfontsize || cur_fontsize == 1) return; // theme is not ready for ellipsis
+   if (eina_stringshare_strlen(wd->label) <= 0) return;
+
+   if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
+     {
+       if (*kvalue != NULL) cur_fontsize = atoi((char*)kvalue);
+     }
+
+   txtbuf = eina_strbuf_new();
+   eina_strbuf_append(txtbuf, wd->label);
+
+   while (_is_width_over(obj) == 1)
+     {
+       if (cur_fontsize > minfontsize)
+         {
+           cur_fontsize--;
+           if (fontbuf != NULL)
+             {
+               eina_strbuf_free(fontbuf);
+               fontbuf = NULL;
+             }
+           fontbuf = eina_strbuf_new();
+           eina_strbuf_append_printf(fontbuf, "%d", cur_fontsize);
+           _strbuf_key_value_replace(txtbuf, "font_size", eina_strbuf_string_get(fontbuf), 0);
+           edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
+           eina_strbuf_free(fontbuf);
+           fontbuf = NULL;
+         }
+       else
+         {
+           if (txtbuf != NULL)
+             {
+               eina_strbuf_free(txtbuf);
+               txtbuf = NULL;
+             }
+           txtbuf = eina_strbuf_new();
+           eina_strbuf_append_printf(txtbuf, "%s", edje_object_part_text_get(wd->lbl, "elm.text"));
+           len = eina_strbuf_length_get(txtbuf);
+           showcount = len - 1;
+           while (showcount > minshowcount)
+             {
+               len = eina_strbuf_length_get(txtbuf);
+               eina_strbuf_remove(txtbuf, len - minshowcount, len);
+               eina_strbuf_append(txtbuf, ellipsis_string);
+               edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
+
+               if (_is_width_over(obj) == 1) 
+                 showcount--;
+               else 
+                 break;
+             }
+         }
+     }
+
+   if (txtbuf) eina_strbuf_free(txtbuf);
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
 /**
  * Add a new label to the parent
  *
@@ -132,6 +425,9 @@ elm_label_add(Evas_Object *parent)
 
    wd = ELM_NEW(Widget_Data);
    e = evas_object_evas_get(parent);
+   wd->bgcolor = EINA_FALSE;
+   wd->bg = evas_object_rectangle_add(e);
+   evas_object_color_set(wd->bg, 0, 0, 0, 0);
    obj = elm_widget_add(e);
    ELM_SET_WIDTYPE(widtype, "label");
    elm_widget_type_set(obj, "label");
@@ -142,6 +438,7 @@ elm_label_add(Evas_Object *parent)
    elm_widget_can_focus_set(obj, 0);
 
    wd->linewrap = EINA_FALSE;
+   wd->ellipsis = EINA_FALSE;
 
    wd->lbl = edje_object_add(e);
    _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
@@ -269,3 +566,138 @@ elm_label_wrap_width_get(const Evas_Object *obj)
    if (!wd) return 0;
    return wd->wrap_w;
 }
+
+/**
+ * Set the font size on the label object
+ *
+ * @param obj The label object
+ * @param size font size
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_fontsize_set(Evas_Object *obj, int fontsize)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char *label, fontvalue[16];
+   int len;
+
+   if (!wd) return;
+   len = strlen(wd->label);
+   if (len <= 0) return;
+   label = alloca(sizeof(char)*(len+32));
+   sprintf(fontvalue, "%d", fontsize);
+
+   if (_stringshare_key_value_replace(&wd->label, "font_size", fontvalue, 0) == 0)
+     edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+
+   if (fontsize == 0) // remove fontsize tag
+    _stringshare_key_value_replace(&wd->label, "font_size", fontvalue, 1);
+
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Set the text align on the label object
+ *
+ * @param obj The label object
+ * @param align align mode
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char *label;
+   int len;
+
+   if (!wd) return;
+   len = strlen(wd->label);
+   if (len <= 0) return;
+
+   if (_stringshare_key_value_replace(&wd->label, "align", alignmode, 0) == 0)
+     edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+
+   wd->changed = 1;
+   _sizing_eval(obj);
+}
+
+/**
+ * Set the text color on the label object
+ *
+ * @param obj The label object
+ * @param r Red property background color of The label object 
+ * @param g Green property background color of The label object 
+ * @param b Blue property background color of The label object 
+ * @param a Alpha property background alpha of The label object 
+ *
+ * @ingroup Label
+ */
+EAPI void
+elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char *label, colorstring[16];
+   int len;
+
+   if (!wd) return;
+   len = strlen(wd->label);
+   if (len <= 0) return;
+   label = alloca(sizeof(char)*(len+32));
+   sprintf(colorstring, "#%02X%02X%02X%02X", r, g, b, a);
+
+   if (_stringshare_key_value_replace(&wd->label, "color", colorstring, 0) == 0)
+     {
+       edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+       wd->changed = 1;
+       _sizing_eval(obj);
+     }
+}
+
+
+/**
+ * Set background color of the label
+ *
+ * @param obj The label object
+ * @param r Red property background color of The label object 
+ * @param g Green property background color of The label object 
+ * @param b Blue property background color of The label object 
+ * @param a Alpha property background alpha of The label object 
+ * @ingroup Label
+ */
+EAPI void
+elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   evas_object_color_set(wd->bg, r, g, b, a);
+
+   if (wd->bgcolor == EINA_FALSE)
+     {
+        wd->bgcolor = 1;
+        edje_object_part_swallow(wd->lbl, "label.swallow.background", wd->bg);
+     }
+}
+
+/**
+ * Set the ellipsis behavior of the label
+ *
+ * @param obj The label object
+ * @param ellipsis To ellipsis text or not
+ * @ingroup Label
+ */
+EAPI void
+elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (wd->ellipsis == ellipsis) return;
+   wd->ellipsis = ellipsis;
+   wd->changed = 1;
+   _sizing_eval(obj);
+}