Evas_Coord lastw;
Ecore_Job *deferred_recalc_job;
Evas_Coord wrap_w;
+ Evas_Coord wrap_h;
Eina_Bool linewrap : 1;
Eina_Bool changed : 1;
Eina_Bool bgcolor : 1;
static int _get_value_in_key_string(const char *oldstring, const char *key, char **value);
static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag);
static int _stringshare_key_value_replace(const char **srcstring, const 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 int _is_width_over(Evas_Object *obj, Eina_Bool multiline);
+static void _ellipsis_label_to_width(Evas_Object *obj, Eina_Bool multiline);
static void
_elm_win_recalc_job(void *data)
edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
evas_object_size_hint_min_set(data, minminw, minh);
}
+
+ if ((wd->ellipsis) && (wd->linewrap) && (wd->wrap_h > 0) &&
+ (_is_width_over(data, 1) == 1))
+ _ellipsis_label_to_width(data, 1);
+
maxh = minh;
evas_object_size_hint_max_set(data, -1, maxh);
}
}
static void
-_theme_hook(Evas_Object *obj)
+_theme_change(Evas_Object *obj)
{
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
+
if (wd->linewrap)
- _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", elm_widget_style_get(obj));
+ {
+ if (wd->ellipsis)
+ _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap_ellipsis",
+ elm_widget_style_get(obj));
+ else
+ _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap",
+ elm_widget_style_get(obj));
+ }
else
- _elm_theme_object_set(obj, wd->lbl, "label", "base", elm_widget_style_get(obj));
+ _elm_theme_object_set(obj, wd->lbl, "label", "base",
+ elm_widget_style_get(obj));
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return;
+ _theme_change(obj);
edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) *
_elm_config->scale);
{
evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
edje_object_size_min_calc(wd->lbl, &minw, &minh);
+ if (wd->wrap_w > 0 && minw > wd->wrap_w) minw = wd->wrap_w;
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);
+ if ((wd->ellipsis) && (_is_width_over(obj, 0) == 1))
+ _ellipsis_label_to_width(obj, 0);
}
}
starttag = curlocater;
endtag = curlocater + key_len;
if ((!endtag) || (*endtag != '='))
- return -1;
-
+ {
+ foundflag = 0;
+ return -1;
+ }
firstindex = abs(oldstring - curlocater);
firstindex += key_len + 1; // strlen("key") + strlen("=")
*value = (char *)oldstring + firstindex;
}
static int
-_is_width_over(Evas_Object *obj)
+_is_width_over(Evas_Object *obj, Eina_Bool multiline)
{
Evas_Coord x, y, w, h;
Evas_Coord vx, vy, vw, vh;
Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return 0;
const char *ellipsis_string = "...";
- Evas_Coord ellen = strlen(ellipsis_string)+1;
+ int mincount = sizeof(ellipsis_string) - 1;
+ char *plaintxt;
+ int plainlen = 0;
+
+ plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
+ if (plaintxt)
+ {
+ plainlen = strlen(plaintxt);
+ free(plaintxt);
+ }
+ // too short to ellipsis
+ if (plainlen <= mincount) 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 (!multiline) // single line
+ {
+ // skip if too early to check widget size
+ if ((w < 0) && (h < 0)) return 0;
+ // if string fits at widget
+ if ((x >= 0) && (y >= 0))
+ {
+ if ((wd->wrap_w > 0) && (wd->wrap_w < w))
+ {
+ Evas_Coord minw, minh;
+
+ edje_object_size_min_calc(wd->lbl, &minw, &minh);
+ if (minw < wd->wrap_w) return 0; // min insufficient
+ else return 1;
+ }
+ else return 0;
+ }
+ if ((0 < wd->wrap_w) && (w > wd->wrap_w)) return 1;
+ }
+ else // multiline
+ {
+ if (((x >= 0) || (y >= 0)) && (h > wd->wrap_h)) return 1;
+ }
- if (!wd) return 0;
+ return 0;
+}
- edje_object_part_geometry_get(wd->lbl,"elm.text",&x,&y,&w,&h);
+static void
+_ellipsis_fontsize_set(Evas_Object *obj, int fontsize)
+{
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return;
- evas_object_geometry_get (obj, &vx,&vy,&vw,&vh);
+ Eina_Strbuf *fontbuf = NULL;
+ Eina_Strbuf *txtbuf = NULL;
+ txtbuf = eina_strbuf_new();
+ fontbuf = eina_strbuf_new();
+ eina_strbuf_append(txtbuf, edje_object_part_text_get(wd->lbl, "elm.text"));
+ eina_strbuf_append_printf(fontbuf, "%d", 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);
+ eina_strbuf_free(txtbuf);
+}
- if ((x >= 0) && (y >= 0)) return 0;
+static Eina_Bool
+_ellipsis_cut_chars_to_widget(Evas_Object *obj)
+{
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return EINA_FALSE;
+ const char *ellipsis_string = "...";
+ int mincount = sizeof(ellipsis_string) - 1;
+ Evas_Coord w, h;
+ Evas_Textblock_Cursor *tc1, *tc2;
+ char *cutstr, *elstr;
+ int limitw = 0;
+ int lencutstr = 0;
+ int i = 0;
+
+ edje_object_part_geometry_get(wd->lbl, "elm.text", NULL, NULL, &w, &h);
+ if (w <= 0) return EINA_FALSE;
+ tc1 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+ tc2 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+
+ if ((wd->wrap_w > 0) && (wd->wrap_w < w)) limitw = wd->wrap_w;
+ else limitw = w;
+ evas_textblock_cursor_pos_set(tc1, 0);
+ evas_textblock_cursor_char_coord_set(tc2, limitw, 0);
+
+ // if too small to cut,(is it bug? or any other reasons?)
+ // then fallback to one step mode
+ if (evas_textblock_cursor_pos_get(tc2) < mincount)
+ {
+ Evas_Coord cx, cy, cw, ch;
+ int eolpos = evas_textblock_cursor_paragraph_text_length_get(tc1);
+
+ for (i = eolpos; i > mincount; i--)
+ {
+ evas_textblock_cursor_pos_set(tc2, i);
+ evas_textblock_cursor_char_geometry_get(tc2, &cx, &cy, &cw, &ch);
+ if (cx <= limitw) break;
+ }
- if ((ellen < wd->wrap_w) && (w > wd->wrap_w)) return 1;
+ if (evas_textblock_cursor_pos_get(tc2) < mincount)
+ {
+ evas_textblock_cursor_free(tc1);
+ evas_textblock_cursor_free(tc2);
+ return EINA_FALSE;
+ }
+ }
- return 0;
+ for (i = 0; i <= mincount; i++) evas_textblock_cursor_char_prev(tc2);
+ cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
+ if (!cutstr) return EINA_FALSE;
+
+ lencutstr = strlen(cutstr);
+ elstr = alloca(sizeof(char) * (lencutstr + mincount + 1));
+ strcpy(elstr, cutstr);
+ free(cutstr);
+ strcat(elstr, ellipsis_string);
+ edje_object_part_text_set(wd->lbl, "elm.text", elstr);
+
+ evas_textblock_cursor_free(tc1);
+ evas_textblock_cursor_free(tc2);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_ellipsis_cut_lines_to_widget(Evas_Object *obj)
+{
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return EINA_FALSE;
+ const char *ellipsis_string = "...";
+ int mincount = sizeof(ellipsis_string) - 1;
+ Evas_Coord w, h;
+ Evas_Textblock_Cursor *tc1, *tc2;
+ int linenum = 0, cutline = 0;
+ double lineheight = 0.0;
+ char *cutstr, *elstr;
+ int lencutstr = 0;
+ int limith = 0;
+ int i;
+
+ edje_object_part_geometry_get(wd->lbl, "elm.text", NULL, NULL, &w, &h);
+
+ tc1 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+ tc2 = evas_object_textblock_cursor_new((Evas_Object *)edje_object_part_object_get(wd->lbl, "elm.text"));
+ // goto last paragraph
+ while (evas_textblock_cursor_paragraph_next(tc2) == EINA_TRUE);
+
+ evas_textblock_cursor_paragraph_last(tc2);
+ // get total linenumber
+ linenum = evas_textblock_cursor_line_geometry_get(tc2, NULL, NULL, NULL, NULL);
+ lineheight = (double)h / (double)linenum;
+ if ((wd->wrap_h > 0) && (wd->wrap_h < h)) limith = wd->wrap_h;
+ else limith = h;
+ cutline = limith / lineheight;
+ if (cutline < 1) cutline = 1;
+
+ evas_textblock_cursor_pos_set(tc1, 0);
+ evas_textblock_cursor_line_set(tc2, cutline - 1);
+ evas_textblock_cursor_line_char_last(tc2);
+ for (i = 0; i <= mincount; i++) evas_textblock_cursor_char_prev(tc2);
+ cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
+ if (!cutstr) return EINA_FALSE;
+
+ lencutstr = strlen(cutstr);
+ elstr = alloca(sizeof(char) * (lencutstr + mincount + 1));
+ strcpy(elstr, cutstr);
+ free(cutstr);
+ strcat(elstr, ellipsis_string);
+ edje_object_part_text_set(wd->lbl, "elm.text", elstr);
+
+ evas_textblock_cursor_free(tc1);
+ evas_textblock_cursor_free(tc2);
+
+ return EINA_TRUE;
}
static void
-_ellipsis_label_to_width(Evas_Object *obj)
+_ellipsis_label_to_width(Evas_Object *obj, Eina_Bool multiline)
{
Widget_Data *wd = elm_widget_data_get(obj);
- int cur_fontsize = 0, len, showcount;
- Eina_Strbuf *fontbuf = NULL, *txtbuf = NULL;
- char *kvalue = NULL;
+ if (!wd) return;
+ int cur_fontsize = 0;
+ char *kvalue;
const char *minfont, *deffont, *maxfont;
- const char *ellipsis_string = "...";
- int minfontsize, maxfontsize, minshowcount;
+ int minfontsize, maxfontsize;
- minshowcount = strlen(ellipsis_string) + 1;
minfont = edje_object_data_get(wd->lbl, "min_font_size");
if (minfont) minfontsize = atoi(minfont);
else minfontsize = 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 (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))
+
+ if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
{
- if (kvalue) cur_fontsize = atoi((char *)kvalue);
+ if (kvalue != NULL) cur_fontsize = atoi(kvalue);
}
- txtbuf = eina_strbuf_new();
- eina_strbuf_append(txtbuf, wd->label);
-
- while (_is_width_over(obj) == 1)
+ while (_is_width_over(obj, multiline))
{
if (cur_fontsize > minfontsize)
{
- cur_fontsize--;
- if (fontbuf)
- {
- 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;
+ cur_fontsize -= 3;
+ if (cur_fontsize < minfontsize) cur_fontsize = minfontsize;
+ _ellipsis_fontsize_set(obj, cur_fontsize);
}
else
{
- if (txtbuf)
+ if (!multiline) // single line
{
- eina_strbuf_free(txtbuf);
- txtbuf = NULL;
+ _ellipsis_cut_chars_to_widget(obj);
+ break;
}
- 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)
+ else // multiline
{
- 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;
+ _ellipsis_cut_lines_to_widget(obj);
+ break;
}
}
}
-
- if (txtbuf) eina_strbuf_free(txtbuf);
- wd->changed = 1;
- _sizing_eval(obj);
}
+
/**
* Add a new label to the parent
*
wd->linewrap = EINA_FALSE;
wd->ellipsis = EINA_FALSE;
+ wd->wrap_w = 0;
+ wd->wrap_h = 0;
wd->lbl = edje_object_add(e);
_elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
if (wd->linewrap == wrap) return;
wd->linewrap = wrap;
t = eina_stringshare_add(elm_label_label_get(obj));
- if (wd->linewrap)
- _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", elm_widget_style_get(obj));
- else
- _elm_theme_object_set(obj, wd->lbl, "label", "base", elm_widget_style_get(obj));
+ _theme_change(obj);
elm_label_label_set(obj, t);
eina_stringshare_del(t);
wd->changed = 1;
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
+ if (w < 0) w = 0;
if (wd->wrap_w == w) return;
+ if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
wd->wrap_w = w;
_sizing_eval(obj);
}
}
/**
+ * Set wrap height of the label
+ *
+ * @param obj The label object
+ * @param w The wrap width in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI void
+elm_label_wrap_height_set(Evas_Object *obj,
+ Evas_Coord h)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype);
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return;
+ if (h < 0) h = 0;
+ if (wd->wrap_h == h) return;
+ if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+ wd->wrap_h = h;
+ _sizing_eval(obj);
+}
+
+/**
+ * get wrap width of the label
+ *
+ * @param obj The label object
+ * @return The wrap height in pixels at a minimum where words need to wrap
+ * @ingroup Label
+ */
+EAPI Evas_Coord
+elm_label_wrap_height_get(const Evas_Object *obj)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype) 0;
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return 0;
+ return wd->wrap_h;
+}
+
+/**
* Set the font size on the label object.
*
* NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
- char fontvalue[16];
- int len;
-
+ Eina_Strbuf *fontbuf = NULL;
+ int len, removeflag = 0;
+
if (!wd) return;
_elm_dangerous_call_check(__FUNCTION__);
len = strlen(wd->label);
if (len <= 0) return;
- sprintf(fontvalue, "%i", fontsize);
-
- if (!_stringshare_key_value_replace(&wd->label, "font_size", fontvalue, 0))
- edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
-
- if (!fontsize) // remove fontsize tag
- _stringshare_key_value_replace(&wd->label, "font_size", fontvalue, 1);
-
- wd->changed = 1;
- _sizing_eval(obj);
+ fontbuf = eina_strbuf_new();
+ eina_strbuf_append_printf(fontbuf, "%d", fontsize);
+
+ if (fontsize == 0) removeflag = 1; // remove fontsize tag
+ if (_stringshare_key_value_replace(&wd->label, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
+ {
+ edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
+ wd->changed = 1;
+ _sizing_eval(obj);
+ }
+ eina_strbuf_free(fontbuf);
}
/**
* "title", "footnote", "quote" etc.
*
* @param obj The label object
- * @param align align mode
+ * @param align align mode ("left", "center", "right")
*
* @ingroup Label
*/
len = strlen(wd->label);
if (len <= 0) return;
- if (!_stringshare_key_value_replace(&wd->label, "align", alignmode, 0))
+ 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;
/**
* Set the text color on the label object
*
- * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
- * "big", "medium", "small" - or better name them by use:
- * "title", "footnote", "quote" etc.
- *
* @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
+ * @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 color 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_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 colorstring[16];
+ Eina_Strbuf *colorbuf = NULL;
int len;
if (!wd) return;
_elm_dangerous_call_check(__FUNCTION__);
len = strlen(wd->label);
if (len <= 0) return;
- sprintf(colorstring, "#%02x%02x%02x%02x", r, g, b, a);
+ colorbuf = eina_strbuf_new();
+ eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
- if (!_stringshare_key_value_replace(&wd->label, "color", colorstring, 0))
+ if (_stringshare_key_value_replace(&wd->label, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
{
edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
wd->changed = 1;
_sizing_eval(obj);
}
+ eina_strbuf_free(colorbuf);
}
-
/**
* Set background color of the label
*
* @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_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);
+ if (!wd) return;
evas_object_color_set(wd->bg, r, g, b, a);
-
+
if (!wd) return;
_elm_dangerous_call_check(__FUNCTION__);
if (wd->bgcolor == EINA_FALSE)
if (!wd) return;
if (wd->ellipsis == ellipsis) return;
wd->ellipsis = ellipsis;
+ if (wd->linewrap) _theme_change(obj);
+ edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
wd->changed = 1;
_sizing_eval(obj);
}