From 6caa5ca2c975cbd91806aaef3c655408eca7d231 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9E=A5=ED=9A=A8=EC=98=81?= Date: Fri, 16 Jul 2010 05:50:45 +0000 Subject: [PATCH] =?utf8?q?From:=20=EC=9E=A5=ED=9A=A8=EC=98=81=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 82 ++++++-- src/lib/Elementary.h.in | 5 + src/lib/elm_label.c | 432 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 498 insertions(+), 21 deletions(-) diff --git a/data/themes/default.edc b/data/themes/default.edc index 3eb83093a..5a801823f 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -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; diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index fc60876be..128f9df8f 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -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 diff --git a/src/lib/elm_label.c b/src/lib/elm_label.c index ad2b37b17..296d040bc 100644 --- a/src/lib/elm_label.c +++ b/src/lib/elm_label.c @@ -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); +} -- 2.34.1