[label] change some comments
[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 slidingmode : 1;
26    Eina_Bool slidingellipsis : 1;
27    Eina_Bool changed : 1;
28    Eina_Bool bgcolor : 1;
29    Eina_Bool ellipsis : 1;
30    int slide_duration;
31 };
32
33 static const char *widtype = NULL;
34 static void _del_hook(Evas_Object *obj);
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, char *key, char **value);
38 static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag);
39 static int _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag);
40 static int _is_width_over(Evas_Object *obj, int linemode);
41 static void _ellipsis_label_to_width(Evas_Object *obj, int linemode);
42
43 static void
44 _elm_win_recalc_job(void *data)
45 {
46    Widget_Data *wd = elm_widget_data_get(data);
47    Evas_Coord minw = -1, minh = -1, maxh = -1;
48    Evas_Coord resw, resh, minminw, minminh;
49    if (!wd) return;
50    wd->deferred_recalc_job = NULL;
51    evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
52    resh = 0;
53    minminw = 0;
54    edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, 0, 0);
55    minminw = minw;
56    minminh = minh;
57    if (wd->wrap_w >= resw) 
58      {
59         resw = wd->wrap_w;
60         edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
61         evas_object_size_hint_min_set(data, minw, minh);
62      }
63    else
64      {
65         if (wd->wrap_w > minminw) minminw = wd->wrap_w;
66         edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
67         evas_object_size_hint_min_set(data, minminw, minh);
68      }
69
70    if (wd->ellipsis && wd->linewrap && wd->wrap_h > 0 && _is_width_over(data, 1) == 1) 
71      _ellipsis_label_to_width(data, 1);
72
73    maxh = minh;
74    evas_object_size_hint_max_set(data, -1, maxh);
75 }
76
77 static void
78 _del_hook(Evas_Object *obj)
79 {
80    Widget_Data *wd = elm_widget_data_get(obj);
81    if (!wd) return;
82    if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
83    if (wd->label) eina_stringshare_del(wd->label);
84    if (wd->bg) evas_object_del(wd->bg);
85    free(wd);
86 }
87
88 static void
89 _theme_change(Evas_Object *obj)
90 {
91    Widget_Data *wd = elm_widget_data_get(obj);
92    if (!wd) return;
93
94    if (wd->linewrap)
95      {
96        if (wd->ellipsis)
97          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap_ellipsis", elm_widget_style_get(obj));
98        else
99          _elm_theme_object_set(obj, wd->lbl, "label", "base_wrap", elm_widget_style_get(obj));
100      }
101    else
102      _elm_theme_object_set(obj, wd->lbl, "label", "base", elm_widget_style_get(obj));
103
104 }
105
106 static void
107 _theme_hook(Evas_Object *obj)
108 {
109    Widget_Data *wd = elm_widget_data_get(obj);
110    if (!wd) return;
111    _theme_change(obj);
112    edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
113    edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) * 
114                          _elm_config->scale);
115    _sizing_eval(obj);
116 }
117
118 static void
119 _sizing_eval(Evas_Object *obj)
120 {
121    Widget_Data *wd = elm_widget_data_get(obj);
122    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
123    Evas_Coord resw, resh;
124    if (!wd) return;
125    if (wd->linewrap)
126      {
127         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
128         if ((resw == wd->lastw) && (!wd->changed)) return;
129         wd->changed = EINA_FALSE;
130         wd->lastw = resw;
131         _elm_win_recalc_job(obj);
132 // FIXME: works ok. but NOT for genlist. what should genlist do?        
133 //        if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
134 //        wd->deferred_recalc_job = ecore_job_add(_elm_win_recalc_job, obj);
135      }
136    else
137      {
138         evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
139         edje_object_size_min_calc(wd->lbl, &minw, &minh);
140                 if (wd->wrap_w > 0 && minw > wd->wrap_w)
141                         minw = wd->wrap_w;
142         evas_object_size_hint_min_set(obj, minw, minh);
143         maxh = minh;
144         evas_object_size_hint_max_set(obj, maxw, maxh);
145
146         if (wd->ellipsis && _is_width_over(obj, 0) == 1) 
147           _ellipsis_label_to_width(obj, 0);
148      }
149 }
150
151 static void 
152 _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, 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         starttag = curlocater;
169         endtag = curlocater + strlen(key);
170         if (endtag == NULL || *endtag != '=') 
171           {
172             foundflag = 0;
173             return -1;
174           }
175
176         firstindex = abs(oldstring - curlocater);
177         firstindex += strlen(key)+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 == NULL) break;
192           }
193
194         while (NULL != endtag)
195           {
196             if (*endtag == '<')
197               {
198                 foundflag = 0;
199                 break;
200               }
201             if (*endtag == '>') 
202               break;
203             else 
204               endtag++;
205             if (endtag == NULL) break;
206           }
207
208         if (foundflag != 0 && *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 static int
224 _strbuf_key_value_replace(Eina_Strbuf *srcbuf, char *key, const char *value, int deleteflag)
225 {
226    const char *srcstring = NULL;
227    Eina_Strbuf *repbuf = NULL, *diffbuf = NULL;
228    char *curlocater, *replocater;
229    char *starttag, *endtag;
230    int tagtxtlen = 0, insertflag = 0;
231
232    srcstring = eina_strbuf_string_get(srcbuf);
233    curlocater = strstr(srcstring, key);
234
235    if (curlocater == NULL)
236      {
237        insertflag = 1;
238      }
239    else
240      {
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 != NULL && endtag+1 != NULL)
249              srcstring = endtag+1;
250            else
251              break;
252          } while (strlen(srcstring) > 1);
253
254        if (starttag && endtag && tagtxtlen > strlen(key))
255          {
256            repbuf = eina_strbuf_new();
257            diffbuf = eina_strbuf_new();
258            eina_strbuf_append_n(repbuf, starttag, tagtxtlen);
259            srcstring = eina_strbuf_string_get(repbuf);
260            curlocater = strstr(srcstring, key);
261
262            if (curlocater != NULL)
263              {
264                replocater = curlocater + strlen(key) + 1;
265
266                while (*replocater == ' ' || *replocater == '=')
267                            {
268                  replocater++;
269                            }
270
271                 while (*replocater != NULL && *replocater != ' ' && *replocater != '>')
272                   replocater++;
273
274                if (replocater-curlocater > strlen(key)+1)
275                  {
276                    replocater--;
277                    eina_strbuf_append_n(diffbuf, curlocater, replocater-curlocater+1);
278                  }
279                else
280                  insertflag = 1;
281              }
282            else
283              {
284                insertflag = 1;
285              }
286            eina_strbuf_reset(repbuf);
287          }
288        else
289          {
290            insertflag = 1; 
291          }
292      }
293
294    if (repbuf == NULL) repbuf = eina_strbuf_new();
295    if (diffbuf == NULL) diffbuf = eina_strbuf_new();
296
297    if (insertflag)
298      {
299        eina_strbuf_append_printf(repbuf, "<%s=%s>", key, value);
300        eina_strbuf_prepend(srcbuf, eina_strbuf_string_get(repbuf));
301      }
302    else
303      {
304         if (deleteflag)
305           {
306             eina_strbuf_prepend(diffbuf, "<");
307             eina_strbuf_append(diffbuf, ">");
308             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), "");
309           }
310         else
311           {
312             eina_strbuf_append_printf(repbuf, "%s=%s", key, value);
313             eina_strbuf_replace_first(srcbuf, eina_strbuf_string_get(diffbuf), eina_strbuf_string_get(repbuf));
314           }
315      }
316
317    if (repbuf) eina_strbuf_free(repbuf);
318    if (diffbuf) eina_strbuf_free(diffbuf);
319   
320    return 0;           
321 }
322
323 static int
324 _stringshare_key_value_replace(const char **srcstring, char *key, const char *value, int deleteflag)
325 {
326    Eina_Strbuf *sharebuf = NULL;   
327    
328    sharebuf = eina_strbuf_new();
329    eina_strbuf_append(sharebuf, *srcstring);
330    _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
331    eina_stringshare_del(*srcstring);
332    *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
333    eina_strbuf_free(sharebuf);
334
335    return 0;
336 }
337
338 static int
339 _is_width_over(Evas_Object *obj, int linemode)
340 {
341    Evas_Coord x, y, w, h;
342    Evas_Coord vx, vy, vw, vh;
343    Widget_Data *wd = elm_widget_data_get(obj);
344    const char *ellipsis_string = "...";
345    size_t ellen = strlen(ellipsis_string)+1;
346
347    if (!wd) return 0;
348
349    // too short to ellipsis
350    if (strlen(edje_object_part_text_get(wd->lbl, "elm.text")) <= ellen)
351            return 0;
352
353    edje_object_part_geometry_get(wd->lbl,"elm.text",&x,&y,&w,&h);
354
355    evas_object_geometry_get (obj, &vx,&vy,&vw,&vh);
356
357    /*
358    fprintf(stderr, "## _is_width_over\n");
359    fprintf(stderr, "## x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
360    fprintf(stderr, "## vx = %d, vy = %d, vw = %d, vh = %d\n", vx, vy, vw, vh);
361    if (linemode)
362            fprintf(stderr, "## wd->wrap_w = %d, wd->wrap_h = %d\n", wd->wrap_w, wd->wrap_h);
363    else
364            fprintf(stderr, "## wd->wrap_w = %d\n", wd->wrap_w);
365    */
366
367    if (linemode == 0) // single line
368      {
369        // skip if too early to check widget size
370        if (w < 0 && h < 0)
371          return 0;
372        // if string fits at widget
373        if ((x >= 0) && (y >= 0))
374            {
375                    if ((wd->wrap_w > 0) && (wd->wrap_w < w))
376                    {
377                            Evas_Coord minw, minh;
378                            edje_object_size_min_calc(wd->lbl, &minw, &minh);
379
380                            if (minw < wd->wrap_w)
381                            { // min insufficient
382                                    return 0;
383                            }
384                            else
385                                    return 1;
386                    }
387                    else
388                            return 0;
389            }
390
391        if (ellen < wd->wrap_w && w > wd->wrap_w) return 1;
392      }
393    else // multiline
394      {
395 //       if (vy > h && h > wd->wrap_h) return 1;
396                  if ((x >= 0 || y >= 0) && h > wd->wrap_h) return 1;
397      }
398
399    return 0;
400 }
401
402 static void
403 _ellipsis_fontsize_set(Evas_Object *obj, int fontsize, Eina_Strbuf *txtbuf)
404 {
405    Widget_Data *wd = elm_widget_data_get(obj);
406    if (!wd) return;
407
408    Eina_Strbuf *fontbuf = NULL;
409    fontbuf = eina_strbuf_new();
410    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
411    _strbuf_key_value_replace(txtbuf, "font_size", eina_strbuf_string_get(fontbuf), 0);
412    edje_object_part_text_set(wd->lbl, "elm.text", eina_strbuf_string_get(txtbuf));
413    eina_strbuf_free(fontbuf);
414 }
415
416 static Eina_Bool
417 _ellipsis_cut_chars_to_widget(Evas_Object *obj, int fontsize, int linemode)
418 {
419    Widget_Data *wd = elm_widget_data_get(obj);
420    if (!wd) return EINA_FALSE;
421
422    const char *ellipsis_string = "...";
423    int minshowcount = strlen(ellipsis_string);
424    Evas_Coord w, h;
425    Evas_Textblock_Cursor *tc1, *tc2;
426    char *cutstr, *elstr;
427    int limitw = 0;
428    int lencutstr = 0;
429    int i = 0;
430
431    edje_object_part_geometry_get(wd->lbl,"elm.text",NULL,NULL,&w,&h);
432    if (w <= 0)
433            return EINA_FALSE;
434    tc1 = evas_object_textblock_cursor_new(edje_object_part_object_get(wd->lbl, "elm.text"));
435    tc2 = evas_object_textblock_cursor_new(edje_object_part_object_get(wd->lbl, "elm.text"));
436    
437    if (wd->wrap_w > 0 && wd->wrap_w < w)
438            limitw = wd->wrap_w;
439    else
440            limitw = w;
441    evas_textblock_cursor_pos_set(tc1, 0);
442    evas_textblock_cursor_char_coord_set(tc2, limitw, 0);
443    for (i = 0; i <= minshowcount; i++)
444            evas_textblock_cursor_char_prev(tc2);
445    cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
446
447    // FIXME: consider other unicode encoding, currently only care about utf-8
448    lencutstr = strlen(cutstr);
449    elstr = malloc(sizeof(char)*(lencutstr+minshowcount+1));
450    strcpy(elstr, cutstr);
451    strcat(elstr, ellipsis_string);
452
453    edje_object_part_text_set(wd->lbl, "elm.text", elstr);
454
455    free(elstr);
456    evas_textblock_cursor_free(tc1);
457    evas_textblock_cursor_free(tc2);
458         
459    return EINA_TRUE;
460 }
461
462 static Eina_Bool
463 _ellipsis_cut_lines_to_widget(Evas_Object *obj, int fontsize, int linemode)
464 {
465    Widget_Data *wd = elm_widget_data_get(obj);
466    if (!wd) return EINA_FALSE;
467
468    const char *ellipsis_string = "...";
469    int minshowcount = strlen(ellipsis_string);
470    Evas_Coord w, h;
471    Evas_Textblock_Cursor *tc1, *tc2;
472    int linenum = 0, cutline = 0;
473    double lineheight = 0.0;
474    char *cutstr, *elstr;
475    int lencutstr = 0;
476    int limith = 0;
477    int i;
478
479    edje_object_part_geometry_get(wd->lbl,"elm.text", NULL, NULL, &w, &h);
480
481    tc1 = evas_object_textblock_cursor_new(edje_object_part_object_get(wd->lbl, "elm.text"));
482    tc2 = evas_object_textblock_cursor_new(edje_object_part_object_get(wd->lbl, "elm.text"));
483    // goto last paragraph
484    while (evas_textblock_cursor_paragraph_next(tc2) == EINA_TRUE)
485            ;
486    evas_textblock_cursor_paragraph_last(tc2);
487    // get total linenumber
488    linenum = evas_textblock_cursor_line_geometry_get(tc2, NULL, NULL, NULL, NULL);
489    lineheight = h/linenum * 1.0;
490    if (wd->wrap_h > 0 && wd->wrap_h < h)
491            limith = wd->wrap_h;
492    else
493            limith = h;
494    cutline = limith / lineheight;
495    if (cutline < 1)
496            cutline = 1;
497
498    evas_textblock_cursor_pos_set(tc1, 0);
499    evas_textblock_cursor_line_set(tc2, cutline-1);
500    evas_textblock_cursor_line_char_last(tc2);
501    for (i = 0; i <= minshowcount; i++)
502            evas_textblock_cursor_char_prev(tc2);
503    cutstr = evas_textblock_cursor_range_text_get(tc1, tc2, EVAS_TEXTBLOCK_TEXT_PLAIN);
504
505    // FIXME: consider other unicode encoding, currently only care about utf-8
506    lencutstr = strlen(cutstr);
507    elstr = malloc(sizeof(char)*(lencutstr+minshowcount+1));
508    strcpy(elstr, cutstr);
509    strcat(elstr, ellipsis_string);
510
511    edje_object_part_text_set(wd->lbl, "elm.text", elstr);
512
513    free(elstr);
514    evas_textblock_cursor_free(tc1);
515    evas_textblock_cursor_free(tc2);
516
517    return EINA_TRUE;
518 }
519
520 static void
521 _ellipsis_label_to_width(Evas_Object *obj, int linemode)
522 {
523    Widget_Data *wd = elm_widget_data_get(obj);
524    if (!wd) return;
525
526    int cur_fontsize = 0;
527    Eina_Strbuf *txtbuf = NULL;
528    char **kvalue = NULL;
529    const char *minfont, *deffont, *maxfont;
530    int minfontsize, maxfontsize;
531
532    minfont = edje_object_data_get(wd->lbl, "min_font_size");
533    if (minfont) minfontsize = atoi(minfont);
534    else minfontsize = 1;
535    maxfont = edje_object_data_get(wd->lbl, "max_font_size");
536    if (maxfont) maxfontsize = atoi(maxfont);
537    else maxfontsize = 1;
538    deffont = edje_object_data_get(wd->lbl, "default_font_size");
539    if (deffont) cur_fontsize = atoi(deffont);
540    else cur_fontsize = 1;
541    if (minfontsize > maxfontsize || cur_fontsize == 1) return; // theme is not ready for ellipsis
542    if (eina_stringshare_strlen(wd->label) <= 0) return;
543
544    if (_get_value_in_key_string(wd->label, "font_size", &kvalue) == 0)
545      {
546        if (*kvalue != NULL) cur_fontsize = atoi((char*)kvalue);
547      }
548
549    txtbuf = eina_strbuf_new();
550    eina_strbuf_append(txtbuf, wd->label);
551
552    while (_is_width_over(obj, linemode))
553      {
554        if (cur_fontsize > minfontsize)
555          {
556            cur_fontsize -= 3;
557                    if (cur_fontsize < minfontsize)
558              cur_fontsize = minfontsize;
559                    _ellipsis_fontsize_set(obj, cur_fontsize, txtbuf);
560          }
561        else
562          {
563            if (linemode == 0) // single line
564              {
565                _ellipsis_cut_chars_to_widget(obj, cur_fontsize, linemode);
566                            break;
567                          }
568            else // multiline
569              {
570                _ellipsis_cut_lines_to_widget(obj, cur_fontsize, linemode);
571                            break;
572                          }
573          }
574      }
575
576    if (txtbuf) eina_strbuf_free(txtbuf);
577    wd->changed = 1;
578    _sizing_eval(obj);
579 }
580
581 /*
582  * setting internal state of mulitline entry
583  * singleline doesn't need it
584  */
585
586 void _label_state_change(Evas_Object *obj)
587 {
588    Widget_Data *wd = elm_widget_data_get(obj);
589    if (!wd) return;
590
591    if (wd->linewrap)
592    {
593            if (wd->wrapmode)
594                    edje_object_signal_emit(wd->lbl, "elm,state,wordwrap", "elm");
595            else
596                    edje_object_signal_emit(wd->lbl, "elm,state,default", "elm");
597    }
598 }
599
600 void _label_sliding_change(Evas_Object *obj)
601 {
602    Widget_Data *wd = elm_widget_data_get(obj);
603    if (!wd) return;
604
605    if (wd->linewrap)
606    {
607            wd->slidingmode = EINA_FALSE;
608            fprintf(stderr, "ERR: elm_label dosen't support multiline sliding effect!!!\n");
609            fprintf(stderr, "ERR: elm_label dosen't support multiline sliding effect!!!\n");
610            fprintf(stderr, "ERR: elm_label dosen't support multiline sliding effect!!!\n");
611    }
612
613    if (wd->slidingmode)
614    {
615            if (wd->ellipsis)
616            {
617                    wd->slidingellipsis = EINA_TRUE;
618                    elm_label_ellipsis_set(obj, EINA_FALSE);
619            }
620            Edje_Message_Int_Set *msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
621            
622            msg->count=1;
623            msg->val[0] = (int)wd->slide_duration;
624
625            edje_object_message_send(wd->lbl, EDJE_MESSAGE_INT_SET, 0, msg);
626            edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
627    }
628    else
629    {
630            edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
631            if (wd->slidingellipsis)
632            {
633                    wd->slidingellipsis = EINA_FALSE;
634                    elm_label_ellipsis_set(obj, EINA_TRUE);
635            }
636    }
637 }
638
639 /**
640  * Add a new label to the parent
641  *
642  * @param parent The parent object
643  * @return The new object or NULL if it cannot be created
644  *
645  * @ingroup Label
646  */
647 EAPI Evas_Object *
648 elm_label_add(Evas_Object *parent)
649 {
650    Evas_Object *obj;
651    Evas *e;
652    Widget_Data *wd;
653
654    wd = ELM_NEW(Widget_Data);
655    e = evas_object_evas_get(parent);
656    wd->bg = evas_object_rectangle_add(e);
657    evas_object_color_set(wd->bg, 0, 0, 0, 0);
658    obj = elm_widget_add(e);
659    ELM_SET_WIDTYPE(widtype, "label");
660    elm_widget_type_set(obj, "label");
661    elm_widget_sub_object_add(parent, obj);
662    elm_widget_data_set(obj, wd);
663    elm_widget_del_hook_set(obj, _del_hook);
664    elm_widget_theme_hook_set(obj, _theme_hook);
665    elm_widget_can_focus_set(obj, 0);
666
667    wd->linewrap = EINA_FALSE;
668    wd->bgcolor = EINA_FALSE;
669    wd->ellipsis = EINA_FALSE;
670    wd->wrapmode = EINA_FALSE;
671    wd->slidingmode = EINA_FALSE;
672    wd->slidingellipsis = EINA_FALSE;
673    wd->wrap_w = 0;
674    wd->wrap_h = 0;
675    wd->slide_duration = 10;
676
677    wd->lbl = edje_object_add(e);
678    _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
679    wd->label = eina_stringshare_add("<br>");
680    edje_object_part_text_set(wd->lbl, "elm.text", "<br>");
681    elm_widget_resize_object_set(obj, wd->lbl);
682    
683    evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _resize, obj);
684    
685    wd->changed = 1;
686    _sizing_eval(obj);
687    return obj;
688 }
689
690 /**
691  * Set the label on the label object
692  *
693  * @param obj The label object
694  * @param label The label will be used on the label object
695  *
696  * @ingroup Label
697  */
698 EAPI void
699 elm_label_label_set(Evas_Object *obj, const char *label)
700 {
701    ELM_CHECK_WIDTYPE(obj, widtype);
702    Widget_Data *wd = elm_widget_data_get(obj);
703    if (!wd) return;
704    if (!label) label = "";
705    eina_stringshare_replace(&wd->label, label);
706    edje_object_part_text_set(wd->lbl, "elm.text", label);
707    wd->changed = 1;
708    _sizing_eval(obj);
709 }
710
711 /**
712  * Get the label used on the label object
713  *
714  * @param obj The label object
715  * @return The string inside the label
716  * @ingroup Label
717  */
718 EAPI const char *
719 elm_label_label_get(const Evas_Object *obj)
720 {
721    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
722    Widget_Data *wd = elm_widget_data_get(obj);
723    if (!wd) return NULL;
724    return wd->label;
725 }
726
727 /**
728  * Set the wrapping behavior of the label
729  *
730  * @param obj The label object
731  * @param wrap To wrap text or not
732  * @ingroup Label
733  */
734 EAPI void
735 elm_label_line_wrap_set(Evas_Object *obj, Eina_Bool wrap)
736 {
737    ELM_CHECK_WIDTYPE(obj, widtype);
738    Widget_Data *wd = elm_widget_data_get(obj);
739    if (!wd) return;
740    const char *t;
741    if (wd->linewrap == wrap) return;
742    wd->linewrap = wrap;
743    t = eina_stringshare_add(elm_label_label_get(obj));
744    _theme_change(obj);
745    elm_label_label_set(obj, t);
746    eina_stringshare_del(t);
747    wd->changed = 1;
748    _sizing_eval(obj);
749 }
750
751 /**
752  * Get the wrapping behavior of the label
753  *
754  * @param obj The label object
755  * @return To wrap text or not
756  * @ingroup Label
757  */
758 EAPI Eina_Bool
759 elm_label_line_wrap_get(const Evas_Object *obj)
760 {
761    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
762    Widget_Data *wd = elm_widget_data_get(obj);
763    if (!wd) return EINA_FALSE;
764    return wd->linewrap;
765 }
766
767 /**
768  * Set wrap width of the label
769  *
770  * @param obj The label object
771  * @param w The wrap width in pixels at a minimum where words need to wrap
772  * @ingroup Label
773  */
774 EAPI void
775 elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
776 {
777    ELM_CHECK_WIDTYPE(obj, widtype);
778    Widget_Data *wd = elm_widget_data_get(obj);
779    if (!wd) return;
780    if (w < 0) w = 0;
781    if (wd->wrap_w == w) return;
782    if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
783    wd->wrap_w = w;
784    _sizing_eval(obj);
785 }
786
787 /**
788  * get wrap width of the label
789  *
790  * @param obj The label object
791  * @return The wrap width in pixels at a minimum where words need to wrap
792  * @ingroup Label
793  */
794 EAPI Evas_Coord
795 elm_label_wrap_width_get(const Evas_Object *obj)
796 {
797    ELM_CHECK_WIDTYPE(obj, widtype) 0;
798    Widget_Data *wd = elm_widget_data_get(obj);
799    if (!wd) return 0;
800    return wd->wrap_w;
801 }
802
803 /**
804  * Set wrap height of the label
805  *
806  * @param obj The label object
807  * @param w The wrap width in pixels at a minimum where words need to wrap
808  * @ingroup Label
809  */
810 EAPI void
811 elm_label_wrap_height_set(Evas_Object *obj, Evas_Coord h)
812 {
813    ELM_CHECK_WIDTYPE(obj, widtype);
814    Widget_Data *wd = elm_widget_data_get(obj);
815    if (!wd) return;
816    if (h < 0) h = 0;
817    if (wd->wrap_h == h) return;
818    if (wd->ellipsis) edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
819    wd->wrap_h = h;
820    _sizing_eval(obj);
821 }
822
823 /**
824  * get wrap width of the label
825  *
826  * @param obj The label object
827  * @return The wrap height in pixels at a minimum where words need to wrap
828  * @ingroup Label
829  */
830 EAPI Evas_Coord
831 elm_label_wrap_height_get(const Evas_Object *obj)
832 {
833    ELM_CHECK_WIDTYPE(obj, widtype) 0;
834    Widget_Data *wd = elm_widget_data_get(obj);
835    if (!wd) return 0;
836    return wd->wrap_h;
837 }
838
839 /**
840  * Set the font size on the label object
841  *
842  * @param obj The label object
843  * @param size font size
844  *
845  * @ingroup Label
846  */
847 EAPI void
848 elm_label_fontsize_set(Evas_Object *obj, int fontsize)
849 {
850    ELM_CHECK_WIDTYPE(obj, widtype);
851    Widget_Data *wd = elm_widget_data_get(obj);
852    Eina_Strbuf *fontbuf = NULL;
853    int len, removeflag = 0;
854
855    if (!wd) return;
856    len = strlen(wd->label);
857    if (len <= 0) return;
858    fontbuf = eina_strbuf_new();
859    eina_strbuf_append_printf(fontbuf, "%d", fontsize);
860
861    if (fontsize == 0) removeflag = 1; // remove fontsize tag
862
863    if (_stringshare_key_value_replace(&wd->label, "font_size", eina_strbuf_string_get(fontbuf), removeflag) == 0)
864      {
865        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
866        wd->changed = 1;
867        _sizing_eval(obj);
868      }
869    eina_strbuf_free(fontbuf);
870 }
871
872 /**
873  * Set the text align on the label object
874  *
875  * @param obj The label object
876  * @param align align mode ("left", "center", "right")
877  *
878  * @ingroup Label
879  */
880 EAPI void
881 elm_label_text_align_set(Evas_Object *obj, const char *alignmode)
882 {
883    ELM_CHECK_WIDTYPE(obj, widtype);
884    Widget_Data *wd = elm_widget_data_get(obj);
885    int len;
886
887    if (!wd) return;
888    len = strlen(wd->label);
889    if (len <= 0) return;
890
891    if (_stringshare_key_value_replace(&wd->label, "align", alignmode, 0) == 0)
892      edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
893
894    wd->changed = 1;
895    _sizing_eval(obj);
896 }
897
898 /**
899  * Set the text color on the label object
900  *
901  * @param obj The label object
902  * @param r Red property background color of The label object 
903  * @param g Green property background color of The label object 
904  * @param b Blue property background color of The label object 
905  * @param a Alpha property background color of The label object 
906  *
907  * @ingroup Label
908  */
909 EAPI void
910 elm_label_text_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
911 {
912    ELM_CHECK_WIDTYPE(obj, widtype);
913    Widget_Data *wd = elm_widget_data_get(obj);
914    Eina_Strbuf *colorbuf = NULL;
915    int len;
916
917    if (!wd) return;
918    len = strlen(wd->label);
919    if (len <= 0) return;
920    colorbuf = eina_strbuf_new();
921    eina_strbuf_append_printf(colorbuf, "#%02X%02X%02X%02X", r, g, b, a);
922
923    if (_stringshare_key_value_replace(&wd->label, "color", eina_strbuf_string_get(colorbuf), 0) == 0)
924      {
925        edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
926        wd->changed = 1;
927        _sizing_eval(obj);
928      }
929    eina_strbuf_free(colorbuf);
930 }
931
932
933 /**
934  * Set background color of the label
935  *
936  * @param obj The label object
937  * @param r Red property background color of The label object 
938  * @param g Green property background color of The label object 
939  * @param b Blue property background color of The label object 
940  * @param a Alpha property background color of The label object 
941  * @ingroup Label
942  */
943 EAPI void
944 elm_label_background_color_set(Evas_Object *obj, unsigned int r, unsigned int g, unsigned int b, unsigned int a)
945 {
946    ELM_CHECK_WIDTYPE(obj, widtype);
947    Widget_Data *wd = elm_widget_data_get(obj);
948    if (!wd) return;
949    evas_object_color_set(wd->bg, r, g, b, a);
950
951    if (wd->bgcolor == EINA_FALSE)
952      {
953         wd->bgcolor = 1;
954         edje_object_part_swallow(wd->lbl, "label.swallow.background", wd->bg);
955      }
956 }
957
958 /**
959  * Set the ellipsis behavior of the label
960  *
961  * @param obj The label object
962  * @param ellipsis To ellipsis text or not
963  * @ingroup Label
964  */
965 EAPI void
966 elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
967 {
968    ELM_CHECK_WIDTYPE(obj, widtype);
969    Widget_Data *wd = elm_widget_data_get(obj);
970    if (!wd) return;
971    if (wd->ellipsis == ellipsis) return;
972    wd->ellipsis = ellipsis;
973    if (wd->linewrap) _theme_change(obj);
974    edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
975    wd->changed = 1;
976    _sizing_eval(obj);
977 }
978
979 /**
980  * Set the wrapmode of the label
981  *
982  * @param obj The label object
983  * @param wrapmode 0 is charwrap, 1 is wordwrap
984  * @ingroup Label
985  */
986 EAPI void
987 elm_label_wrap_mode_set(Evas_Object *obj, Eina_Bool wrapmode)
988 {
989    ELM_CHECK_WIDTYPE(obj, widtype);
990    Widget_Data *wd = elm_widget_data_get(obj);
991    if (!wd) return;
992    if (wd->wrapmode == wrapmode) return;
993    wd->wrapmode = wrapmode;
994    _label_state_change(obj);
995    wd->changed = 1;
996    _sizing_eval(obj);
997 }
998
999 /**
1000  * Set the text slide of the label
1001  *
1002  * @param obj The label object
1003  * @param slide To start slide or stop
1004  * @ingroup Label
1005  */
1006 EAPI void
1007 elm_label_slide_set(Evas_Object *obj, Eina_Bool slide)
1008 {
1009    ELM_CHECK_WIDTYPE(obj, widtype);
1010    Widget_Data *wd = elm_widget_data_get(obj);
1011    if (!wd) return;
1012
1013    if (wd->slidingmode == slide) return;
1014    wd->slidingmode = slide;
1015    _label_sliding_change(obj);
1016    wd->changed = 1;
1017    _sizing_eval(obj);
1018 }
1019
1020 /**
1021  * get the text slide mode of the label
1022  *
1023  * @param obj The label object
1024  * @return slide slide mode value
1025  * @ingroup Label
1026  */
1027 EAPI Eina_Bool
1028 elm_label_slide_get(Evas_Object *obj)
1029 {
1030    ELM_CHECK_WIDTYPE(obj, widtype);
1031    Widget_Data *wd = elm_widget_data_get(obj);
1032    if (!wd) return EINA_FALSE;
1033
1034    return wd->slidingmode;
1035 }
1036
1037 /**
1038  * set the slide duration(speed) of the label
1039  *
1040  * @param obj The label object
1041  * @return The duration time in moving text from slide begin position to slide end position
1042  * @ingroup Label
1043  */
1044 EAPI void
1045 elm_label_slide_duration_set(Evas_Object *obj, int duration)
1046 {
1047    ELM_CHECK_WIDTYPE(obj, widtype);
1048    Widget_Data *wd = elm_widget_data_get(obj);
1049    Edje_Message_Int_Set *msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
1050    
1051    if (!wd) return;
1052    wd->slide_duration = duration;
1053
1054    msg->count=1;
1055    msg->val[0] = (int)wd->slide_duration;
1056
1057    edje_object_message_send(wd->lbl, EDJE_MESSAGE_INT_SET, 0, msg);
1058 }
1059
1060 /**
1061  * get the slide duration(speed) of the label
1062  *
1063  * @param obj The label object
1064  * @return The duration time in moving text from slide begin position to slide end position
1065  * @ingroup Label
1066  */
1067 EAPI int
1068 elm_label_slide_duration_get(Evas_Object *obj)
1069 {
1070    ELM_CHECK_WIDTYPE(obj, widtype) 0;
1071    Widget_Data *wd = elm_widget_data_get(obj);
1072    if (!wd) return;
1073    return wd->slide_duration;
1074 }