[label] added sliding text feature
[framework/uifw/elementary.git] / src / lib / elm_label.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Label Label
6  * @ingroup Elementary
7  *
8  * Display text, with simple html-like markup. The theme of course
9  * can invent new markup tags and style them any way it likes
10  */
11
12 typedef struct _Widget_Data Widget_Data;
13
14 struct _Widget_Data
15 {
16    Evas_Object *lbl;
17    Evas_Object *bg;
18    const char *label;
19    Evas_Coord lastw;
20    Ecore_Job *deferred_recalc_job;
21    Evas_Coord wrap_w;
22    Evas_Coord wrap_h;
23    Eina_Bool linewrap : 1;
24    Eina_Bool wrapmode : 1;
25    Eina_Bool changed : 1;
26    Eina_Bool bgcolor : 1;
27    Eina_Bool ellipsis : 1;
28 };
29
30 static const char *widtype = NULL;
31 static void _del_hook(Evas_Object *obj);
32 static void _theme_hook(Evas_Object *obj);
33 static void _sizing_eval(Evas_Object *obj);
34 static int _get_value_in_key_string(const char *oldstring, char *key, char **value);
35 static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag);
36 static int _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag);
37 static int _is_width_over(Evas_Object *obj, int linemode);
38 static void _ellipsis_label_to_width(Evas_Object *obj, int linemode);
39
40 static void
41 _elm_win_recalc_job(void *data)
42 {
43    Widget_Data *wd = elm_widget_data_get(data);
44    Evas_Coord minw = -1, minh = -1, maxh = -1;
45    Evas_Coord resw, resh, minminw, minminh;
46    if (!wd) return;
47    wd->deferred_recalc_job = NULL;
48    evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
49    resh = 0;
50    minminw = 0;
51    edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, 0, 0);
52    minminw = minw;
53    minminh = minh;
54    if (wd->wrap_w >= resw) 
55      {
56         resw = wd->wrap_w;
57         edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
58         evas_object_size_hint_min_set(data, minw, minh);
59      }
60    else
61      {
62         if (wd->wrap_w > minminw) minminw = wd->wrap_w;
63         edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
64         evas_object_size_hint_min_set(data, minminw, minh);
65      }
66
67    if (wd->ellipsis && wd->linewrap && wd->wrap_h > 0 && _is_width_over(data, 1) == 1) 
68      _ellipsis_label_to_width(data, 1);
69
70    maxh = minh;
71    evas_object_size_hint_max_set(data, -1, maxh);
72 }
73
74 static void
75 _del_hook(Evas_Object *obj)
76 {
77    Widget_Data *wd = elm_widget_data_get(obj);
78    if (!wd) return;
79    if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
80    if (wd->label) eina_stringshare_del(wd->label);
81    if (wd->bg) evas_object_del(wd->bg);
82    free(wd);
83 }
84
85 static void
86 _theme_change(Evas_Object *obj)
87 {
88    Widget_Data *wd = elm_widget_data_get(obj);
89    if (!wd) return;
90
91    if (wd->linewrap)
92      {
93        if (wd->ellipsis)
94          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap_ellipsis", elm_widget_style_get(obj));
95        else
96          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", elm_widget_style_get(obj));
97      }
98    else
99      _elm_theme_object_set(obj, wd->lbl, "label", "base", elm_widget_style_get(obj));
100
101 }
102
103 static void
104 _theme_hook(Evas_Object *obj)
105 {
106    Widget_Data *wd = elm_widget_data_get(obj);
107    if (!wd) return;
108    _theme_change(obj);
109    edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
110    edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) * 
111                          _elm_config->scale);
112    _sizing_eval(obj);
113 }
114
115 static void
116 _sizing_eval(Evas_Object *obj)
117 {
118    Widget_Data *wd = elm_widget_data_get(obj);
119    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
120    Evas_Coord resw, resh;
121    if (!wd) return;
122    if (wd->linewrap)
123      {
124         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
125         if ((resw == wd->lastw) && (!wd->changed)) return;
126         wd->changed = EINA_FALSE;
127         wd->lastw = resw;
128         _elm_win_recalc_job(obj);
129 // FIXME: works ok. but NOT for genlist. what should genlist do?        
130 //        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
131 //        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
132      }
133    else
134      {
135         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
136         edje_object_size_min_calc(wd->lbl, &minw, &minh);
137         evas_object_size_hint_min_set(obj, minw, minh);
138         maxh = minh;
139         evas_object_size_hint_max_set(obj, maxw, maxh);
140
141         if (wd->ellipsis && _is_width_over(obj, 0) == 1) 
142           _ellipsis_label_to_width(obj, 0);
143      }
144 }
145
146 static void 
147 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
148 {
149    Widget_Data *wd = elm_widget_data_get(data);
150    if (!wd) return;
151    if (wd->linewrap) _sizing_eval(data);
152 }
153
154 static int
155 _get_value_in_key_string(const char *oldstring, char *key, char **value)
156 {
157    char *curlocater, *starttag, *endtag;
158    int firstindex = 0, foundflag = -1;
159
160    curlocater = strstr(oldstring, key);
161    if (curlocater)
162      {
163         starttag = curlocater;
164         endtag = curlocater + strlen(key);
165         if (endtag == NULL || *endtag != '=') 
166           {
167             foundflag = 0;
168             return -1;
169           }
170
171         firstindex = abs(oldstring - curlocater);
172         firstindex += strlen(key)+1; // strlen("key") + strlen("=")
173         *value = (char*)oldstring + firstindex;
174
175         while (oldstring != starttag)
176           {
177             if (*starttag == '>')
178               {
179                 foundflag = 0;
180                 break;
181               }
182             if (*starttag == '<') 
183               break;
184             else 
185               starttag--;
186             if (starttag == NULL) break;
187           }
188
189         while (NULL != endtag)
190           {
191             if (*endtag == '<')
192               {
193                 foundflag = 0;
194                 break;
195               }
196             if (*endtag == '>') 
197               break;
198             else 
199               endtag++;
200             if (endtag == NULL) break;
201           }
202
203         if (foundflag != 0 && *starttag == '<' && *endtag == '>') 
204           foundflag = 1;
205         else 
206           foundflag = 0;
207      }
208    else
209      {
210        foundflag = 0;
211      }
212
213    if (foundflag == 1) return 0;
214
215    return -1;
216 }
217
218 static int
219 _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag)
220 {
221    const char *srcstring = NULL;
222    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
223    char *curlocater, *replocater;
224    char *starttag, *endtag;
225    int tagtxtlen = 0, insertflag = 0;
226
227    srcstring = eina_strbuf_string_get(srcbuf);
228    curlocater = strstr(srcstring, key);
229
230    if (curlocater == NULL)
231      {
232        insertflag = 1;
233      }
234    else
235      {
236        do 
237          {
238            starttag = strchr(srcstring, '<');
239            endtag = strchr(srcstring, '>');
240            tagtxtlen = endtag - starttag;
241            if (tagtxtlen <= 0) tagtxtlen = 0;
242            if (starttag < curlocater && curlocater < endtag) break;
243            if (endtag != NULL && endtag+1 != NULL)
244              srcstring = endtag+1;
245            else
246              break;
247          } while (strlen(srcstring) > 1);
248
249        if (starttag && endtag && tagtxtlen > strlen(key))
250          {
251            repbuf = eina_strbuf_new();
252            diffbuf = eina_strbuf_new();
253            eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
254            srcstring = eina_strbuf_string_get(repbuf);
255            curlocater = strstr(srcstring, key);
256
257            if (curlocater != NULL)
258              {
259                replocater = curlocater + strlen(key) + 1;
260
261                while (*replocater == ' ' || *replocater == '=')
262                            {
263                  replocater++;
264                            }
265
266                 while (*replocater != NULL && *replocater != ' ' && *replocater != '>')
267                   replocater++;
268
269                if (replocater-curlocater > strlen(key)+1)
270                  {
271                    replocater--;
272                    eina_strbuf_append_n(diffbuf, curlocater, replocater-curlocater+1);
273                  }
274                else
275                  insertflag = 1;
276              }
277            else
278              {
279                insertflag = 1;
280              }
281            eina_strbuf_reset(repbuf);
282          }
283        else
284          {
285            insertflag = 1; 
286          }
287      }
288
289    if (repbuf == NULL) repbuf = eina_strbuf_new();
290    if (diffbuf == NULL) diffbuf = eina_strbuf_new();
291
292    if (insertflag)
293      {
294        eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
295        eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
296      }
297    else
298      {
299         if (deleteflag)
300           {
301             eina_strbuf_prepend(diffbuf, "<");
302             eina_strbuf_append(diffbuf, ">");
303             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
304           }
305         else
306           {
307             eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
308             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
309           }
310      }
311
312    if (repbuf) eina_strbuf_free(repbuf);
313    if (diffbuf) eina_strbuf_free(diffbuf);
314   
315    return 0;           
316 }
317
318 static int
319 _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag)
320 {
321    Eina_Strbuf *sharebuf = NULL;   
322    
323    sharebuf = eina_strbuf_new();
324    eina_strbuf_append(sharebuf, *srcstring);
325    _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
326    eina_stringshare_del(*srcstring);
327    *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
328    eina_strbuf_free(sharebuf);
329
330    return 0;
331 }
332
333 static int
334 _is_width_over(Evas_Object *obj, int linemode)
335 {
336    Evas_Coord x, y, w, h;
337    Evas_Coord vx, vy, vw, vh;
338    Widget_Data *wd = elm_widget_data_get(obj);
339    const char *ellipsis_string = "...";
340    size_t ellen = strlen(ellipsis_string)+1;
341
342    if (!wd) return 0;
343
344    edje_object_part_geometry_get(wd->lbl,"elm.text",&x,&y,&w,&h);
345
346    evas_object_geometry_get (obj, &vx,&vy,&vw,&vh);
347
348    if (linemode == 0) // single line
349      {
350        if ((x >= 0) && (y >= 0))
351            {
352                    if ((wd->wrap_w > 0) && (wd->wrap_w < w))
353                    {
354                            Evas_Coord minw, minh;
355                            edje_object_size_min_calc(wd->lbl, &minw, &minh);
356
357                            if (minw < wd->wrap_w)
358                            { // min insufficient
359                                    return 0;
360                            }
361                            else
362                                    return 1;
363                    }
364                    else
365                            return 0;
366            }
367
368        if (ellen < wd->wrap_w && w > wd->wrap_w) return 1;
369      }
370    else // multiline
371      {
372        if (vy > h && h > wd->wrap_h) return 1;
373      }
374
375    return 0;
376 }
377
378 static void
379 _ellipsis_label_to_width(Evas_Object *obj, int linemode)
380 {
381    Widget_Data *wd = elm_widget_data_get(obj);
382    int cur_fontsize = 0, len, showcount;
383    Eina_Strbuf *fontbuf = NULL, *txtbuf = NULL;
384    char **kvalue = NULL;
385    const char *minfont, *deffont, *maxfont;
386    const char *ellipsis_string = "...";
387    int minfontsize, maxfontsize, minshowcount;
388
389    minshowcount = strlen(ellipsis_string) + 1;
390    minfont = edje_object_data_get(wd->lbl, "min_font_size");
391    if (minfont) minfontsize = atoi(minfont);
392    else minfontsize = 1;
393    maxfont = edje_object_data_get(wd->lbl, "max_font_size");
394    if (maxfont) maxfontsize = atoi(maxfont);
395    else maxfontsize = 1;
396    deffont = edje_object_data_get(wd->lbl, "default_font_size");
397    if (deffont) cur_fontsize = atoi(deffont);
398    else cur_fontsize = 1;
399    if (minfontsize > maxfontsize || cur_fontsize == 1) return; // theme is not ready for ellipsis
400    if (eina_stringshare_strlen(wd->label) <= 0) return;
401
402    if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
403      {
404        if (*kvalue != NULL) cur_fontsize = atoi((char*)kvalue);
405      }
406
407    txtbuf = eina_strbuf_new();
408    eina_strbuf_append(txtbuf, wd->label);
409
410    while (_is_width_over(obj, linemode))
411      {
412        if (cur_fontsize > minfontsize)
413          {
414            cur_fontsize--;
415            if (fontbuf != NULL)
416              {
417                eina_strbuf_free(fontbuf);
418                fontbuf = NULL;
419              }
420            fontbuf = eina_strbuf_new();
421            eina_strbuf_append_printf(fontbuf, "%d", cur_fontsize);
422            _strbuf_key_value_replace(txtbuf, "font_size", eina_strbuf_string_get(fontbuf), 0);
423            edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
424            eina_strbuf_free(fontbuf);
425            fontbuf = NULL;
426          }
427        else
428          {
429            if (txtbuf != NULL)
430              {
431                eina_strbuf_free(txtbuf);
432                txtbuf = NULL;
433              }
434            txtbuf = eina_strbuf_new();
435            eina_strbuf_append_printf(txtbuf, "%s", edje_object_part_text_get(wd->lbl, "elm.text"));
436            len = eina_strbuf_length_get(txtbuf);
437            showcount = len - 1;
438            while (showcount > minshowcount)
439              {
440                unsigned char *ltxt = eina_strbuf_string_get(txtbuf);
441                len = eina_strbuf_length_get(txtbuf);
442                // FIXME : more reliable truncate routine is needed
443                //         it works on only EUC-KR
444                int delta = 0;
445                            if (ltxt[len-minshowcount-delta] >= 0x80)
446                  {
447                    delta = 2;
448                    showcount--;
449                  }
450                eina_strbuf_remove(txtbuf, len-minshowcount-delta, len);
451                eina_strbuf_append(txtbuf, ellipsis_string);
452                edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
453
454                if (_is_width_over(obj, linemode))
455                  showcount--;
456                else 
457                  break;
458              }
459          }
460      }
461
462    if (txtbuf) eina_strbuf_free(txtbuf);
463    wd->changed = 1;
464    _sizing_eval(obj);
465 }
466
467 /*
468  * setting internal state of mulitline entry
469  * singleline doesn't need it
470  */
471
472 void _label_state_change(Evas_Object *obj)
473 {
474    Widget_Data *wd = elm_widget_data_get(obj);
475    if (!wd) return;
476
477    if (wd->linewrap)
478    {
479            if (wd->wrapmode)
480                    edje_object_signal_emit(wd->lbl, "elm,state,wordwrap", "elm");
481            else
482                    edje_object_signal_emit(wd->lbl, "elm,state,default", "elm");
483    }
484 }
485
486
487 /**
488  * Add a new label to the parent
489  *
490  * @param parent The parent object
491  * @return The new object or NULL if it cannot be created
492  *
493  * @ingroup Label
494  */
495 EAPI Evas_Object *
496 elm_label_add(Evas_Object *parent)
497 {
498    Evas_Object *obj;
499    Evas *e;
500    Widget_Data *wd;
501
502    wd = ELM_NEW(Widget_Data);
503    e = evas_object_evas_get(parent);
504    wd->bg = evas_object_rectangle_add(e);
505    evas_object_color_set(wd->bg, 0, 0, 0, 0);
506    obj = elm_widget_add(e);
507    ELM_SET_WIDTYPE(widtype, "label");
508    elm_widget_type_set(obj, "label");
509    elm_widget_sub_object_add(parent, obj);
510    elm_widget_data_set(obj, wd);
511    elm_widget_del_hook_set(obj, _del_hook);
512    elm_widget_theme_hook_set(obj, _theme_hook);
513    elm_widget_can_focus_set(obj, 0);
514
515    wd->linewrap = EINA_FALSE;
516    wd->bgcolor = EINA_FALSE;
517    wd->ellipsis = EINA_FALSE;
518    wd->wrapmode = EINA_FALSE;
519    wd->wrap_w = 0;
520    wd->wrap_h = 0;
521
522    wd->lbl = edje_object_add(e);
523    _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
524    wd->label = eina_stringshare_add("<br>");
525    edje_object_part_text_set(wd->lbl, "elm.text", "<br>");
526    elm_widget_resize_object_set(obj, wd->lbl);
527    
528    evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _resize, obj);
529    
530    wd->changed = 1;
531    _sizing_eval(obj);
532    return obj;
533 }
534
535 /**
536  * Set the label on the label object
537  *
538  * @param obj The label object
539  * @param label The label will be used on the label object
540  *
541  * @ingroup Label
542  */
543 EAPI void
544 elm_label_label_set(Evas_Object *obj, const char *label)
545 {
546    ELM_CHECK_WIDTYPE(obj, widtype);
547    Widget_Data *wd = elm_widget_data_get(obj);
548    if (!wd) return;
549    if (!label) label = "";
550    eina_stringshare_replace(&wd->label, label);
551    edje_object_part_text_set(wd->lbl, "elm.text", label);
552    wd->changed = 1;
553    _sizing_eval(obj);
554 }
555
556 /**
557  * Get the label used on the label object
558  *
559  * @param obj The label object
560  * @return The string inside the label
561  * @ingroup Label
562  */
563 EAPI const char *
564 elm_label_label_get(const Evas_Object *obj)
565 {
566    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
567    Widget_Data *wd = elm_widget_data_get(obj);
568    if (!wd) return NULL;
569    return wd->label;
570 }
571
572 /**
573  * Set the wrapping behavior of the label
574  *
575  * @param obj The label object
576  * @param wrap To wrap text or not
577  * @ingroup Label
578  */
579 EAPI void
580 elm_label_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
581 {
582    ELM_CHECK_WIDTYPE(obj, widtype);
583    Widget_Data *wd = elm_widget_data_get(obj);
584    if (!wd) return;
585    const char *t;
586    if (wd->linewrap == wrap) return;
587    wd->linewrap = wrap;
588    t = eina_stringshare_add(elm_label_label_get(obj));
589    _theme_change(obj);
590    elm_label_label_set(obj, t);
591    eina_stringshare_del(t);
592    wd->changed = 1;
593    _sizing_eval(obj);
594 }
595
596 /**
597  * Get the wrapping behavior of the label
598  *
599  * @param obj The label object
600  * @return To wrap text or not
601  * @ingroup Label
602  */
603 EAPI Eina_Bool
604 elm_label_line_wrap_get(const Evas_Object *obj)
605 {
606    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
607    Widget_Data *wd = elm_widget_data_get(obj);
608    if (!wd) return EINA_FALSE;
609    return wd->linewrap;
610 }
611
612 /**
613  * Set wrap width of the label
614  *
615  * @param obj The label object
616  * @param w The wrap width in pixels at a minimum where words need to wrap
617  * @ingroup Label
618  */
619 EAPI void
620 elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
621 {
622    ELM_CHECK_WIDTYPE(obj, widtype);
623    Widget_Data *wd = elm_widget_data_get(obj);
624    if (!wd) return;
625    if (w < 0) w = 0;
626    if (wd->wrap_w == w) return;
627    if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
628    wd->wrap_w = w;
629    _sizing_eval(obj);
630 }
631
632 /**
633  * get wrap width of the label
634  *
635  * @param obj The label object
636  * @return The wrap width in pixels at a minimum where words need to wrap
637  * @ingroup Label
638  */
639 EAPI Evas_Coord
640 elm_label_wrap_width_get(const Evas_Object *obj)
641 {
642    ELM_CHECK_WIDTYPE(obj, widtype) 0;
643    Widget_Data *wd = elm_widget_data_get(obj);
644    if (!wd) return 0;
645    return wd->wrap_w;
646 }
647
648 /**
649  * Set wrap height of the label
650  *
651  * @param obj The label object
652  * @param w The wrap width in pixels at a minimum where words need to wrap
653  * @ingroup Label
654  */
655 EAPI void
656 elm_label_wrap_height_set(Evas_Object *obj, Evas_Coord h)
657 {
658    ELM_CHECK_WIDTYPE(obj, widtype);
659    Widget_Data *wd = elm_widget_data_get(obj);
660    if (!wd) return;
661    if (h < 0) h = 0;
662    if (wd->wrap_h == h) return;
663    if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
664    wd->wrap_h = h;
665    _sizing_eval(obj);
666 }
667
668 /**
669  * get wrap width of the label
670  *
671  * @param obj The label object
672  * @return The wrap height in pixels at a minimum where words need to wrap
673  * @ingroup Label
674  */
675 EAPI Evas_Coord
676 elm_label_wrap_height_get(const Evas_Object *obj)
677 {
678    ELM_CHECK_WIDTYPE(obj, widtype) 0;
679    Widget_Data *wd = elm_widget_data_get(obj);
680    if (!wd) return 0;
681    return wd->wrap_h;
682 }
683
684 /**
685  * Set the font size on the label object
686  *
687  * @param obj The label object
688  * @param size font size
689  *
690  * @ingroup Label
691  */
692 EAPI void
693 elm_label_fontsize_set(Evas_Object *obj, int fontsize)
694 {
695    ELM_CHECK_WIDTYPE(obj, widtype);
696    Widget_Data *wd = elm_widget_data_get(obj);
697    Eina_Strbuf *fontbuf = NULL;
698    int len, removeflag = 0;
699
700    if (!wd) return;
701    len = strlen(wd->label);
702    if (len <= 0) return;
703    fontbuf = eina_strbuf_new();
704    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
705
706    if (fontsize == 0) removeflag = 1; // remove fontsize tag
707
708    if (_stringshare_key_value_replace(&wd->label, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
709      {
710        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
711        wd->changed = 1;
712        _sizing_eval(obj);
713      }
714    eina_strbuf_free(fontbuf);
715 }
716
717 /**
718  * Set the text align on the label object
719  *
720  * @param obj The label object
721  * @param align align mode ("left", "center", "right")
722  *
723  * @ingroup Label
724  */
725 EAPI void
726 elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
727 {
728    ELM_CHECK_WIDTYPE(obj, widtype);
729    Widget_Data *wd = elm_widget_data_get(obj);
730    int len;
731
732    if (!wd) return;
733    len = strlen(wd->label);
734    if (len <= 0) return;
735
736    if (_stringshare_key_value_replace(&wd->label, "align", alignmode, 0) == 0)
737      edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
738
739    wd->changed = 1;
740    _sizing_eval(obj);
741 }
742
743 /**
744  * Set the text color on the label object
745  *
746  * @param obj The label object
747  * @param r Red property background color of The label object 
748  * @param g Green property background color of The label object 
749  * @param b Blue property background color of The label object 
750  * @param a Alpha property background alpha of The label object 
751  *
752  * @ingroup Label
753  */
754 EAPI void
755 elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
756 {
757    ELM_CHECK_WIDTYPE(obj, widtype);
758    Widget_Data *wd = elm_widget_data_get(obj);
759    Eina_Strbuf *colorbuf = NULL;
760    int len;
761
762    if (!wd) return;
763    len = strlen(wd->label);
764    if (len <= 0) return;
765    colorbuf = eina_strbuf_new();
766    eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
767
768    if (_stringshare_key_value_replace(&wd->label, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
769      {
770        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
771        wd->changed = 1;
772        _sizing_eval(obj);
773      }
774    eina_strbuf_free(colorbuf);
775 }
776
777
778 /**
779  * Set background color of the label
780  *
781  * @param obj The label object
782  * @param r Red property background color of The label object 
783  * @param g Green property background color of The label object 
784  * @param b Blue property background color of The label object 
785  * @param a Alpha property background alpha of The label object 
786  * @ingroup Label
787  */
788 EAPI void
789 elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
790 {
791    ELM_CHECK_WIDTYPE(obj, widtype);
792    Widget_Data *wd = elm_widget_data_get(obj);
793    evas_object_color_set(wd->bg, r, g, b, a);
794
795    if (wd->bgcolor == EINA_FALSE)
796      {
797         wd->bgcolor = 1;
798         edje_object_part_swallow(wd->lbl, "label.swallow.background", wd->bg);
799      }
800 }
801
802 /**
803  * Set the ellipsis behavior of the label
804  *
805  * @param obj The label object
806  * @param ellipsis To ellipsis text or not
807  * @ingroup Label
808  */
809 EAPI void
810 elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
811 {
812    ELM_CHECK_WIDTYPE(obj, widtype);
813    Widget_Data *wd = elm_widget_data_get(obj);
814    if (wd->ellipsis == ellipsis) return;
815    wd->ellipsis = ellipsis;
816    if (wd->linewrap) _theme_change(obj);
817    wd->changed = 1;
818    _sizing_eval(obj);
819 }
820
821 /**
822  * Set the wrapmode of the label
823  *
824  * @param obj The label object
825  * @param wrapmode 0 is charwrap, 1 is wordwrap
826  * @ingroup Label
827  */
828 EAPI void
829 elm_label_wrap_mode_set(Evas_Object *obj, Eina_Bool wrapmode)
830 {
831    ELM_CHECK_WIDTYPE(obj, widtype);
832    Widget_Data *wd = elm_widget_data_get(obj);
833    if (wd->wrapmode == wrapmode) return;
834    wd->wrapmode = wrapmode;
835    _label_state_change(obj);
836    wd->changed = 1;
837    _sizing_eval(obj);
838 }
839
840 /**
841  * Set the text slide of the label
842  *
843  * @param obj The label object
844  * @param slide To start slide or stop
845  * @ingroup Label
846  */
847 EAPI void
848 elm_label_slide_set(Evas_Object *obj, Eina_Bool slide)
849 {
850    ELM_CHECK_WIDTYPE(obj, widtype);
851    Widget_Data *wd = elm_widget_data_get(obj);
852    if (!wd) return;
853
854    if (slide)
855            edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
856    else
857            edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
858 }