harmattan version.
[monky] / lua_scripts / piechart.lua
1 --[[PIE CHART WIDGET BY WLOURF v1.21 26 june 2010
2
3 This widget draw a pie chart or a ring in a conky window.
4 More info on the parameters with pictures on this page :
5 http://u-scripts.blogspot.com/2010/04/pie-chart-widget.html
6
7 Parameters are :
8 tableV                          -- table of labels and values {{label,conky_variable,conky_argument,convert to Go-Mo-Ko units (true/false) or unit}, ...}
9                                         -- this table is mandatory, others parameters are optionals
10                                         -- example :
11                                                         tableV={
12                                                                 {"cpu 0","cpu","cpu0",100,"%"},
13                                                                 {"cpu 1","cpu","cpu1",100,"%"},                                                 
14                                                                 },
15                                         -- to know disk space, use this line :
16                                                         tableV=read_df(true,true),      
17                                                         
18 xc                                      -- x center of the pie, default = conky_window.width/2
19 yc,                                     -- y center of the pie, default = conky_window.height/2
20 radius_int                      -- internal radius in pixel, default = conky_window.width/6
21 radius_ext                      -- external radius in pixel, default = conky_window.width/4
22 first_angle                     -- first angle of the pie (in degrees), default=0
23 last_angle                      -- last angle of the pie (in degrees), default=360
24 type_arc,                       -- fill the arc in a linear way (ring) or radial way (pie), values l or r, default=l
25 inverse_l_arc           -- inverse arc for rings (true/false), default=false
26 proportional            -- display proportional sectors (true/false); default =false
27 gradient_effect         -- gradient effect (true/false), default=true
28 line_length                     -- length for horizontal line (from radius_ext to end of line), default=radius_ext
29 line_thickness          -- thickness of line, default=1
30 line_space                      -- vertical space between two lines, default=10 pixels
31 extend_line                     -- grow up the line (true/false) if length of text> line_length, default=true
32 nb_decimals                     -- number of decimals for numbers, default=1
33 show_text                       -- display text (true/false), default=true
34 font_name                       -- font, default "Nokia Pure"
35 font_size                       -- font size, default=12
36 font_color                      -- font color (for gradient) or nil (for constant color), default = nil
37 font_alpha                      -- font alpha, default=1
38 txt_offset                      -- space between text and line, default=1
39 txt_format                      -- string for formatting text, possibles values are :  default = "&l : &v"
40                                                 -- &l for label
41                                                 -- &o for occupied percentage
42                                                 -- &f for free percentage
43                                                 -- &v for value 
44                                                 -- &n for free value (non-occupied)     
45                                                 -- &m for max value
46                                                 -- &p for percentage value of full graph
47 tablebg                         -- table of tables of colours for background {colors,alpha}
48 tablefg                         -- table of tables of colours for foreground {colors,alpha}
49         
50         
51 v1.0 10/04/2010  original release
52 v1.1 15/05/2010  the parameters are in a table (pie_settings), only the values in pie_settings.tableV are mandatory
53                                  added an option to draw values like a ring (type_arc="l")
54 v1.2 26/05/2010  add inverse_l parameter (for type_arc="l")
55                                  bug fix : line_length problem
56                                  read_df function improved
57 v1.21 26/06/2010 rename some parameters and write more infos
58 ]]
59
60
61 require 'cairo'
62
63
64 --main function
65 function conky_main_pie()
66     if conky_window==nil then return end
67
68
69 -- ------------------PARAMETERS TO SET-----------------------
70     --theses parameters are called many times so I put them into variables
71     local font_name,font_size="Nokia Pure",14
72     local col0,col1,col2=0xFFFFCC,0xCCFF99,0x99FF00
73     local colbg=0x99CCFF
74         
75     --for the clock
76     local temp = os.date("*t")
77     local hour=temp.hour
78     if hour>12 then hour=hour-12 end
79     local hpc,mpc,spc=hour/12,temp.min/60,temp.sec/60
80
81     
82     pie_settings= {
83
84         {--CIRCLE 4 : DISK SPACE
85             tableV=read_df(true,true),
86             xc=500,
87             yc=150 ,
88             int_radius=30,
89             radius=45,
90             type_arc="r",
91             proportional=true,
92             first_angle=-90,
93             last_angle=270, 
94             gradient_effect=true,
95             show_text=true,
96             line_lgth=100,
97             line_space=19,
98             txt_format="&l free &n",
99             font_color=colbg,    
100             tablebg={            
101                 {colbg,0.5},
102                 },
103             tablefg={            
104                 {col0,1},
105                 {col1,1},
106                 {col2,1},
107                 },
108         },        
109
110
111         {--CIRCLE 1 : ARCS 1 & 2 INTERNET SPEED
112             tableV={
113                 {"dl","downspeedf","eth1",1000,"kb/s"},
114                 {"ul","upspeedf","eth1",100,"kb/s"},
115                 },
116             xc=300,
117             yc=200,
118             int_radius=30,
119             radius=45,
120             first_angle=-30,
121             last_angle=210,
122             type_arc="r",
123             --line_lgth=150,
124             line_width=0,
125             show_text=false,
126             font_color=colbg,
127             tablebg={
128                 {colbg,0.5},
129                 },
130             tablefg={
131                 {col0,1},
132                 {col1,1},
133                 },
134         },        
135
136         
137             {--CIRCLE 2 : ARC 1 CPU 0
138             tableV={
139                 {"cpu 0","cpu","cpu 0",100,"%"},
140                 --{"cpu 1","cpu","cpu 1",100,"%"},
141                 },
142             xc=300,
143             yc=350,
144             int_radius=30,
145             radius=45,
146             first_angle=-30,
147             last_angle=210,
148             type_arc="l",
149             show_text=false,
150             tablebg={
151                 {colbg,0.5},
152                 },
153             tablefg={
154                 {col0,1},
155                 },
156         },        
157
158 --            {--CIRCLE 2 : ARC 2 CPU 1
159 --            tableV={
160 --                --{"cpu 0","cpu","cpu 0",100,"%"},
161 --                {"cpu 1","cpu","cpu 1",100,"%"},
162 --                },
163 --            xc=200,
164 --            yc=350,
165 --            int_radius=30,
166 --            radius=45,
167 --            first_angle=90,
168 --            last_angle=220,
169 --            type_arc="l",
170 --            inverse_l_arc=true,
171 --            show_text=false,
172 --            tablebg={
173 --                {colbg,0.5},
174 --                },
175 --            tablefg={
176 --                {col0,1},
177 --                },
178 --        },        
179         
180                 
181
182     
183
184         {--CIRCLE  3 : MEMORY : ram
185             tableV={
186                 {"mem","memperc","",100,"%"},
187                 },
188             xc=400,
189             yc=370,
190             int_radius=30,
191             radius=45,
192             first_angle=-30,
193             last_angle=220,
194             type_arc="l",
195             inverse_l_arc=false,
196             proportional=false,
197             gradient_effect=true,
198             nb_decimals=0,
199             show_text=false,
200             tablebg={
201                 {colbg,0.5},
202                 },
203             tablefg={
204                 {col0,1},
205                 },
206         },                                
207               
208
209     }
210 -------------------END OF PARAMETERS ---------------
211
212     local w=conky_window.width
213     local h=conky_window.height
214     local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h)
215     cr=cairo_create(cs)
216
217     if tonumber(conky_parse('${updates}'))>5 then
218         for i in pairs(pie_settings) do
219             draw_pie(pie_settings[i])
220         end
221     end
222         cairo_surface_destroy(cs)
223     cairo_destroy(cr)
224 end
225
226
227
228 function string:split(delimiter)
229 --source for the split function : http://www.wellho.net/resources/ex.php4?item=u108/split
230   local result = { }
231   local from  = 1
232   local delim_from, delim_to = string.find( self, delimiter, from  )
233   while delim_from do
234     table.insert( result, string.sub( self, from , delim_from-1 ) )
235     from  = delim_to + 1
236     delim_from, delim_to = string.find( self, delimiter, from  )
237   end
238   table.insert( result, string.sub( self, from  ) )
239   return result
240 end
241
242
243 function rgb_to_r_g_b(colour, alpha)
244     return ((colour / 0x10000) % 0x100) / 255., ((colour / 0x100) % 0x100) / 255., (colour % 0x100) / 255., alpha
245 end
246
247 function round(num, idp)
248     local mult = 10^(idp or 0)
249     return math.floor(num * mult + 0.5) / mult
250 end
251
252 function size_to_text(size,nb_dec)
253     local txt_v
254     if nb_dec<0 then nb_dec=0 end
255     size = tonumber(size)
256     if size>1024*1024*1024 then
257         txt_v=string.format("%."..nb_dec.."f G",size/1024/1024/1024)
258     elseif size>1024*1024 then 
259         txt_v=string.format("%."..nb_dec.."f M",size/1024/1024)
260     elseif size>1024 then 
261         txt_v=string.format("%."..nb_dec.."f K",size/1024)
262     else
263         txt_v=string.format("%."..nb_dec.."f B",size)
264     end
265     return txt_v
266 end
267
268 function text_to_bytes(txt_in)
269         local txt_modifier
270         local num_bytes
271         txt_modifier = string.match(txt_in,"%d(%a)")
272         num_bytes = string.gsub(txt_in,"%d(%a)","")
273         if txt_modifier == "G" then
274                 num_bytes = num_bytes*1024*1024*1024
275         elseif txt_modifier == "M" then
276                 num_bytes = num_bytes*1024*1024
277         elseif txt_modifier == "K" then
278                 num_bytes = num_bytes*1024
279         elseif txt_modifier == "B" then
280                 num_bytes = num_bytes
281         end
282                 return num_bytes
283 end
284
285
286
287 function read_df(show_media,sort_table)
288     --read output of command df and return arrays of value for files systems
289     --reurn array of table {file syst, "", occupied space , total space , convert to G, M, K ...}
290     
291     local f = io.popen("df")
292
293     local results={}
294                 table.insert(results,{"/home/user/MyDocs","",text_to_bytes(conky_parse("${fs_used /home/user/MyDocs}")),text_to_bytes(conky_parse("${fs_size /home/user/MyDocs}")),true})
295                 table.insert(results,{"/home","",text_to_bytes(conky_parse("${fs_used /home}")),text_to_bytes(conky_parse("${fs_size /home}")),true})
296                 table.insert(results,{"rootfs","",text_to_bytes(conky_parse("${fs_used /}")),text_to_bytes(conky_parse("${fs_size /}")),true})
297                 table.insert(results,{"SD","",text_to_bytes(conky_parse("${fs_used /media/mmc1}")),text_to_bytes(conky_parse("${fs_size /media/mmc1}")),true})
298                 --table.insert(results,{"/home/user/MyDocs2","","30","50",true})
299                 --table.insert(results,{text_to_bytes(conky_parse("${fs_used /home/user/MyDocs}")),"","10","50",true})
300 --    while true do
301 --         local line = f:read("*l")
302 --         if line == nil then break end
303 --         while string.match(line,"  ") do
304 --             line=string.gsub(line,"  "," ")
305 --         end
306 --        local arr_l=string.split(line," ")
307 --        local match = string.match(arr_l[1],"/")
308 --        
309 --        if string.match(arr_l[1],"/") then
310 --            if not show_media then arr_l[6]=string.gsub(arr_l[6],"/media/","",1) end
311 --            if string.match(arr_l[1],"opt/") then break end
312 --            table.insert(results,{arr_l[6],"",(arr_l[2]-arr_l[4])*1024,arr_l[2]*1024,true})
313 --        end
314 --    end
315 --
316 --    f:close()
317 --    
318 --    if sort_table then
319 --        --how to sort table into table?
320 --        local flagS=true
321 --        while flagS do
322 --            for k=2, #results do 
323 --                flagS=false
324 --                if tonumber(results[1][3])>tonumber(results[2][3]) then
325 --                    local tmpV = results[1]
326 --                    results[1] = results[2]
327 --                    results[2] = tmpV
328 --                    flagS=true
329 --                end
330 --                if tonumber(results[k][3])<tonumber(results[k-1][3]) then
331 --                    local tmpV = results[k-1]
332 --                    results[k-1] = results[k]
333 --                    results[k] = tmpV
334 --                    flagS=true
335 --                end
336 --            end
337 --        end
338 --    end
339     
340     return results --array {file syst, occupied space , total space }
341 end
342
343
344 function draw_pie(t)
345     
346     if t.tableV==nil then 
347         print ("No input values ...") 
348         return
349     else
350         tableV=t.tableV
351     end
352
353     if t.xc==nil then t.xc=conky_window.width/2 end
354     if t.yc==nil then t.yc=conky_window.height/2 end
355     if t.int_radius ==nil then t.int_radius =conky_window.width/6 end
356     if t.radius ==nil then t.radius =conky_window.width/4 end
357     if t.first_angle==nil then t.first_angle =0 end
358     if t.last_angle==nil then t.last_angle=360 end
359     if t.proportional==nil then t.proportional=false end
360     if t.tablebg==nil then t.tablebg={{0xFFFFFF,0.5},{0xFFFFFF,0.5}} end
361     if t.tablefg==nil then t.tablefg={{0xFF0000,1},{0x00FF00,1}} end
362     if t.gradient_effect==nil then t.gradient_effect=true end
363     if t.show_text==nil then t.show_text=true end
364     if t.line_lgth==nil then t.line_lgth=t.int_radius end
365     if t.line_space==nil then t.line_space=10 end
366     if t.line_width==nil then t.line_width=1 end
367     if t.extend_line==nil then t.extend_line=true end
368     if t.txt_font==nil then t.txt_font="Nokia Pure" end
369     if t.font_size==nil then t.font_size=12 end
370     --if t.font_color==nil then t.font_color=0xFFFFFF end
371     if t.font_alpha==nil then t.font_alpha = 1 end
372     if t.txt_offset==nil then t.txt_offset = 1 end
373     if t.txt_format==nil then t.txt_format = "&l : &v" end
374     if t.nb_decimals==nil then t.nb_decimals=1 end
375     if t.type_arc==nil then t.type_arc="l" end
376     if t.inverse_l_arc==nil then t.inverse_l_arc=false end
377     
378     
379     local function draw_sector(tablecolor,colorindex,pc,lastAngle,angle,radius,int_radius,gradient_effect,type_arc,inverse_l_arc)
380         --draw a portion of arc
381         radiuspc=(radius-int_radius)*pc+int_radius
382         angle0=lastAngle
383         val=1
384         if type_arc=="l" then 
385             val=pc;radiuspc=radius
386         end
387         angle1=angle*val
388
389         if type_arc=="l" and inverse_l_arc then 
390
391             cairo_save(cr)
392     
393             cairo_rotate(cr,angle0+angle)
394             
395             if gradient_effect then        
396                 local pat = cairo_pattern_create_radial (0,0, int_radius, 0,0,radius)
397                 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(tablecolor[colorindex][1],0))
398                 cairo_pattern_add_color_stop_rgba (pat, 0.5, rgb_to_r_g_b(tablecolor[colorindex][1],tablecolor[colorindex][2]))
399                 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(tablecolor[colorindex][1],0))
400                 cairo_set_source (cr, pat)
401                 cairo_pattern_destroy(pat)
402             else
403                 cairo_set_source_rgba(cr,rgb_to_r_g_b(tablecolor[colorindex][1],tablecolor[colorindex][2]))
404             end
405             cairo_move_to(cr,0,-int_radius)
406             cairo_line_to(cr,0,-radiuspc)
407             cairo_rotate(cr,-math.pi/2)
408         
409             cairo_arc_negative(cr,0,0,radiuspc,0,-angle1)
410             cairo_rotate(cr,-math.pi/2-angle1)
411             cairo_line_to(cr,0,int_radius)
412             cairo_rotate(cr,math.pi/2)
413             cairo_arc(cr,0,0,int_radius,0,angle1)
414             cairo_close_path (cr);
415             cairo_fill(cr)
416
417             cairo_restore(cr)
418         else
419         
420             cairo_save(cr)
421     
422             cairo_rotate(cr,angle0)
423
424             if gradient_effect then        
425                 local pat = cairo_pattern_create_radial (0,0, int_radius, 0,0,radius)
426                 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(tablecolor[colorindex][1],0))
427                 cairo_pattern_add_color_stop_rgba (pat, 0.5, rgb_to_r_g_b(tablecolor[colorindex][1],tablecolor[colorindex][2]))
428                 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(tablecolor[colorindex][1],0))
429                 cairo_set_source (cr, pat)
430                 cairo_pattern_destroy(pat)
431             else
432                 cairo_set_source_rgba(cr,rgb_to_r_g_b(tablecolor[colorindex][1],tablecolor[colorindex][2]))
433             end
434             cairo_move_to(cr,0,-int_radius)
435             cairo_line_to(cr,0,-radiuspc)
436             cairo_rotate(cr,-math.pi/2)
437         
438             cairo_arc(cr,0,0,radiuspc,0,angle1)
439             cairo_rotate(cr,angle1-math.pi/2)
440             cairo_line_to(cr,0,int_radius)
441             cairo_rotate(cr,math.pi/2)
442             cairo_arc_negative(cr,0,0,int_radius,0,-angle1)
443             cairo_close_path (cr);
444             cairo_fill(cr)
445
446             cairo_restore(cr)
447         end
448         
449
450     end
451
452     function draw_lines(idx,nbArcs,angle,table_colors,idx_color,adjust,line_lgth,length_txt,txt_offset,radius,line_width,line_space,font_color,font_alpha)
453         --draw lines
454         
455         local x0=radiuspc*math.sin(lastAngle+angle/2)
456         local y0=-radiuspc*math.cos(lastAngle+angle/2)
457         local x1=1.2*radius*math.sin(lastAngle+angle/2)
458         local y1=-1.2*radius*math.cos(lastAngle+angle/2)
459
460         local x2=line_lgth
461         local y2=y1
462         local x3,y3=nil,nil
463         if x0<=0 then
464             x2=-x2
465         end
466
467         if adjust then
468             if x0>0 and x2-x1<length_txt then x2=x1+length_txt end
469             if x0<=0 and x1-x2<length_txt then x2=x1-length_txt end            
470         end 
471         
472         if idx>1 then
473             local dY = math.abs(y2-lastPt2[2])
474             if dY < line_space and lastPt2[1]*x1>0 then
475                 if x0>0 then
476                     y2 = line_space+lastPt2[2]
477                 else
478                     y2 = -line_space+lastPt2[2]
479                 end
480                 if (y2>y1 and x0>0) or (y2<y1 and x0<0 )  then
481                     --x3 is for vertical segment if needed
482                     x3,y3=x2,y2                    
483                     x2=x1
484                     if x3>0 then x3=x3+txt_offset end
485                 else
486                     Z=intercept({x0,y0},{x1,y1},{0,y2},{1,y2})
487                     x1,y1=Z[1],Z[2]
488                 end
489             end
490         else
491             --remind x2,y2 of first value
492             x2first,y2first = x2,y2
493         end
494
495         if font_color==nil then
496             cairo_set_source_rgba(cr,rgb_to_r_g_b(table_colors[idx_color][1],table_colors[idx_color][2]))
497         else
498             local pat = cairo_pattern_create_linear (x2,y2, x0,y0)
499             cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(font_color,font_alpha))
500             cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(table_colors[idx_color][1],table_colors[idx_color][2]))
501             cairo_set_source (cr, pat)
502             cairo_pattern_destroy(pat)
503         end
504
505         
506         cairo_move_to(cr,x0,y0)
507         cairo_line_to(cr,x1,y1)
508         cairo_line_to(cr,x2,y2)
509         if x3~=nil then 
510             cairo_line_to(cr,x3,y3)
511             x2,y2=x3,y3    
512         end
513         cairo_set_line_width(cr,line_width)
514         cairo_stroke(cr)
515         --lastAngle=lastAngle+angle
516         return {x2,y2}
517     end
518     
519     function intercept(p11,p12,p21,p22)
520         --calculate interscetion of two lines and return coordinates
521         a1=(p12[2]-p11[2])/(p12[1]-p11[1])
522
523         a2=(p22[2]-p21[2])/(p22[1]-p21[1])
524
525         b1=p11[2]-a1*p11[1]
526
527         b2=p21[2]-a2*p21[1]
528
529         X=(b2-b1)/(a1-a2)
530
531         Y=a1*X+b1
532         return {X,Y}
533     end
534
535     --some checks
536     if t.first_angle>=t.last_angle then
537         local tmp_angle=t.last_angle
538         --t.last_angle=t.first_angle
539         --t.first_angle=tmp_angle
540         print ("inversed angles")
541     end
542
543     if t.last_angle-t.first_angle>360 and t.first_angle>0 then
544         t.last_angle=360+t.first_angle
545         print ("reduce angles")
546     end
547     
548     if t.last_angle+t.first_angle>360 and t.first_angle<=0 then
549         t.last_angle=360+t.first_angle
550         print ("reduce angles")
551     end
552     
553     if t.int_radius<0 then t.int_radius =0 end
554     if t.int_radius>t.radius then
555         local tmp_radius=t.radius
556         t.radius=t.int_radius
557         t.int_radius=tmp_radius
558         print ("inversed angles")
559     end
560     if t.int_radius==t.radius then
561         t.int_radius=0
562         print ("int radius set to 0")
563     end    
564     --end of checks
565     
566     cairo_save(cr)
567     cairo_translate(cr,t.xc,t.yc)
568     cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND)
569     cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND)
570     
571     local nbArcs=#tableV
572     local anglefull= (t.last_angle-t.first_angle)*math.pi/180
573     local fullsize = 0
574     for i= 1,nbArcs do
575         fullsize=fullsize+tableV[i][4]
576     end
577
578     local cb,cf,angle=0,0,anglefull/nbArcs
579     lastAngle=t.first_angle*math.pi/180
580     lastPt2={nil,nil}
581
582     for i =1, nbArcs do
583         if t.proportional then
584             angle=tableV[i][4]/fullsize*anglefull
585         end
586         --set colours
587         cb,cf=cb+1,cf+1
588         if cb>#t.tablebg then cb=1 end
589         if cf>#t.tablefg then cf=1 end
590         
591         if tableV[i][2]~="" then
592             str=string.format('${%s %s}',tableV[i][2],tableV[i][3])
593         else
594             str = tableV[i][3]
595         end
596         str=conky_parse(str)
597         value=tonumber(str)
598         if value==nil then value=0 end
599     
600         --draw sectors
601         draw_sector(t.tablebg,cb,1,lastAngle,angle,t.radius,t.int_radius,t.gradient_effect,t.type_arc,t.inverse_l_arc)
602         --print (t.tablefg,cf,tableV[i][2],tableV[i][3],lastAngle,angle,t.radius,t.int_radius)
603         --print (cf,tableV[i],tableV[i][2],tableV[i][3])
604         draw_sector(t.tablefg,cf,value/tableV[i][4],lastAngle,angle,t.radius,t.int_radius,t.gradient_effect,t.type_arc,t.inverse_l_arc)
605
606         if t.show_text then
607             --draw text
608             local txt_l   = tableV[i][1]
609             local txt_opc = round(100*value/tableV[i][4],t.nb_decimals).."%%"
610             local txt_fpc = round(100*(tableV[i][4]-value/tableV[i][4]),t.nb_decimals).."%%"
611             local txt_ov,txt_fv,txt_max
612             if tableV[i][5]==true then
613                 txt_ov  = size_to_text(value,t.nb_decimals)
614                 txt_fv  = size_to_text(tableV[i][4]-value,t.nb_decimals)
615                 txt_max = size_to_text(tableV[i][4],t.nb_decimals)
616             else
617                 if tableV[i][5]=="%" then tableV[i][5]="%%" end
618                 txt_ov=string.format("%."..t.nb_decimals.."f ",value)..tableV[i][5]
619                 txt_fv=string.format("%."..t.nb_decimals.."f",tableV[i][4]-value)..tableV[i][5]
620                 txt_max=string.format("%."..t.nb_decimals.."f",tableV[i][4])..tableV[i][5]
621             end
622             txt_pc = string.format("%."..t.nb_decimals.."f",100*tableV[i][4]/fullsize).."%%"
623             local txt_out = t.txt_format
624             txt_out = string.gsub(txt_out,"&l",txt_l)  --label
625             txt_out = string.gsub(txt_out,"&o",txt_opc)--occ. %
626             txt_out = string.gsub(txt_out,"&f",txt_fpc)--free %
627             txt_out = string.gsub(txt_out,"&v",txt_ov) --occ. value
628             txt_out = string.gsub(txt_out,"&n",txt_fv) --free value
629             txt_out = string.gsub(txt_out,"&m",txt_max)--max
630             txt_out = string.gsub(txt_out,"&p",txt_pc)--percent
631             
632             local te=cairo_text_extents_t:create()
633             cairo_set_font_size(cr,t.font_size)
634             cairo_select_font_face(cr, t.txt_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL)
635             cairo_text_extents (cr,txt_out,te)
636
637             --draw lines 
638             lastPt2=draw_lines(i,nbArcs,angle,t.tablefg,cf,t.extend_line,t.line_lgth+t.radius, 
639                     te.width + te.x_bearing,t.txt_offset,t.radius,t.line_width,t.line_space,t.font_color,t.font_alpha)    
640         
641             local xA=lastPt2[1]
642             local yA=lastPt2[2]-t.line_width-t.txt_offset
643             if xA>0 then xA = xA-(te.width + te.x_bearing) end
644             cairo_move_to(cr,xA,yA)
645             cairo_show_text(cr,txt_out)
646         end
647         
648         lastAngle=lastAngle+angle
649     end
650     cairo_restore(cr)
651 end
652
653
654 --[[END OF PIE CHART WIDGET]]