4 v2.0 by wlourf (12.07.2010)
5 this widget draws a bargraph with different effects
6 http://u-scripts.blogspot.com/2010/07/bargraph-widget.html
10 3 parameters are mandatory
11 name - the name of the conky variable to display, for example for {$cpu cpu0}, just write name="cpu"
12 arg - the argument of the above variable, for example for {$cpu cpu0}, just write arg="cpu0"
13 arg can be a numerical value if name=""
14 max - the maximum value the above variable can reach, for example, for {$cpu cpu0}, just write max=100
17 x,y - coordinates of the starting point of the bar, default = middle of the conky window
18 cap - end of cap line, ossibles values are r,b,s (for round, butt, square), default="b"
19 http://www.cairographics.org/samples/set_line_cap/
20 angle - angle of rotation of the bar in degress, default = 0 (i.e. a vertical bar)
21 set to 90 for an horizontal bar
22 skew_x - skew bar around x axis, default = 0
23 skew_y - skew bar around y axis, default = 0
24 blocks - number of blocks to display for a bar (values >0) , default= 10
25 height - height of a block, default=10 pixels
26 width - width of a block, default=20 pixels
27 space - space between 2 blocks, default=2 pixels
28 angle_bar - this angle is used to draw a bar on a circular way (ok, this is no more a bar !) default=0
29 radius - for cicular bars, internal radius, default=0
30 with radius, parameter width has no more effect.
32 Colours below are defined into braces {colour in hexadecimal, alpha}
33 fg_colour - colour of a block ON, default= {0x00FF00,1}
34 bg_colour - colour of a block OFF, default = {0x00FF00,0.5}
35 alarm - threshold, values after this threshold will use alarm_colour colour , default=max
36 alarm_colour - colour of a block greater than alarm, default=fg_colour
37 smooth - (true or false), create a gradient from fg_colour to bg_colour, default=false
38 mid_colour - colours to add to gradient, with this syntax {position into the gradient (0 to1), colour hexa, alpha}
39 for example, this table {{0.25,0xff0000,1},{0.5,0x00ff00,1},{0.75,0x0000ff,1}} will add
40 3 colurs to gradient created by fg_colour and alarm_colour, default=no mid_colour
41 led_effect - add LED effects to each block, default=no led_effect
42 if smooth=true, led_effect is not used
43 possibles values : "r","a","e" for radial, parallelel, perdendicular to the bar (just try!)
44 led_effect has to be used with theses colours :
45 fg_led - middle colour of a block ON, default = fg_colour
46 bg_led - middle colour of a block OFF, default = bg_colour
47 alarm_led - middle colour of a block > ALARM, default = alarm_colour
49 reflection parameters, not avaimable for circular bars
50 reflection_alpha - add a reflection effect (values from 0 to 1) default = 0 = no reflection
51 other values = starting opacity
52 reflection_scale - scale of the reflection (default = 1 = height of text)
53 reflection_length - length of reflection, define where the opacity will be set to zero
54 calues from 0 to 1, default =1
55 reflection - position of reflection, relative to a vertical bar, default="b"
56 possibles values are : "b","t","l","r" for bottom, top, left, right
59 v1.0 (10 Feb. 2010) original release
60 v1.1 (13 Feb. 2010) numeric values can be passed instead conky stats with parameters name="", arg = numeric_value
61 v1.2 (28 Feb. 2010) just renamed the widget to bargraph
62 v1.3 (03 March 2010) added parameters radius & angle_bar to draw the bar in a circular way
63 v2.0 (12 Jul. 2010) rewrite script + add reflection effects and parameters are now set into tables
68 ----------------START OF PARAMETERS ----------
69 function conky_main_bars()
75 max=conky_parse("${to_bytes ${fs_size /}}"),
76 --alarm=1,--no alarm with 1 smooth block, don't do extra work here
77 bg_colour={0x00ff00,0.25},
78 fg_colour={0x00ff00,1},
79 alarm_colour={0xff0000,1},
85 mid_colour={{0.5,0xffff00,1}},
91 max=conky_parse("${to_bytes ${fs_size /home}}"),
92 --alarm=1,--no alarm with 1 smooth block, don't do extra work here
93 bg_colour={0x00ff00,0.25},
94 fg_colour={0x00ff00,1},
95 alarm_colour={0xff0000,1},
101 mid_colour={{0.5,0xffff00,1}},
105 arg="/home/user/MyDocs",
106 max=conky_parse("${to_bytes ${fs_size /home/user/MyDocs}}"),
107 --alarm=1,--no alarm with 1 smooth block, don't do extra work here
108 bg_colour={0x00ff00,0.25},
109 fg_colour={0x00ff00,1},
110 alarm_colour={0xff0000,1},
116 mid_colour={{0.5,0xffff00,1}},
117 DrawMe=conky_parse("${if_mounted /home/user/MyDocs}1$endif")
122 max=conky_parse("${to_bytes ${fs_size /media/mmc1}}"),
123 --alarm=1,--no alarm with 1 smooth block, don't do extra work here
124 bg_colour={0x00ff00,0.25},
125 fg_colour={0x00ff00,1},
126 alarm_colour={0xff0000,1},
132 mid_colour={{0.5,0xffff00,1}},
133 DrawMe=conky_parse("${if_mounted /media/mmc1}1$endif")
138 max=conky_parse("${to_bytes ${memmax}}"),
140 bg_colour={0x00ff00,0.25},
141 fg_colour={0x00ff00,1},
142 alarm_colour={0xff0000,1},
148 --mid_colour={{0.5,0xffff00,1}},
151 name="battery_percent",
156 alarm_colour={0x00ffff,0.5},
157 bg_colour={0x00ffff,0.5},
158 fg_colour={0xff0000,0.5},
160 bg_led ={0x0000ff,1},
161 fg_led ={0xffff00,1},
166 name="wireless_link_qual_perc",
170 bg_colour={0x00ff33,0},
171 fg_colour={0x00ff33,1},
178 mid_colour={{0,0xFF0000,1},{0.5,0xff0000,1},{0.7,0xffff00,1},{0.85,0x00ff33,1}},
180 DrawMe=conky_parse("${if_empty ${wireless_essid wlan0}}${else}1$endif"),
183 name="wireless_link_qual_perc",
187 bg_colour={0x00ff33,0},
188 fg_colour={0x00ff33,1},
195 mid_colour={{0,0xFF0000,1},{0.5,0xff0000,1},{0.7,0xffff00,1},{0.85,0x00ff33,1}},
197 DrawMe=conky_parse("${if_empty ${wireless_essid wlan0}}${else}1$endif"),
200 name="cell_radio_percent",
203 bg_colour={0x00ff33,0},
204 fg_colour={0x00ff33,1},
213 mid_colour={{0,0xFF0000,1},{0.5,0xff0000,1},{0.7,0xffff00,1},{0.85,0x00ff33,1}},
215 --DrawMe=conky_parse("${if_up gprs0}1$endif")
219 if conky_window == nil then return end
220 local cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)
221 cr = cairo_create(cs)
222 --prevent segmentation error when reading cpu state
223 if tonumber(conky_parse('${updates}'))>3 then
224 for i in pairs(bars_settings) do
225 draw_multi_bar_graph(bars_settings[i])
229 cairo_surface_destroy(cs)
233 function draw_multi_bar_graph(t)
236 if t.DrawMe~=nil and t.DrawMe ~= "1" then return end
237 if t.name==nil and t.arg==nil then
238 print ("No input values ... use parameters 'name' with 'arg' or only parameter 'arg' ")
242 print ("No maximum value defined, use 'max'")
245 if t.name==nil then t.name="" end
246 if t.arg==nil then t.arg="" end
249 if t.x == nil then t.x = conky_window.width/2 end
250 if t.y == nil then t.y = conky_window.height/2 end
251 if t.blocks == nil then t.blocks=10 end
252 if t.height == nil then t.height=10 end
253 if t.angle == nil then t.angle=0 end
254 t.angle = t.angle*math.pi/180
256 if t.cap==nil then t.cap = "b" end
258 for i,v in ipairs({"s","r","b"}) do
259 if v==t.cap then cap=v end
262 if t.cap=="r" or t.cap=="s" then delta = t.height end
263 if cap=="s" then cap = CAIRO_LINE_CAP_SQUARE
265 cap = CAIRO_LINE_CAP_ROUND
267 cap = CAIRO_LINE_CAP_BUTT
270 --if t.led_effect == nil then t.led_effect="r" end
271 if t.width == nil then t.width=20 end
272 if t.space == nil then t.space=2 end
273 if t.radius == nil then t.radius=0 end
274 if t.angle_bar == nil then t.angle_bar=0 end
275 t.angle_bar = t.angle_bar*math.pi/360 --halt angle
277 if t.bg_colour == nil then t.bg_colour = {0x00FF00,0.5} end
278 if #t.bg_colour~=2 then t.bg_colour = {0x00FF00,0.5} end
279 if t.fg_colour == nil then t.fg_colour = {0x00FF00,1} end
280 if #t.fg_colour~=2 then t.fg_colour = {0x00FF00,1} end
281 if t.alarm_colour == nil then t.alarm_colour = t.fg_colour end
282 if #t.alarm_colour~=2 then t.alarm_colour = t.fg_colour end
283 if t.mid_colour ~= nil then
284 for i=1, #t.mid_colour do
285 if #t.mid_colour[i]~=3 then
286 print ("error in mid_color table")
287 t.mid_colour[i]={1,0xFFFFFF,1}
291 if t.bg_led ~= nil and #t.bg_led~=2 then t.bg_led = t.bg_colour end
292 if t.fg_led ~= nil and #t.fg_led~=2 then t.fg_led = t.fg_colour end
293 if t.alarm_led~= nil and #t.alarm_led~=2 then t.alarm_led = t.fg_led end
294 if t.led_effect~=nil then
295 if t.bg_led == nil then t.bg_led = t.bg_colour end
296 if t.fg_led == nil then t.fg_led = t.fg_colour end
297 if t.alarm_led == nil then t.alarm_led = t.fg_led end
299 if t.alarm==nil then t.alarm = t.max end --0.8*t.max end
300 if t.smooth == nil then t.smooth = false end
301 if t.skew_x == nil then
304 t.skew_x = math.pi*t.skew_x/180
306 if t.skew_y == nil then
309 t.skew_y = math.pi*t.skew_y/180
311 if t.reflection_alpha==nil then t.reflection_alpha=0 end
312 if t.reflection_length==nil then t.reflection_length=1 end
313 if t.reflection_scale==nil then t.reflection_scale=1 end
314 --end of default values
316 local function rgb_to_r_g_b(col_a)
317 return ((col_a[1] / 0x10000) % 0x100) / 255., ((col_a[1] / 0x100) % 0x100) / 255., (col_a[1] % 0x100) / 255., col_a[2]
320 --functions used to create patterns
321 local function create_smooth_linear_gradient(x0,y0,x1,y1)
322 local pat = cairo_pattern_create_linear (x0,y0,x1,y1)
323 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(t.fg_colour))
324 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(t.alarm_colour))
325 if t.mid_colour ~=nil then
326 for i=1, #t.mid_colour do
327 cairo_pattern_add_color_stop_rgba (pat, t.mid_colour[i][1], rgb_to_r_g_b({t.mid_colour[i][2],t.mid_colour[i][3]}))
333 local function create_smooth_radial_gradient(x0,y0,r0,x1,y1,r1)
334 local pat = cairo_pattern_create_radial (x0,y0,r0,x1,y1,r1)
335 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(t.fg_colour))
336 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(t.alarm_colour))
337 if t.mid_colour ~=nil then
338 for i=1, #t.mid_colour do
339 cairo_pattern_add_color_stop_rgba (pat, t.mid_colour[i][1], rgb_to_r_g_b({t.mid_colour[i][2],t.mid_colour[i][3]}))
345 local function create_led_linear_gradient(x0,y0,x1,y1,col_alp,col_led)
346 local pat = cairo_pattern_create_linear (x0,y0,x1,y1) ---delta, 0,delta+ t.width,0)
347 cairo_pattern_add_color_stop_rgba (pat, 0.0, rgb_to_r_g_b(col_alp))
348 cairo_pattern_add_color_stop_rgba (pat, 0.5, rgb_to_r_g_b(col_led))
349 cairo_pattern_add_color_stop_rgba (pat, 1.0, rgb_to_r_g_b(col_alp))
353 local function create_led_radial_gradient(x0,y0,r0,x1,y1,r1,col_alp,col_led,mode)
354 local pat = cairo_pattern_create_radial (x0,y0,r0,x1,y1,r1)
356 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(col_alp))
357 cairo_pattern_add_color_stop_rgba (pat, 0.5, rgb_to_r_g_b(col_led))
358 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(col_alp))
360 cairo_pattern_add_color_stop_rgba (pat, 0, rgb_to_r_g_b(col_led))
361 cairo_pattern_add_color_stop_rgba (pat, 1, rgb_to_r_g_b(col_alp))
366 local function draw_single_bar()
367 --this fucntion is used for bars with a single block (blocks=1) but
368 --the drawing is cut in 3 blocks : value/alarm/background
369 --not zvzimzblr for circular bar
370 local function create_pattern(col_alp,col_led,bg)
373 if t.led_effect=="e" then
374 pat = create_led_linear_gradient (-delta, 0,delta+ t.width,0,col_alp,col_led)
375 elseif t.led_effect=="a" then
376 pat = create_led_linear_gradient (t.width/2, 0,t.width/2,-t.height,col_alp,col_led)
377 elseif t.led_effect=="r" then
378 pat = create_led_radial_gradient (t.width/2, -t.height/2, 0, t.width/2,-t.height/2,t.height/1.5,col_alp,col_led,2)
380 pat = cairo_pattern_create_rgba (rgb_to_r_g_b(col_alp))
384 pat = cairo_pattern_create_rgba (rgb_to_r_g_b(t.bg_colour))
386 pat = create_smooth_linear_gradient(t.width/2, 0, t.width/2,-t.height)
392 local y1=-t.height*pct/100
394 if pct>(100*t.alarm/t.max) then
395 y1 = -t.height*t.alarm/100
396 y2 = -t.height*pct/100
397 if t.smooth then y1=y2 end
400 if t.angle_bar==0 then
403 local pat = create_pattern(t.fg_colour,t.fg_led,false)
404 cairo_set_source(cr,pat)
405 cairo_rectangle(cr,0,0,t.width,y1)
407 cairo_pattern_destroy(pat)
408 -- block for alarm value
409 if not t.smooth and y2 ~=nil then
410 pat = create_pattern(t.alarm_colour,t.alarm_led,false)
411 cairo_set_source(cr,pat)
412 cairo_rectangle(cr,0,y1,t.width,y2-y1)
415 cairo_pattern_destroy(pat)
419 -- block for bg value
420 cairo_rectangle(cr,0,y2,t.width,-t.height-y3)
421 pat = create_pattern(t.bg_colour,t.bg_led,true)
422 cairo_set_source(cr,pat)
423 cairo_pattern_destroy(pat)
428 local function draw_multi_bar()
429 --function used for bars with 2 or more blocks
430 for pt = 1,t.blocks do
432 local y1 = -(pt-1)*(t.height+t.space)
436 local col_alp = t.bg_colour
437 local col_led = t.bg_led
438 if pct>=(100/t.blocks) or pct>0 then --ligth on or not the block
439 if pct>=(pcb*(pt-1)) then
441 col_alp = t.fg_colour
443 if pct>=(100*t.alarm/t.max) and (pcb*pt)>(100*t.alarm/t.max) then
444 col_alp = t.alarm_colour
445 col_led = t.alarm_led
451 --have to try to create gradients outside the loop ?
454 if t.angle_bar==0 then
455 if t.led_effect=="e" then
456 pat = create_led_linear_gradient (-delta, 0,delta+ t.width,0,col_alp,col_led)
457 elseif t.led_effect=="a" then
458 pat = create_led_linear_gradient (t.width/2, -t.height/2+y1,t.width/2,0+t.height/2+y1,col_alp,col_led)
459 elseif t.led_effect=="r" then
460 pat = create_led_radial_gradient (t.width/2, y1, 0, t.width/2,y1,t.width/1.5,col_alp,col_led,2)
462 pat = cairo_pattern_create_rgba (rgb_to_r_g_b(col_alp))
465 if t.led_effect=="a" then
466 pat = create_led_radial_gradient (0, 0, t.radius+(t.height+t.space)*(pt-1),
467 0, 0, t.radius+(t.height+t.space)*(pt),
470 pat = cairo_pattern_create_rgba (rgb_to_r_g_b(col_alp))
475 if t.angle_bar==0 then
476 pat = create_smooth_linear_gradient(t.width/2, t.height/2, t.width/2,-(t.blocks-0.5)*(t.height+t.space))
478 pat = create_smooth_radial_gradient(0, 0, (t.height+t.space), 0,0,(t.blocks+1)*(t.height+t.space),2)
481 pat = cairo_pattern_create_rgba (rgb_to_r_g_b(t.bg_colour))
484 cairo_set_source (cr, pat)
485 cairo_pattern_destroy(pat)
488 if t.angle_bar==0 then
489 cairo_move_to(cr,0,y1)
490 cairo_line_to(cr,t.width,y1)
493 t.radius+(t.height+t.space)*(pt)-t.height/2,
494 -t.angle_bar -math.pi/2 ,
495 t.angle_bar -math.pi/2)
501 local function setup_bar_graph()
502 --function used to retrieve the value to display and to set the cairo structure
503 if t.blocks ~=1 then t.y=t.y-t.height/2 end
506 value = (conky_parse(string.format('${%s %s}', t.name, t.arg)))
507 if string.match(value,"%w") then
508 value = conky_parse(string.format('${to_bytes %s}',value))
510 value=tonumber(value)
512 value = tonumber(t.arg)
514 if value==nil then value =0 end
515 pct = 100*value/t.max
517 cairo_set_line_width (cr, t.height)
518 cairo_set_line_cap (cr, cap)
519 cairo_translate(cr,t.x,t.y)
520 cairo_rotate(cr,t.angle)
521 local matrix0 = cairo_matrix_t:create()
522 tolua.takeownership(matrix0)
523 cairo_matrix_init (matrix0, 1,t.skew_y,t.skew_x,1,0,0)
524 cairo_transform(cr,matrix0)
525 --call the drawing function for blocks
526 if t.blocks==1 and t.angle_bar==0 then
528 if t.reflection=="t" or t.reflection=="b" then cairo_translate(cr,0,-t.height) end
532 --call the drawing function for reflection and prepare the mask used
533 if t.reflection_alpha>0 and t.angle_bar==0 then
535 local matrix1 = cairo_matrix_t:create()
536 tolua.takeownership(matrix1)
537 if t.angle_bar==0 then
538 pts={-delta/2,(t.height+t.space)/2,t.width+delta,-(t.height+t.space)*(t.blocks)}
539 if t.reflection=="t" then
540 cairo_matrix_init (matrix1,1,0,0,-t.reflection_scale,0,-(t.height+t.space)*(t.blocks-0.5)*2*(t.reflection_scale+1)/2)
541 pat2 = cairo_pattern_create_linear (t.width/2,-(t.height+t.space)*(t.blocks),t.width/2,(t.height+t.space)/2)
542 elseif t.reflection=="r" then
543 cairo_matrix_init (matrix1,-t.reflection_scale,0,0,1,delta+2*t.width,0)
544 pat2 = cairo_pattern_create_linear (delta/2+t.width,0,-delta/2,0)
545 elseif t.reflection=="l" then
546 cairo_matrix_init (matrix1,-t.reflection_scale,0,0,1,-delta,0)
547 pat2 = cairo_pattern_create_linear (-delta/2,0,delta/2+t.width,-0)
549 cairo_matrix_init (matrix1,1,0,0,-1*t.reflection_scale,0,(t.height+t.space)*(t.reflection_scale+1)/2)
550 pat2 = cairo_pattern_create_linear (t.width/2,(t.height+t.space)/2,t.width/2,-(t.height+t.space)*(t.blocks))
553 cairo_transform(cr,matrix1)
554 if t.blocks==1 and t.angle_bar==0 then
556 cairo_translate(cr,0,-t.height/2)
560 cairo_set_line_width(cr,0.01)
561 cairo_pattern_add_color_stop_rgba (pat2, 0,0,0,0,1-t.reflection_alpha)
562 cairo_pattern_add_color_stop_rgba (pat2, t.reflection_length,0,0,0,1)
563 if t.angle_bar==0 then
564 cairo_rectangle(cr,pts[1],pts[2],pts[3],pts[4])
566 cairo_clip_preserve(cr)
567 cairo_set_operator(cr,CAIRO_OPERATOR_CLEAR)
570 cairo_pattern_destroy(pat2)
571 cairo_set_operator(cr,CAIRO_OPERATOR_OVER)
574 end --setup_bar_graph()