--[[PANEL WIDGET v1.0 by Wlourf 04 Oct. 2011
This widget can drawn a panel-like conky : with some indicators :circles, bars, graphs, text ..
http://wlourf.deviantart.com/#/d4bs4ksTo call the script in a conky, use, before TEXT
lua_load /path/to/the/script/panel.lua
lua_draw_hook_pre draw_panel
and add one line (blank or not) after TEXT
The parameters are set into two tables, one for the backgound (bar_settings) and one for the widgets (widgets_settings).
******************
***bar_settings***
******************
The parameters (all optionals) are :
x - x coordinate of top-left corner of the box, default = 0 = (top-left corner of conky window)
y - y coordinate of top-left corner of the box, default = 0 = (top-left corner of conky window)
width - width of the box, default = width of the conky window
height - height of the box, default = height of the conky window
corners - corners is a table for the four corners in this order : top-left, top-right,bottom-right, bottom-left
each corner is defined in a table with a shape and a radius, available shapes are : "curve","circle","line"
example for the same shapes for all corners:
{ {"circle",10} }
example for first corner different from the three others
{ {"circle",10}, {"circle",5} }
example for top corners differents from bottom corners
{ {"circle",10}, {"circle",10}, {"line",0} }
default = { {"line",0} } i.e=no corner
draw_me - if set to false, box is not drawn (default = true or 1)
it can be used with a conky string, if the string returns 1, the box is drawn :
example : "${if_empty ${wireless_essid wlan0}}${else}1$endif",
colour - table of colours, default = plain white {{1,0xFFFFFF,0.5}}
this table contains one or more tables with format {P,C,A}
P=position of gradient (0 = start of the gradient, 1= end of the gradient)
C=hexadecimal colour
A=alpha (opacity) of color (0=invisible,1=opacity 100%)
Examples :
for a plain color {{1,0x00FF00,0.5}}
for a gradient with two colours {{0,0x00FF00,0.5},{1,0x000033,1}}
or {{0.5,0x00FF00,1},{1,0x000033,1}} -with this one, gradient will start in the middle
for a gradient with three colours {{0,0x00FF00,0.5},{0.5,0x000033,1},{1,0x440033,1}}
and so on ...
The usage of theses parameters are explained on this page :http://u-scripts.blogspot.com/2011/01/box-widget_27.html
**********************
***widgets_settings***
**********************
The table widgets_settings contains one or more table for each widget.
The 3 mandatory parameters are :
name - the name of the conky variable to display, for example for {$cpu cpu0}, just write name="cpu"
arg - the argument of the above variable, for example for {$cpu cpu0}, just write arg="cpu0"
arg can be a numerical value if name=""
max - the maximum value the above variable can reach, for example, for {$cpu cpu0}, just write max=100
Optional parameters are :
style - style of the widget : "circle", "bar", "graph", "text", default=circle
xw,yw - x and y coordinates of the widget, relative to the top-left corner of the bar
for "circle" : x and y are the center of the circle, default : center of the bar
for "bar" and graph : x and y are the top left corner of the widget, default : center of the bar
text - text to display, default = ""
it can be used with conky variables, i.e. text="my cpu1 is ${cpu cpu1} %")
xt,yt - x and y coordinates of the text widget, or the text of a widget, relative to the top-left corner of the bar
default : center of the bar
angle - rotation of text in degrees, default = 0 (horizontal)
h_align - horizontal alignement of text relative to point (x,y), default="l"
available values are "l": left, "c" : center, "r" : right
v_align - vertical alignment of text relative to point (x,y), default="b"
available values "t" : top, "m" : middle, "b" : bottom
font_name - name of font to use, default = Free Sans
font_size - size of font to use, default = 14
italic - display text in italic (true/false), default=false
oblique - display text in oblique (true/false), default=false (I don' see the difference with italic!)
bold - display text in bold (true/false), default=false
colour - table of colours for widget, default = plain white {{1,0xFFFFFF,1}}
this table contains one or more tables with format {P,C,A}
P=position of gradient (0 = beginning of text, 1= end of text)
C=hexadecimal colour
A=alpha (opacity) of color (0=invisible,1=opacity 100%)
Examples :
for a plain color {{1,0x00FF00,0.5}}
for a gradient with two colours {{0,0x00FF00,0.5},{1,0x000033,1}}
or {{0.5,0x00FF00,1},{1,0x000033,1}} -with this one, gradient will start in the middle of the text
for a gradient with three colours {{0,0x00FF00,0.5},{0.5,0x000033,1},{1,0x440033,1}}
and so on ...
clear - if set to true, don't use the color but clear the background, default=false
draw_me - if set to false, text is not drawn, default = true or 1
it can be used with a conky string, if the string returns 1, the text is drawn :
example : "${if_empty ${wireless_essid wlan0}}${else}1$endif",
draw_border - draw the border of the widget if true, default=true
thickness - thickness of the border, default=1 pixel
inverse - if set to true, widgets are displayed in inverse order, default =false
***special parameters for circle widget only***
radius - radius of the circle, in % of the bar height, default=90
start - starting angle of the circle, default=0
hand - if hand>0, draw only the hand, not a sector, value is a percentage of the radius, default=0
***special parameters for graph widget only***
fill_graph - if set to true, fill the graph, default =false
auto_scale - if set to true, the y-axis of the graph is "autoscaled", defaault = false
***special parameters for graph and bar widgets only***
width - width of the widget in pixel, default=100
height - height of the widget in pixel, default=10
***special parameter for graph widget only***
fill_graph - if set to true, fill the graph, default =false
v1.0 04/10/2011, Original release
]]
require 'cairo'
local graphs={}
function conky_draw_panel()
--{{EXAMPLE1
--paremeters for the background
local bar_settings={
x=0,y=0,
height=25, width=480,
corners={{"circle",0}, {"circle",0}, {"circle",10}},
colour={ {0 ,0x666666,1},
{0.5 ,0xffffff,1},
{1 ,0x666666,1}
},
--draw_me=false
}
main_colour={{0 ,0x0000ff,0.25},
{0.50 ,0x0000ff,1},
{1 ,0x0000ff,0.25}
}
--parameters for the widgets
local widgets_settings={
--memory circle
{
name="memperc", arg="", max=100,
xw=30 ,
text="mem",
xt=12,
font_size=10, bold=true,
angle=-90,
h_align="c", v_align="m",
colour=main_colour,
start=90,
inverse=true
},
--home bar
{
style="bar",
name="fs_used_perc", arg="/home", max=100,
xw=70 ,yw=3 , width=80, height=8,
text="h",
xt=60, yt=7,
font_size=12, bold=true,
v_align="m",
colour=main_colour,
},
--root bar
{
style="bar",
name="fs_used_perc", arg="/", max=100,
xw=70 ,yw=14 , width=80, height=8,
text="r",
xt=60, yt=18,
font_size=12, bold=true,
v_align="m",
colour=main_colour,
},
--cpu1 circle
{
name="cpu", arg="cpu1", max=100,
xw=190 ,
text="cpu",
xt=170,
font_size=12, bold=true,
angle=-90,
h_align="c",
v_align="m",
colour=main_colour,
start=90,
inverse=true
},
--cpu2 circle
{
name="cpu", arg="cpu2", max=100,
xw=215 ,
colour=main_colour,
start=90,
inverse=true
},
--dl/ul graph border
{--dl graph
style="graph",
name="downspeedf", arg="eth0", max=2000,
xw=240 , yw=3, width=75,
colour={{0 ,0x0066ff,0.25},
{0.50 ,0x0066ff,1},
{1 ,0x0000ff,1}
},
height=19,
--auto_scale=true,
draw_border=false,
text="DL: ${downspeed eth0}",
font_size=10,
xt=320, yt=6, bold=true,
v_align="m",
fill_graph=true,
},
{--ul graph
style="graph",
name="upspeedf", arg="eth0", max=100,
xw=240 , yw=3, width=75,
colour={{0 ,0xff0066,0.25},
{0.50 ,0xff0066,1},
{1 ,0x0000ff,1}
},
height=19,
--auto_scale=true,
draw_border=false,
text="UL: ${upspeed eth0}",
font_size=10,
xt=320, yt=18, bold=true,
v_align="m"
},
{
style="graph",
name="", arg=0, max=1,
xw=240 , yw=3, width=75,
colour=main_colour,
height=19
},
{--time
style="text",
-- name="time", arg="", max=100,
text="${time %H:%M}",
xt=390, yt=15,
font_size=22,
angle=10,
bold=true,
colour=main_colour,
} ,
{--date
style="text",
-- name="time", arg="", max=100,
text="${time %d}",
xt=460, yt=12,
v_align="b",
font_size=12,
bold=true,
colour=main_colour,
},
{--date
style="text",
-- name="time", arg="", max=100,
text="${time %m}",
xt=460, yt=13,
v_align="t",
font_size=12,
bold=true,
colour=main_colour,
},
}
--END EXAMPLE 1}}
--------------END OF PARAMETERS----------------
if conky_window == nil then return end
if tonumber(conky_parse("$updates"))<3 then return end
local cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)
if bar_settings.x == nil then bar_settings.x=0 end
if bar_settings.y == nil then bar_settings.y=0 end
display_background(cs,bar_settings)
for i,v in pairs(widgets_settings) do
v.number=i
if v.style=="graph" and graphs[i] == nil then
graphs[i]={}
print ("setup graph " .. tostring(i) .. " at update :" .. conky_parse("$updates"))
if v.width== nil then v.width=100 end
for x=1, v.width do graphs[i][x]=0 end
end
--graphs[i][1]=0
cr = cairo_create (cs)
cairo_translate(cr,bar_settings.x,bar_settings.y)
display_widget(v,bar_settings)
cairo_destroy(cr)
cr = nil
end
cairo_surface_destroy(cs)
end
function rgb_to_r_g_b2(tcolour)
local colour,alpha=tcolour[2],tcolour[3]
return ((colour / 0x10000) % 0x100) / 255., ((colour / 0x100) % 0x100) / 255., (colour % 0x100) / 255., alpha
end
function set_pattern(t,pts)
--this function set the pattern
if #t.colour==1 then
cairo_set_source_rgba(cr,rgb_to_r_g_b2(t.colour[1]))
else
local pat = cairo_pattern_create_linear (pts[1],pts[2],pts[3],pts[4])
for i=1, #t.colour do
cairo_pattern_add_color_stop_rgba (pat, t.colour[i][1], rgb_to_r_g_b2(t.colour[i]))
end
cairo_set_source (cr, pat)
cairo_pattern_destroy(pat)
end
end
function display_background(cs,b)
function table.copy(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = {v[1],v[2]}
end
return t2
end
function draw_corner(num,t)
local shape=t[1]
local radius=t[2]
local x,y = t[3],t[4]
if shape=="line" then
if num == 1 then cairo_line_to(cr,radius,0)
elseif num == 2 then cairo_line_to(cr,x,radius)
elseif num == 3 then cairo_line_to(cr,x-radius,y)
elseif num == 4 then cairo_line_to(cr,0,y-radius)
end
end
if shape=="circle" then
local PI = math.pi
if num == 1 then cairo_arc(cr,radius,radius,radius,-PI,-PI/2)
elseif num == 2 then cairo_arc(cr,x-radius,y+radius,radius,-PI/2,0)
elseif num == 3 then cairo_arc(cr,x-radius,y-radius,radius,0,PI/2)
elseif num == 4 then cairo_arc(cr,radius,y-radius,radius,PI/2,-PI)
end
end
if shape=="curve" then
if num == 1 then cairo_curve_to(cr,0,radius ,0,0 ,radius,0)
elseif num == 2 then cairo_curve_to(cr,x-radius,0, x,y, x,radius)
elseif num == 3 then cairo_curve_to(cr,x,y-radius, x,y, x-radius,y)
elseif num == 4 then cairo_curve_to(cr,radius,y, x,y, 0,y-radius)
end
end
end
local table_corners={"circle","curve","line"}
if b.draw_me==true then b.draw_me = nil end
if b.draw_me~=nil and conky_parse(tostring(b.draw_me)) ~= "1" then return end
--check values and set default values
if b.height == nil then b.height = conky_window.height end
if b.width == nil then b.width = conky_window.width end
b.w,b.h = b.width,b.height
if b.w == nil then b.w = conky_window.width end
if b.h == nil then b.h = conky_window.height end
if b.colour==nil then b.colour={{0 ,0xffffff,1},
--{0.5 ,0xeeeeee,1},
--{1 ,0xaaaaaa,1}
} end
if b.corners == nil then b.corners={ {"line",0} } end
local t_corners = {}
local t_corners = table.copy(b.corners)
--don't use t_corners=b.corners otherwise b.corners is altered
--complete the t_corners table if needed
for i=#t_corners+1,4 do
t_corners[i]=t_corners[#t_corners]
local flag=false
for j,v in pairs(table_corners) do flag=flag or (t_corners[i][1]==v) end
if not flag then print ("error in corners table :",t_corners[i][1]);t_corners[i][1]="curve" end
end
--this way :
-- t_corners[1][4]=x
-- t_corners[2][3]=y
--doesn't work
t_corners[1]={t_corners[1][1],t_corners[1][2],0,0}
t_corners[2]={t_corners[2][1],t_corners[2][2],b.width,0}
t_corners[3]={t_corners[3][1],t_corners[3][2],b.width,b.height}
t_corners[4]={t_corners[4][1],t_corners[4][2],0,b.height}
for i=1, #b.colour do
if #b.colour[i]~=3 then
print ("error in background color table")
bar.colour[i]={1,0xFFFFFF,1}
end
end
cr = cairo_create (cs)
set_pattern(b,{b.x,b.y,b.x,b.x+b.height})
--cairo_rectangle(cr,b.x,b.y,b.width,b.height)
cairo_translate(cr, b.x, b.y)
local tc=t_corners
cairo_move_to(cr,tc[1][2],0)
cairo_line_to(cr,b.w-tc[2][2],0)
draw_corner(2,tc[2])
cairo_line_to(cr,b.w,b.h-tc[3][2])
draw_corner(3,tc[3])
cairo_line_to(cr,tc[4][2],b.h)
draw_corner(4,tc[4])
cairo_line_to(cr,0,tc[1][2])
draw_corner(1,tc[1])
cairo_fill(cr)
cairo_destroy(cr)
end
function display_text(t,b,te)
-- if t.clear then
-- cairo_set_operator(cr,CAIRO_OPERATOR_CLEAR)
--else
-- set_pattern(t,{0,0,0,b.height})
--end
cairo_save(cr)
cairo_translate(cr,t.xt,t.yt)
cairo_rotate(cr,t.angle*math.pi/180)
local mx,my=0,0
if t.h_align=="c" then
mx=-te.width/2-te.x_bearing
elseif t.h_align=="r" then
mx=-te.width
end
if t.v_align=="m" then
my=-te.height/2-te.y_bearing
elseif t.v_align=="t" then
my=-te.y_bearing
end
cairo_move_to(cr,mx,my)
cairo_show_text(cr,t.text)
cairo_stroke(cr)
cairo_restore(cr)
end
function display_widget(t,bar)
if t.draw_me==true then t.draw_me = nil end
if t.draw_me~=nil and conky_parse(tostring(t.draw_me)) ~= "1" then return end
--set default values if needed
if t.style == nil then t.style = "circle" end
if t.style ~= "text" then
if t.name==nil and t.arg==nil then
print ("No input values ... use parameters 'name' with 'arg' or only parameter 'arg' ")
return
end
if t.max==nil then
print ("No maximum value defined, use 'max'")
return
end
end
if t.name==nil then t.name="" end
if t.arg==nil then t.arg="" end
if t.text==nil then t.text="" end
if t.xt==nil then t.xt = bar.width/2 end
if t.yt==nil then t.yt = bar.height/2 end
if t.angle==nil then t.angle=0 end
if t.colour==nil then t.colour={{1,0xFFFFFF,1}} end
if t.font_name==nil then t.font_name="Free Sans" end
if t.font_size==nil then t.font_size=14 end
if t.italic==nil then t.italic=false end
if t.oblique==nil then t.oblique=false end
if t.bold==nil then t.bold=false end
if t.radius == nil then t.radius = 90 end
--if t.radius > 100 then t.radius = 100 end
if t.start==nil then t.start = 0 end
if t.inverse==nil then t.inverse=false end
if t.hand==nil then t.hand=0 end
if t.thickness== nil then t.thickness = 2 end
if t.draw_border==nil then t.draw_border=true end
if t.width== nil then t.width = 100 end
if t.height==nil then t.height=10 end
if t.t_align== nil then t.t_align = "l" end
if t.b_align== nil then t.b_align = "l" end
if t.h_align==nil then t.h_align="l" end
if t.v_align==nil then t.v_align="b" end
if t.style=="text" and t.yt==nil then t.yt = conky_window.height/2 end
if t.style=="bar" then
if t.xw == nil then t.xw = bar.width/2 end
if t.yw == nil then t.yw = bar.height*0.52 end
if t.width == nil then t.width = 100 end
if t.height == nil then t.height = 10 end
end
if t.style=="circle" then
if t.yw == nil then t.yw = bar.height/2 end
if t.xw == nil then t.xw = bar.width/2 end
end
if t.style=="graph" then
if t.xw == nil then t.xw = bar.width/2 end
if t.yw == nil then t.yw = bar.height*0.52 end
if t.auto_scale== nil then t.auto_scale=false end
if t.fill_graph== nil then t.fill_graph=false end
end
if t.xw == nil then t.xw = t.xt end
if t.yw == nil then t.yw = t.yt end
if t.yt == nil then t.yt = t.yw end
-- if t.h_align==nil then t.h_align="l" end
-- if t.v_align==nil then t.v_align="b" end
--if t.reflection_alpha == nil then t.reflection_alpha=0 end
--if t.reflection_length == nil then t.reflection_length=1 end
--if t.reflection_scale == nil then t.reflection_scale=1 end
--if t.skew_x==nil then t.skew_x=0 end
--if t.skew_y==nil then t.skew_y=0 end
local slant = CAIRO_FONT_SLANT_NORMAL
local weight = CAIRO_FONT_WEIGHT_NORMAL
if t.italic then slant = CAIRO_FONT_SLANT_ITALIC end
if t.oblique then slant = CAIRO_FONT_SLANT_OBLIQUE end
if t.bold then weight = CAIRO_FONT_WEIGHT_BOLD end
for i=1, #t.colour do
if #t.colour[i]~=3 then
print ("error in color table")
t.colour[i]={1,0xFFFFFF,1}
end
end
cairo_select_font_face(cr, t.font_name, slant,weight)
cairo_set_font_size(cr,t.font_size)
local te=cairo_text_extents_t:create()
tolua.takeownership(te)
t.text=conky_parse(t.text)
cairo_text_extents (cr,t.text,te)
if t.clear then
cairo_set_operator(cr,CAIRO_OPERATOR_CLEAR)
else
--set_pattern(t,{bar.height/2,0,-bar.height/2,0})
set_pattern(t,{0,0,0,bar.height})
end
if t.style=="circle" then
display_circle(t,bar,te)
elseif t.style=="bar" then
display_bar(t,bar,te)
elseif t.style == "text" then
display_text(t,bar, te)
elseif t.style=="graph" then
display_graph(t,bar, te)
end
end
function get_value(t)
local value = 0
if t.name ~="" then
value = tonumber(conky_parse(string.format('${%s %s}', t.name, t.arg)))
--$to_bytes doesn't work when value has a decimal point,
--https://garage.maemo.org/plugins/ggit/browse.php/?p=monky;a=commitdiff;h=174c256c81a027a2ea406f5f37dc036fac0a524b;hp=d75e2db5ed3fc788fb8514121f67316ac3e5f29f
--http://sourceforge.net/tracker/index.php?func=detail&aid=3000865&group_id=143975&atid=757310
--conky bug?
--value = (conky_parse(string.format('${%s %s}', t.name, t.arg)))
--if string.match(value,"%w") then
-- value = conky_parse(string.format('${to_bytes %s}',value))
--end
else
value = tonumber(t.arg)
end
if value==nil then value =0 end
return value
end
function display_circle(t,b,te)
if t.text ~= "" then display_text(t,b,te) end
cairo_save(cr)
cairo_translate(cr,t.xw,t.yw)
cairo_rotate(cr,-math.pi/2)
local r = b.height*t.radius/200
cairo_set_line_width(cr,t.thickness)
if t.xw == nil then
t.xw = r+te.height+t.thickness
else
t.xw= t.xw-t.xt
end
if t.draw_border then
cairo_arc(cr,0,0,r,0,2*math.pi)
cairo_stroke(cr)
end
local pct = get_value(t)/t.max
cairo_move_to(cr,0,0)
cairo_rotate(cr,t.start*math.pi/180)
if t.hand >0 then
cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND)
if t.inverse then
cairo_rotate(cr,-2*math.pi*pct)
else
cairo_rotate(cr,-2*math.pi*(1-pct))
end
cairo_line_to(cr,t.hand*r/100,0)
cairo_stroke(cr)
else
if t.inverse then
cairo_arc_negative(cr,0,0,r,0,-2*math.pi*pct)
else
cairo_arc(cr,0,0,r,0,-2*math.pi*(1-pct))
end
end
cairo_fill(cr)
cairo_restore(cr)
end
function display_bar(t,b,te)
if t.text ~= "" then display_text(t,b,te) end
cairo_translate(cr,t.xw,t.yw)
cairo_save(cr)
cairo_set_line_width(cr,t.thickness)
if t.draw_border then
cairo_rectangle(cr,0,0,t.width,t.height)
cairo_stroke(cr)
end
local pct = get_value(t)/t.max
cairo_move_to(cr,0,0)
if t.inverse then
cairo_rectangle(cr,t.width*(1-pct),0,t.width-t.width*(1-pct),t.height)
else
cairo_rectangle(cr,0,0,t.width*pct,t.height)
end
cairo_fill(cr)
cairo_restore(cr)
end
function display_graph(t,b,te)
if t.text ~= "" then display_text(t,b,te) end
cairo_translate(cr,t.xw,t.yw)
cairo_save(cr)
cairo_set_line_width(cr,t.thickness)
if t.draw_border then
cairo_rectangle(cr,0,0,t.width,t.height)
cairo_stroke(cr)
end
local pct = get_value(t)/t.max
for i=2,t.width do
graphs[t.number][i-1]=graphs[t.number][i]
end
graphs[t.number][t.width]=get_value(t)
local automax=0
if t.auto_scale then
for i=1,t.width do
automax = math.max (automax,graphs[t.number][i])
end
else
automax=t.max
end
for i=1,t.width do
if t.inverse then
cairo_line_to(cr, i, (automax-graphs[t.number][t.width-i+1])/automax*t.height)
else
cairo_line_to(cr, i, (automax-graphs[t.number][i])/automax*t.height)
end
end
if t.fill_graph then
cairo_line_to(cr,t.width,t.height)
cairo_line_to(cr,0,t.height)
cairo_close_path(cr)
cairo_fill(cr)
else
cairo_stroke(cr)
end
cairo_restore(cr)
end