Merge branch 'master' into svn_merge
[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  *
7  * Display text, with simple html-like markup. The theme of course
8  * can invent new markup tags and style them any way it likes
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12
13 struct _Widget_Data
14 {
15    Evas_Object *lbl;
16    Evas_Object *bg;
17    const char *label;
18    const char *format;
19    Ecore_Job *deferred_recalc_job;
20    double slide_duration;
21    Evas_Coord lastw;
22    Evas_Coord wrap_w;
23    Evas_Coord wrap_h;
24    Eina_Bool linewrap : 1;
25    Eina_Bool changed : 1;
26    Eina_Bool bgcolor : 1;
27    Eina_Bool ellipsis : 1;
28    Eina_Bool slidingmode : 1;
29    Eina_Bool slidingellipsis : 1;
30 };
31
32 static const char *widtype = NULL;
33 static void _del_hook(Evas_Object *obj);
34 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
35 static void _theme_hook(Evas_Object *obj);
36 static void _sizing_eval(Evas_Object *obj);
37 static int _get_value_in_key_string(const char *oldstring, const char *key, char **value);
38 static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag);
39 static int _stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag);
40 static int _is_width_over(Evas_Object *obj);
41 static void _ellipsis_label_to_width(Evas_Object *obj);
42 static void _label_sliding_change(Evas_Object *obj);
43
44 static void
45 _elm_win_recalc_job(void *data)
46 {
47    Widget_Data *wd = elm_widget_data_get(data);
48    Evas_Coord minw = -1, minh = -1;
49    Evas_Coord resw;
50    if (!wd) return;
51    wd->deferred_recalc_job = NULL;
52    evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, NULL);
53    if (wd->wrap_w > resw)
54       resw = wd->wrap_w;
55
56    edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
57    /* This is a hack to workaround the way min size hints are treated.
58     * If the minimum width is smaller than the restricted width, it means
59     * the mininmum doesn't matter. */
60    if ((minw <= resw) && (minw != wd->wrap_w))
61      {
62         Evas_Coord ominw = -1;
63         evas_object_size_hint_min_get(data, &ominw, NULL);
64         minw = ominw;
65      }
66    evas_object_size_hint_min_set(data, minw, minh);
67    evas_object_size_hint_max_set(data, wd->wrap_w, wd->wrap_h);
68
69    if ((wd->ellipsis) && (wd->linewrap) && (wd->wrap_h > 0) &&
70        (_is_width_over(data) == 1))
71      _ellipsis_label_to_width(data);
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    _elm_theme_object_set(obj, wd->lbl, "label", "base",
92          elm_widget_style_get(obj));
93 }
94
95 static void
96 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
97 {
98    Widget_Data *wd = elm_widget_data_get(obj);
99    if (!wd) return;
100    edje_object_mirrored_set(wd->lbl, rtl);
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    _elm_widget_mirrored_reload(obj);
109    _mirrored_set(obj, elm_widget_mirrored_get(obj));
110    _theme_change(obj);
111    edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
112    edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
113    edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) *
114                          _elm_config->scale);
115    _label_sliding_change(obj);
116    _sizing_eval(obj);
117 }
118
119 static void
120 _sizing_eval(Evas_Object *obj)
121 {
122    Widget_Data *wd = elm_widget_data_get(obj);
123    Evas_Coord minw = -1, minh = -1;
124    Evas_Coord resw, resh;
125    if (!wd) return;
126
127    if (wd->linewrap)
128      {
129         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
130         if ((resw == wd->lastw) && (!wd->changed)) return;
131         wd->changed = EINA_FALSE;
132         wd->lastw = resw;
133         _elm_win_recalc_job(obj);
134         // FIXME: works ok. but NOT for genlist. what should genlist do?
135         //        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
136         //        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
137      }
138    else
139      {
140         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
141         edje_object_size_min_calc(wd->lbl, &minw, &minh);
142         if (wd->wrap_w > 0 && minw > wd->wrap_w) minw = wd->wrap_w;
143         if (wd->wrap_h > 0 && minh > wd->wrap_h) minh = wd->wrap_h;
144         evas_object_size_hint_min_set(obj, minw, minh);
145         evas_object_size_hint_max_set(obj, wd->wrap_w, wd->wrap_h);
146         if ((wd->ellipsis) && (_is_width_over(obj) == 1))
147           _ellipsis_label_to_width(obj);
148      }
149 }
150
151 static void
152 _lbl_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
153 {
154    Widget_Data *wd = elm_widget_data_get(data);
155    if (!wd) return;
156    if (wd->linewrap) _sizing_eval(data);
157 }
158
159 static int
160 _get_value_in_key_string(const char *oldstring, const char *key, char **value)
161 {
162    char *curlocater, *starttag, *endtag;
163    int firstindex = 0, foundflag = -1;
164
165    curlocater = strstr(oldstring, key);
166    if (curlocater)
167      {
168         int key_len = strlen(key);
169         starttag = curlocater;
170         endtag = curlocater + key_len;
171         if ((!endtag) || (*endtag != '='))
172           {
173              foundflag = 0;
174              return -1;
175           }
176         firstindex = abs(oldstring - curlocater);
177         firstindex += key_len + 1; // strlen("key") + strlen("=")
178         *value = (char *)oldstring + firstindex;
179
180         while (oldstring != starttag)
181           {
182              if (*starttag == '>')
183                {
184                   foundflag = 0;
185                   break;
186                }
187              if (*starttag == '<')
188                break;
189              else
190                starttag--;
191              if (!starttag) break;
192           }
193
194         while (endtag)
195           {
196              if (*endtag == '<')
197                {
198                   foundflag = 0;
199                   break;
200                }
201              if (*endtag == '>')
202                break;
203              else
204                endtag++;
205              if (!endtag) break;
206           }
207
208         if ((foundflag) && (*starttag == '<') && (*endtag == '>'))
209           foundflag = 1;
210         else
211           foundflag = 0;
212      }
213    else
214      {
215         foundflag = 0;
216      }
217
218    if (foundflag == 1) return 0;
219
220    return -1;
221 }
222
223
224 static int
225 _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag)
226 {
227    const char *srcstring = NULL;
228    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
229    char *curlocater, *replocater;
230    char *starttag, *endtag;
231    int tagtxtlen = 0, insertflag = 0;
232
233    srcstring = eina_strbuf_string_get(srcbuf);
234    curlocater = strstr(srcstring, key);
235
236    if (!curlocater)
237      insertflag = 1;
238    else
239      {
240         int key_len = strlen(key);
241         do
242           {
243              starttag = strchr(srcstring, '<');
244              endtag = strchr(srcstring, '>');
245              tagtxtlen = endtag - starttag;
246              if (tagtxtlen <= 0) tagtxtlen = 0;
247              if ((starttag < curlocater) && (curlocater < endtag)) break;
248              if ((endtag) && ((endtag + 1)))
249                srcstring = endtag + 1;
250              else
251                break;
252           } while (strlen(srcstring) > 1);
253
254         if ((starttag) && (endtag) && (tagtxtlen > key_len))
255           {
256              char *eqchar = NULL;
257              repbuf = eina_strbuf_new();
258              diffbuf = eina_strbuf_new();
259              eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
260              srcstring = eina_strbuf_string_get(repbuf);
261              curlocater = strstr(srcstring, key);
262              // key=value
263              //    ^ : move to here
264              eqchar = curlocater + key_len;
265              if ((curlocater) && (eqchar))
266                {
267                   // some case at useless many whitespaces (key  =value)
268                   // find the separator(=) position
269                   eqchar = strchr(curlocater + key_len, '=');
270                   if (eqchar)
271                     {
272                        // key=value
273                        //     ^ : move to here
274                        replocater = eqchar + 1;
275                        while ((*replocater) &&
276                               (*replocater != ' ') &&
277                               (*replocater != '>'))
278                          replocater++;
279
280                        if ((replocater - curlocater) > key_len)
281                          eina_strbuf_append_n(diffbuf, curlocater,
282                                               replocater-curlocater);
283                        else
284                          insertflag = 1;
285                     }
286                   else
287                     insertflag = 1;
288                }
289              else
290                insertflag = 1;
291              eina_strbuf_reset(repbuf);
292           }
293         else
294           insertflag = 1;
295      }
296
297    if (!repbuf) repbuf = eina_strbuf_new();
298    if (!diffbuf) diffbuf = eina_strbuf_new();
299
300    if (insertflag)
301      {
302         eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
303         eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
304      }
305    else
306      {
307         if (deleteflag)
308           {
309              eina_strbuf_prepend(diffbuf, "<");
310              eina_strbuf_append(diffbuf, ">");
311              eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
312           }
313         else
314           {
315              eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
316              eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
317           }
318      }
319
320    if (repbuf) eina_strbuf_free(repbuf);
321    if (diffbuf) eina_strbuf_free(diffbuf);
322
323    return 0;
324 }
325
326 static int
327 _stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag)
328 {
329    Eina_Strbuf *sharebuf = NULL;
330
331    sharebuf = eina_strbuf_new();
332    eina_strbuf_append(sharebuf, *srcstring);
333    _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
334    eina_stringshare_del(*srcstring);
335    *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
336    eina_strbuf_free(sharebuf);
337
338    return 0;
339 }
340
341 static int
342 _is_width_over(Evas_Object *obj)
343 {
344    Evas_Coord x, y, w, h;
345    Evas_Coord vx, vy, vw, vh;
346    Widget_Data *wd = elm_widget_data_get(obj);
347    if (!wd) return 0;
348
349    edje_object_part_geometry_get(wd->lbl, "elm.text", &x, &y, NULL, NULL);
350    /* Calc the formatted size with ellipsis turned off */
351    if (wd->ellipsis)
352      {
353         const Evas_Object *tb;
354         char *_kvalue;
355         double ellipsis = 0.0;
356         Eina_Bool found_key = EINA_FALSE;
357         if (_get_value_in_key_string(wd->format, "ellipsis", &_kvalue) == 0)
358           {
359              ellipsis = atof(_kvalue);
360              found_key = EINA_TRUE;
361           }
362
363         if (_stringshare_key_value_replace(&wd->format,
364                  "ellipsis", NULL, 1) == 0)
365           {
366              edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
367              edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
368           }
369
370         tb = edje_object_part_object_get(wd->lbl, "elm.text");
371         evas_object_textblock_size_formatted_get(tb, &w, &h);
372
373         if (found_key)
374           {
375              Eina_Strbuf *elpbuf;
376              elpbuf = eina_strbuf_new();
377              eina_strbuf_append_printf(elpbuf, "%f", ellipsis);
378              if (_stringshare_key_value_replace(&wd->format, "ellipsis",
379                       eina_strbuf_string_get(elpbuf), 0) == 0)
380                {
381                   edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
382                   edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
383                }
384              eina_strbuf_free(elpbuf);
385           }
386      }
387    else
388      {
389         const Evas_Object *tb;
390         tb = edje_object_part_object_get(wd->lbl, "elm.text");
391         evas_object_textblock_size_formatted_get(tb, &w, &h);
392      }
393    evas_object_geometry_get(obj, &vx, &vy, &vw, &vh);
394
395    if (w > wd->wrap_w || h > wd->wrap_h)
396       return 1;
397
398    return 0;
399 }
400
401 static void
402 _ellipsis_fontsize_set(Evas_Object *obj, int fontsize)
403 {
404    Widget_Data *wd = elm_widget_data_get(obj);
405    Eina_Strbuf *fontbuf = NULL;
406    int removeflag = 0;
407    if (!wd) return;
408
409    fontbuf = eina_strbuf_new();
410    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
411    if (fontsize == 0) removeflag = 1;  // remove fontsize tag
412
413    if (_stringshare_key_value_replace(&wd->format, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
414      {
415         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
416         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
417      }
418    eina_strbuf_free(fontbuf);
419 }
420
421 static void
422 _ellipsis_label_to_width(Evas_Object *obj)
423 {
424    Widget_Data *wd = elm_widget_data_get(obj);
425    if (!wd) return;
426    int cur_fontsize = 0;
427    char *kvalue;
428    const char *minfont, *deffont, *maxfont;
429    int minfontsize, maxfontsize;
430
431    minfont = edje_object_data_get(wd->lbl, "min_font_size");
432    if (minfont) minfontsize = atoi(minfont);
433    else minfontsize = 1;
434    maxfont = edje_object_data_get(wd->lbl, "max_font_size");
435    if (maxfont) maxfontsize = atoi(maxfont);
436    else maxfontsize = 1;
437    deffont = edje_object_data_get(wd->lbl, "default_font_size");
438    if (deffont) cur_fontsize = atoi(deffont);
439    else cur_fontsize = 1;
440    if (minfontsize > maxfontsize || cur_fontsize == 1) return;  // theme is not ready for ellipsis
441    if (eina_stringshare_strlen(wd->label) <= 0) return;
442
443    if (_get_value_in_key_string(wd->format, "font_size", &kvalue) == 0)
444      {
445         if (kvalue != NULL) cur_fontsize = atoi(kvalue);
446      }
447
448    while (_is_width_over(obj))
449      {
450         if (cur_fontsize > minfontsize)
451           {
452              cur_fontsize -= 3;
453              if (cur_fontsize < minfontsize) cur_fontsize = minfontsize;
454              _ellipsis_fontsize_set(obj, cur_fontsize);
455           }
456         else
457           {
458              break;
459           }
460      }
461 }
462
463 static void
464 _label_sliding_change(Evas_Object *obj)
465 {
466    Widget_Data *wd = elm_widget_data_get(obj);
467    if (!wd) return;
468    char *plaintxt;
469    int plainlen = 0;
470
471    // dosen't support multiline sliding effect
472    if (wd->linewrap)
473      {
474         wd->slidingmode = EINA_FALSE;
475         return;
476      }
477
478    plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
479    if (plaintxt != NULL)
480      {
481         plainlen = strlen(plaintxt);
482         free(plaintxt);
483      }
484    // too short to slide label
485    if (plainlen < 1)
486      {
487         wd->slidingmode = EINA_TRUE;
488         return;
489      }
490
491    if (wd->slidingmode)
492      {
493         Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
494
495         if (wd->ellipsis)
496           {
497              wd->slidingellipsis = EINA_TRUE;
498              elm_label_ellipsis_set(obj, EINA_FALSE);
499           }
500
501         msg->count = 1;
502         msg->val[0] = wd->slide_duration;
503
504         edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
505         edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
506      }
507    else
508      {
509         edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
510         if (wd->slidingellipsis)
511           {
512              wd->slidingellipsis = EINA_FALSE;
513              elm_label_ellipsis_set(obj, EINA_TRUE);
514           }
515      }
516 }
517
518 static void
519 _elm_label_label_set(Evas_Object *obj, const char *item, const char *label)
520 {
521    ELM_CHECK_WIDTYPE(obj, widtype);
522    Widget_Data *wd = elm_widget_data_get(obj);
523    if (!wd) return;
524    if (item && strcmp(item, "default")) return;
525    if (!label) label = "";
526    eina_stringshare_replace(&wd->label, label);
527    edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
528    edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
529    wd->changed = 1;
530    _sizing_eval(obj);
531 }
532
533 static const char *
534 _elm_label_label_get(const Evas_Object *obj, const char *item)
535 {
536    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
537    Widget_Data *wd = elm_widget_data_get(obj);
538    if (item && strcmp(item, "default")) return NULL;
539    if (!wd) return NULL;
540    return wd->label;
541 }
542
543 /**
544  * Add a new label to the parent
545  *
546  * @param parent The parent object
547  * @return The new object or NULL if it cannot be created
548  *
549  * @ingroup Label
550  */
551 EAPI Evas_Object *
552 elm_label_add(Evas_Object *parent)
553 {
554    Evas_Object *obj;
555    Evas *e;
556    Widget_Data *wd;
557
558    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
559
560    ELM_SET_WIDTYPE(widtype, "label");
561    elm_widget_type_set(obj, "label");
562    elm_widget_sub_object_add(parent, obj);
563    elm_widget_data_set(obj, wd);
564    elm_widget_del_hook_set(obj, _del_hook);
565    elm_widget_theme_hook_set(obj, _theme_hook);
566    elm_widget_can_focus_set(obj, EINA_FALSE);
567    elm_widget_text_set_hook_set(obj, _elm_label_label_set);
568    elm_widget_text_get_hook_set(obj, _elm_label_label_get);
569
570    wd->bgcolor = EINA_FALSE;
571    wd->bg = evas_object_rectangle_add(e);
572    evas_object_color_set(wd->bg, 0, 0, 0, 0);
573
574    wd->linewrap = EINA_FALSE;
575    wd->ellipsis = EINA_FALSE;
576    wd->slidingmode = EINA_FALSE;
577    wd->slidingellipsis = EINA_FALSE;
578    wd->wrap_w = -1;
579    wd->wrap_h = -1;
580    wd->slide_duration = 10;
581
582    wd->lbl = edje_object_add(e);
583    _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
584    wd->format = eina_stringshare_add("");
585    wd->label = eina_stringshare_add("<br>");
586    edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
587    edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
588
589    elm_widget_resize_object_set(obj, wd->lbl);
590
591    evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _lbl_resize, obj);
592
593    _mirrored_set(obj, elm_widget_mirrored_get(obj));
594    wd->changed = 1;
595    _sizing_eval(obj);
596    return obj;
597 }
598
599 /**
600  * Set the label on the label object
601  *
602  * @param obj The label object
603  * @param label The label will be used on the label object
604  *
605  * @ingroup Label
606  */
607 EAPI void
608 elm_label_label_set(Evas_Object *obj, const char *label)
609 {
610   _elm_label_label_set(obj, NULL, label);
611 }
612
613 /**
614  * Get the label used on the label object
615  *
616  * @param obj The label object
617  * @return The string inside the label
618  * @ingroup Label
619  * @deprecated
620  */
621 EAPI const char *
622 elm_label_label_get(const Evas_Object *obj)
623 {
624   return _elm_label_label_get(obj, NULL);
625 }
626
627 /**
628  * Set the wrapping behavior of the label
629  *
630  * @param obj The label object
631  * @param wrap To wrap text or not
632  * @ingroup Label
633  * @deprecated
634  */
635 EAPI void
636 elm_label_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
637 {
638    ELM_CHECK_WIDTYPE(obj, widtype);
639    Widget_Data *wd = elm_widget_data_get(obj);
640    const char *wrap_str;
641    int len;
642
643    if (!wd) return;
644    if (wd->linewrap == wrap) return;
645    wd->linewrap = wrap;
646    len = strlen(wd->label);
647    if (len <= 0) return;
648
649    switch (wrap)
650      {
651       case ELM_WRAP_CHAR:
652          wrap_str = "char";
653          break;
654       case ELM_WRAP_WORD:
655          wrap_str = "word";
656          break;
657       case ELM_WRAP_MIXED:
658          wrap_str = "mixed";
659          break;
660       default:
661          wrap_str = "none";
662          break;
663      }
664
665    if (_stringshare_key_value_replace(&wd->format,
666             "wrap", wrap_str, 0) == 0)
667      {
668         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
669         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
670         wd->changed = 1;
671         _sizing_eval(obj);
672      }
673 }
674
675 /**
676  * Get the wrapping behavior of the label
677  *
678  * @param obj The label object
679  * @return Wrap type
680  * @ingroup Label
681  */
682 EAPI Elm_Wrap_Type
683 elm_label_line_wrap_get(const Evas_Object *obj)
684 {
685    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
686    Widget_Data *wd = elm_widget_data_get(obj);
687    if (!wd) return EINA_FALSE;
688    return wd->linewrap;
689 }
690
691 /**
692  * Set wrap width of the label
693  *
694  * @param obj The label object
695  * @param w The wrap width in pixels at a minimum where words need to wrap
696  * @ingroup Label
697  */
698 EAPI void
699 elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
700 {
701    ELM_CHECK_WIDTYPE(obj, widtype);
702    Widget_Data *wd = elm_widget_data_get(obj);
703    if (!wd) return;
704    if (w < 0) w = 0;
705    if (wd->wrap_w == w) return;
706    if (wd->ellipsis)
707      {
708         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
709         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
710      }
711    wd->wrap_w = w;
712    _sizing_eval(obj);
713 }
714
715 /**
716  * get wrap width of the label
717  *
718  * @param obj The label object
719  * @return The wrap width in pixels at a minimum where words need to wrap
720  * @ingroup Label
721  */
722 EAPI Evas_Coord
723 elm_label_wrap_width_get(const Evas_Object *obj)
724 {
725    ELM_CHECK_WIDTYPE(obj, widtype) 0;
726    Widget_Data *wd = elm_widget_data_get(obj);
727    if (!wd) return 0;
728    return wd->wrap_w;
729 }
730
731 /**
732  * Set wrap height of the label
733  *
734  * @param obj The label object
735  * @param w The wrap width in pixels at a minimum where words need to wrap
736  * @ingroup Label
737  */
738 EAPI void
739 elm_label_wrap_height_set(Evas_Object *obj,
740                           Evas_Coord   h)
741 {
742    ELM_CHECK_WIDTYPE(obj, widtype);
743    Widget_Data *wd = elm_widget_data_get(obj);
744    if (!wd) return;
745    if (h < 0) h = 0;
746    if (wd->wrap_h == h) return;
747    if (wd->ellipsis)
748      {
749         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
750         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
751      }
752    wd->wrap_h = h;
753    _sizing_eval(obj);
754 }
755
756 /**
757  * get wrap width of the label
758  *
759  * @param obj The label object
760  * @return The wrap height in pixels at a minimum where words need to wrap
761  * @ingroup Label
762  */
763 EAPI Evas_Coord
764 elm_label_wrap_height_get(const Evas_Object *obj)
765 {
766    ELM_CHECK_WIDTYPE(obj, widtype) 0;
767    Widget_Data *wd = elm_widget_data_get(obj);
768    if (!wd) return 0;
769    return wd->wrap_h;
770 }
771
772 /**
773  * Set the font size on the label object.
774  *
775  * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
776  * "big", "medium", "small" - or better name them by use:
777  * "title", "footnote", "quote" etc.
778  *
779  * @param obj The label object
780  * @param size font size
781  *
782  * @ingroup Label
783  */
784 EAPI void
785 elm_label_fontsize_set(Evas_Object *obj, int fontsize)
786 {
787    ELM_CHECK_WIDTYPE(obj, widtype);
788    Widget_Data *wd = elm_widget_data_get(obj);
789    Eina_Strbuf *fontbuf = NULL;
790    int len, removeflag = 0;
791
792    if (!wd) return;
793    _elm_dangerous_call_check(__FUNCTION__);
794    len = strlen(wd->label);
795    if (len <= 0) return;
796    fontbuf = eina_strbuf_new();
797    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
798
799    if (fontsize == 0) removeflag = 1;  // remove fontsize tag
800
801    if (_stringshare_key_value_replace(&wd->format, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
802      {
803         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
804         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
805         wd->changed = 1;
806         _sizing_eval(obj);
807      }
808    eina_strbuf_free(fontbuf);
809 }
810
811 /**
812  * Set the text align on the label object
813  *
814  * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
815  * "big", "medium", "small" - or better name them by use:
816  * "title", "footnote", "quote" etc.
817  *
818  * @param obj The label object
819  * @param align align mode ("left", "center", "right")
820  *
821  * @ingroup Label
822  */
823 EAPI void
824 elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
825 {
826    ELM_CHECK_WIDTYPE(obj, widtype);
827    Widget_Data *wd = elm_widget_data_get(obj);
828    int len;
829
830    if (!wd) return;
831    _elm_dangerous_call_check(__FUNCTION__);
832    len = strlen(wd->label);
833    if (len <= 0) return;
834
835    if (_stringshare_key_value_replace(&wd->format, "align", alignmode, 0) == 0)
836      {
837         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
838         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
839      }
840
841    wd->changed = 1;
842    _sizing_eval(obj);
843 }
844
845 /**
846  * Set the text color on the label object
847  *
848  * @param obj The label object
849  * @param r Red property background color of The label object
850  * @param g Green property background color of The label object
851  * @param b Blue property background color of The label object
852  * @param a Alpha property background color of The label object
853  *
854  * @ingroup Label
855  */
856 EAPI void
857 elm_label_text_color_set(Evas_Object *obj,
858                          unsigned int r,
859                          unsigned int g,
860                          unsigned int b,
861                          unsigned int a)
862 {
863    ELM_CHECK_WIDTYPE(obj, widtype);
864    Widget_Data *wd = elm_widget_data_get(obj);
865    Eina_Strbuf *colorbuf = NULL;
866    int len;
867
868    if (!wd) return;
869    _elm_dangerous_call_check(__FUNCTION__);
870    len = strlen(wd->label);
871    if (len <= 0) return;
872    colorbuf = eina_strbuf_new();
873    eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
874
875    if (_stringshare_key_value_replace(&wd->format, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
876      {
877         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
878         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
879         wd->changed = 1;
880         _sizing_eval(obj);
881      }
882    eina_strbuf_free(colorbuf);
883 }
884
885 /**
886  * Set background color of the label
887  *
888  * NEVER use this. It is for hyper-special cases only. use styles instead. e.g.
889  * "big", "medium", "small" - or better name them by use:
890  * "title", "footnote", "quote" etc.
891  *
892  * @param obj The label object
893  * @param r Red property background color of The label object
894  * @param g Green property background color of The label object
895  * @param b Blue property background color of The label object
896  * @param a Alpha property background alpha of The label object
897  *
898  * @ingroup Label
899  */
900 EAPI void
901 elm_label_background_color_set(Evas_Object *obj,
902                                unsigned int r,
903                                unsigned int g,
904                                unsigned int b,
905                                unsigned int a)
906 {
907    ELM_CHECK_WIDTYPE(obj, widtype);
908    Widget_Data *wd = elm_widget_data_get(obj);
909    if (!wd) return;
910    evas_object_color_set(wd->bg, r, g, b, a);
911
912    if (!wd) return;
913    _elm_dangerous_call_check(__FUNCTION__);
914    if (wd->bgcolor == EINA_FALSE)
915      {
916         wd->bgcolor = 1;
917         edje_object_part_swallow(wd->lbl, "label.swallow.background", wd->bg);
918      }
919 }
920
921 /**
922  * Set the wrapmode of the label
923  *
924  * @param obj The label object
925  * @param wrapmode 0 is charwrap, 1 is wordwrap
926  * @ingroup Label
927  * @deprecated 
928 */
929 EAPI void
930 elm_label_wrap_mode_set(Evas_Object *obj,
931                         Eina_Bool    wrapmode)
932 {
933    return;
934 }
935
936 /**
937  * Set the ellipsis behavior of the label
938  *
939  * @param obj The label object
940  * @param ellipsis To ellipsis text or not
941  * @ingroup Label
942  */
943 EAPI void
944 elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
945 {
946    ELM_CHECK_WIDTYPE(obj, widtype);
947    Widget_Data *wd = elm_widget_data_get(obj);
948    Eina_Strbuf *fontbuf = NULL;
949    int len, removeflag = 0;
950
951    if (!wd) return;
952    if (wd->ellipsis == ellipsis) return;
953    wd->ellipsis = ellipsis;
954    len = strlen(wd->label);
955    if (len <= 0) return;
956
957    if (ellipsis == EINA_FALSE) removeflag = 1;  // remove fontsize tag
958
959    fontbuf = eina_strbuf_new();
960    eina_strbuf_append_printf(fontbuf, "%f", 1.0);
961
962    if (_stringshare_key_value_replace(&wd->format,
963             "ellipsis", eina_strbuf_string_get(fontbuf), removeflag) == 0)
964      {
965         edje_object_part_text_set(wd->lbl, "elm.text", wd->format);
966         edje_object_part_text_append(wd->lbl, "elm.text", wd->label);
967         wd->changed = 1;
968         _sizing_eval(obj);
969      }
970    eina_strbuf_free(fontbuf);
971
972 }
973
974 /**
975  * Set the text slide of the label
976  *
977  * @param obj The label object
978  * @param slide To start slide or stop
979  * @ingroup Label
980  */
981 EAPI void
982 elm_label_slide_set(Evas_Object *obj,
983                     Eina_Bool    slide)
984 {
985    ELM_CHECK_WIDTYPE(obj, widtype);
986    Widget_Data *wd = elm_widget_data_get(obj);
987    if (!wd) return;
988
989    if (wd->slidingmode == slide) return;
990    wd->slidingmode = slide;
991    _label_sliding_change(obj);
992    wd->changed = 1;
993    _sizing_eval(obj);
994 }
995
996 /**
997  * get the text slide mode of the label
998  *
999  * @param obj The label object
1000  * @return slide slide mode value
1001  * @ingroup Label
1002  */
1003 EAPI Eina_Bool
1004 elm_label_slide_get(Evas_Object *obj)
1005 {
1006    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1007    Widget_Data *wd = elm_widget_data_get(obj);
1008    if (!wd) return EINA_FALSE;
1009    return wd->slidingmode;
1010 }
1011
1012 /**
1013  * set the slide duration(speed) of the label
1014  *
1015  * @param obj The label object
1016  * @return The duration time in moving text from slide begin position to slide end position
1017  * @ingroup Label
1018  */
1019 EAPI void
1020 elm_label_slide_duration_set(Evas_Object *obj, double duration)
1021 {
1022    ELM_CHECK_WIDTYPE(obj, widtype);
1023    Widget_Data *wd = elm_widget_data_get(obj);
1024    Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
1025
1026    if (!wd) return;
1027    wd->slide_duration = duration;
1028    msg->count = 1;
1029    msg->val[0] = wd->slide_duration;
1030    edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
1031 }
1032
1033 /**
1034  * get the slide duration(speed) of the label
1035  *
1036  * @param obj The label object
1037  * @return The duration time in moving text from slide begin position to slide end position
1038  * @ingroup Label
1039  */
1040 EAPI double
1041 elm_label_slide_duration_get(Evas_Object *obj)
1042 {
1043    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1044    Widget_Data *wd = elm_widget_data_get(obj);
1045    if (!wd) return 0;
1046    return wd->slide_duration;
1047 }
1048