--[[ GRAPH widget v1.0 by wlourf (31.10.2010) this widget draws some graphs with some effects http://u-scripts.blogspot.com/2010/10/graph-widget.html To call the script in a conky, use, before TEXT lua_load /path/to/the/script/graph.lua lua_draw_hook_pre main_graph and add one line (blank or not) after TEXT Parameters are : 3 parameters are mandatory 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 cpu1}, just write arg="cpu1" arg can be a numerical value if name="" max - the maximum value the above variable can reach, for example for {$cpu cpu1}, just write max=100 or less or more Optional parameters: x,y - coordinates of the bottom-left corner of the graph, relative to the top-left corner of the conky window default = bottom-left corner of the conky window width - width of the graph, default = 100 pixels height - height of the graph, default = 20 pixels nb_values - number of values to display in the graph, default=width i.e. 1 pixel for 1 value autoscale - if set to true, calculate the max valeu of the y axis and doesn't use the max parameter above, default=false skew_x - skew graph around x axis, défaut = 0 skew_y - skew graph around y axis, défaut = 0 angle - angle of rotation of the graph in degress, default = 0 i.e. a horizontal graph) inverse - if set to true, graph are draw from right to left, default=false background - if set to false, background is not drawn, default=true foreground - if set to false, foreground is not drawn, default=true foreground = plain graph bg_bd_size - size of the border of the background, default=0=no border fg_bd_size - size of the border of the foreground, default=0=no border Colours tables below are defined into braces : {position in the gradient (0 to 1), colour in hexadecimal, alpha (0 to 1)} example for a single colour table : {{0,0xFFAA00,1}} position parameter doesn't matter example for a two-colours table : {{0,0xFFAA00,1},{1,0x00AA00,1}} or {{0.5,0xFFAA00,1},{1,0x00AA00,1}} example for a three-colours table : {{0,0xFFAA00,1},{0.5,0xFF0000,1},{1,0x00AA00,1}} bg_colour - colour table for background, default = {{0,0x000000,.5},{1,0xFFFFFF,.5}} fg_colour - colour table for foreground, default = {{0,0x00FFFF,1},{1,0x0000FF,1}} bg_bd_colour- colour table for background border, default = {{1,0xFFFFFF,1}} fg_bd_colour- colour table for foreground border, default = {{1,0xFFFF00,1}} bg_orientation, bg_bd_orientation, fg_orientation, fg_bd_orientation, - "orientation" defines the starting point of the gradient, default="nn" there are 8 available starting points : "nw","nn","ne","ee","se","ss","sw","ww" (n for north, w for west ...) theses 8 points are the 4 corners + the 4 middles of graph so a gradient "nn" will go from "nn" to "ss" a gradient "nw" will go from "nw" to "se" v1.0 (31 Oct. 2010) original release -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation version 3 (GPLv3) -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -- MA 02110-1301, USA. ]] require 'cairo' function set_settings() graph_settings={ { name="cpu", arg="", max=100, y=87, x=5, autoscale=false, width=215, height=29, nb_values=120, fg_bd_size=2, bg_colour = {{0,0x007AF6,0},{1,0x000000,0}}, --fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFFA209,1},{1,0xFFFF00,1}}, fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFF3300,1},{1,0xFFFFFF,1}}, --fg_colour = { {0,0xFF0000,1},{0.5,0xFFA209,1},{1,0xFFFF00,1}}, fg_colour = { {0,0x00CCFF,0.7},{0.5,0x0000FF,0.7},{1,0x000000,0.1}}, foreground=true, fg_orientation="ne", bg_bd_orientation="nn", bg_orientation="ne", }, { name="upspeedf", arg="wlan0", max=9999, y=233, x=5, autoscale=true, width=275, height=35, nb_values=120, fg_bd_size=1, bg_colour = {{0,0x007AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFFA209,0.8},{1,0xFFFF00,0.6}}, fg_colour = { {0,0xFF0000,0.65},{0.5,0xFFA209,0.5},{1,0xFFFF00,0.3}}, foreground=true, inverse=true, DrawMe="${if_up wlan0}1${else}0$endif", bg_orientation="ww", }, { name="downspeedf", arg="wlan0", max=9999, y=233, x=525, autoscale=true, width=275, height=35, nb_values=120, fg_bd_size=1, bg_colour = {{0,0x007AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFFA209,0.8},{1,0xFFFF00,0.6}}, fg_colour = { {0,0xFF0000,0.65},{0.5,0xFFA209,0.5},{1,0xFFFF00,0.3}}, foreground=true, DrawMe="${if_up wlan0}1${else}0$endif", bg_orientation="ee", }, { name="upspeedf", arg="gprs0", max=9999, y=233, x=5, autoscale=true, width=275, height=35, nb_values=120, fg_bd_size=1, bg_colour = {{0,0x007AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFFA209,0.8},{1,0xFFFF00,0.6}}, fg_colour = { {0,0xFF0000,0.65},{0.5,0xFFA209,0.5},{1,0xFFFF00,0.3}}, foreground=true, inverse=true, DrawMe="${if_up gprs0}1${else}0$endif", bg_orientation="ww", }, { name="downspeedf", arg="gprs0", max=9999, y=233, x=525, autoscale=true, width=275, height=35, nb_values=120, fg_bd_size=1, bg_colour = {{0,0x007AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xFF0000,1},{0.5,0xFFA209,0.8},{1,0xFFFF00,0.6}}, fg_colour = { {0,0xFF0000,0.65},{0.5,0xFFA209,0.5},{1,0xFFFF00,0.3}}, foreground=true, DrawMe="${if_up gprs0}1${else}0$endif", bg_orientation="ee", }, { name="loadavg", arg="1", max=20, y=95, x=372, autoscale=true, width=140, height=36, nb_values=100, fg_bd_size=0, bg_colour = {{0,0x667AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xdd0000,0.7},{0.5,0xdddd00,0.7},{1,0xFFFF00,0.7}}, fg_colour = { {0,0x000000,0.7},{0.5,0xdd0000,0.7},{1,0xff0000,0.7}}, foreground=true, }, { name="to_bytes ${diskio", arg="mmcblk0}", max=2500000, y=187, x=640, autoscale=true, width=160, height=89, nb_values=130, fg_bd_size=0, bg_colour = {{0,0x667AF6,0},{1,0x000000,0}}, fg_bd_colour = { {0,0xdd0000,1},{0.5,0xdddd00,1},{1,0xFFFF00,1}}, fg_colour = { {1,0x111111,0.3},{0.5,0x33cc00,0.6},{0,0x00FF00,0.8}}, foreground=true, bg_orientation="ne", fg_orientation="ee", }, } end function check_settings(t) --tables are check only when conky start if t.name==nil and t.arg==nil then print ("No input values ... use parameters 'name'" .. " with 'arg' or only parameter 'arg' ") return 1 end if t.max==nil then print ("No maximum value defined, use 'max'") print ("for name=" .. t.name .. " with arg=" .. t.arg) return 1 end if t.name==nil then t.name="" end if t.arg==nil then t.arg="" end return 0 end function conky_main_graph() if conky_window == nil then return end local w=conky_window.width local h=conky_window.height local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h) cr=cairo_create(cs) updates=tonumber(conky_parse('${updates}')) --start drawing after "updates_gap" updates --prevent segmentation error for cpu updates_gap=5 if updates==1 then set_settings() flagOK=0 for i in pairs(graph_settings) do if graph_settings[i].width==nil then graph_settings[i].width=100 end if graph_settings[i].nb_values==nil then graph_settings[i].nb_values= graph_settings[i].width end --create an empty table to store values graph_settings[i]["values"]={} --beginning point graph_settings[i].beg = graph_settings[i].nb_values --graph_settings[i].beg = 0 for j =1, graph_settings[i].nb_values do graph_settings[i].values[j]=0 end graph_settings[i].flag_init=true flagOK=flagOK + check_settings(graph_settings[i]) end end if flagOK>0 then --abort script if error in one of the tables print ("ERROR : Check the graph_setting table") return end --drawing process if updates > updates_gap then for i in pairs(graph_settings) do if (graph_settings[i].DrawMe==nil or conky_parse(graph_settings[i].DrawMe) == "1") then --print(graph_settings[i].DrawMe.."= '"..conky_parse(graph_settings[i].DrawMe).."'") --return --cancel fetch value from conky if interface down or whatever local nb_values=graph_settings[i].nb_values graph_settings[i].automax=0 for j =1, nb_values do if graph_settings[i].values[j+1]==nil then graph_settings[i].values[j+1]=0 end graph_settings[i].values[j]=graph_settings[i].values[j+1] if j==nb_values then --store value if graph_settings[i].name=="" then value=graph_settings[i].arg else value=tonumber(conky_parse('${' .. graph_settings[i].name .. " " .. graph_settings[i].arg ..'}')) end graph_settings[i].values[nb_values]=value end graph_settings[i].automax=math.max(graph_settings[i].automax, graph_settings[i].values[j]) if graph_settings[i].automax == 0 then graph_settings[i].automax = 1 end --should stop weird glitches at beginning when no values reported yet for upspeed or diskio end draw_graph(graph_settings[i]) end end end cairo_destroy(cr) cairo_surface_destroy(cs) updates=nil updates_gap=nil end function draw_graph(t) --drawing function local function rgb_to_r_g_b(colour) return ((colour[2] / 0x10000) % 0x100) / 255., ((colour[2] / 0x100) % 0x100) / 255., (colour[2] % 0x100) / 255., colour[3] end local function linear_orientation(o,w,h) --set gradient for bg and bg border local p if o=="nn" then p={w/2,h,w/2,0} elseif o=="ne" then p={w,h,0,0} elseif o=="ww" then p={0,h/2,w,h/2} elseif o=="se" then p={w,0,0,h} elseif o=="ss" then p={w/2,0,w/2,h} elseif o=="ee" then p={w,h/2,0,h/2} elseif o=="sw" then p={0,0,w,h} elseif o=="nw" then p={0,h,w,0} end return p end local function linear_orientation_inv(o,w,h) --set gradient for fg and fg border local p if o=="ss" then p={w/2,h,w/2,0} elseif o=="sw" then p={w,h,0,0} elseif o=="ee" then p={0,h/2,w,h/2} elseif o=="nw" then p={w,0,0,h} elseif o=="nn" then p={w/2,0,w/2,h} elseif o=="ww" then p={w,h/2,0,h/2} elseif o=="ne" then p={0,0,w,h} elseif o=="se" then p={0,h,w,0} end return p end if t.DrawMe~=nil and conky_parse(t.DrawMe) ~= "1" then --print(t.DrawMe.."= '"..conky_parse(t.DrawMe).."'") return --else -- print(t.name) end --cancel drawing for same reason as earlier --set default values if t.height==nil then t.height=20 end --checked in previous part : width and nb_values if t.background==nil then t.background=true end if t.bg_bd_size==nil then t.bg_bd_size=0 end if t.x==nil then t.x=t.bg_bd_size end if t.y==nil then t.y=conky_window.height -t.bg_bd_size end if t.bg_colour==nil then t.bg_colour={{0,0x000000,.5},{1,0xFFFFFF,.5}} end if t.bg_bd_colour==nil then t.bg_bd_colour={{1,0xFFFFFF,1}} end if t.foreground==nil then t.foreground=true end if t.fg_colour==nil then t.fg_colour={{0,0x00FFFF,1},{1,0x0000FF,1}} end if t.fg_bd_size==nil then t.fg_bd_size=0 end if t.fg_bd_colour==nil then t.fg_bd_colour={{1,0xFFFF00,1}} end if t.autoscale==nil then t.autoscale=false end if t.inverse==nil then t.inverse=false end if t.angle==nil then t.angle=0 end if t.bg_bd_orientation==nil then t.bg_bd_orientation="nn" end if t.bg_orientation==nil then t.bg_orientation="nn" end if t.fg_bd_orientation==nil then t.fg_bd_orientation="nn" end if t.fg_orientation==nil then t.fg_orientation="nn" end --check colours tables for i=1, #t.fg_colour do if #t.fg_colour[i]~=3 then print ("error in fg_colour table") t.fg_colour[i]={1,0x0000FF,1} end end for i=1, #t.fg_bd_colour do if #t.fg_bd_colour[i]~=3 then print ("error in fg_bd_colour table") t.fg_bd_colour[i]={1,0x00FF00,1} end end for i=1, #t.bg_colour do if #t.bg_colour[i]~=3 then print ("error in background color table") t.bg_colour[i]={1,0xFFFFFF,0.5} end end for i=1, #t.bg_bd_colour do if #t.bg_bd_colour[i]~=3 then print ("error in background border color table") t.bg_bd_colour[i]={1,0xFFFFFF,1} end end --calculate skew parameters if needed if t.flag_init then if t.skew_x == nil then t.skew_x=0 else t.skew_x = math.pi*t.skew_x/180 end if t.skew_y == nil then t.skew_y=0 else t.skew_y = math.pi*t.skew_y/180 end t.flag_init=false end cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND) cairo_set_line_join(cr,CAIRO_LINE_JOIN_ROUND) local matrix0 = cairo_matrix_t:create() tolua.takeownership(matrix0) cairo_save(cr) cairo_matrix_init (matrix0, 1,t.skew_y,t.skew_x,1,0,0) cairo_transform(cr,matrix0) local ratio=t.width/t.nb_values cairo_translate(cr,t.x,t.y) cairo_rotate(cr,t.angle*math.pi/180) cairo_scale(cr,1,-1) --background if t.background then local pts=linear_orientation(t.bg_orientation,t.width,t.height) local pat = cairo_pattern_create_linear (pts[1],pts[2],pts[3],pts[4]) for i=1, #t.bg_colour do --print ("i",i,t.colour[i][1], rgb_to_r_g_b(t.colour[i])) cairo_pattern_add_color_stop_rgba (pat, t.bg_colour[i][1], rgb_to_r_g_b(t.bg_colour[i])) end cairo_set_source (cr, pat) cairo_rectangle(cr,0,0,t.width,t.height) cairo_fill(cr) cairo_pattern_destroy(pat) end --autoscale cairo_save(cr) if t.autoscale then t.max= t.automax*1.1 end local scale_x = t.width/(t.nb_values-1) local scale_y = t.height/t.max --define first point of the graph if updates-updates_gap 0 then local pts=linear_orientation_inv(t.fg_bd_orientation,t.width,t.height) local pat = cairo_pattern_create_linear (pts[1],pts[2],pts[3],pts[4]) for i=1,#t.fg_bd_colour,1 do cairo_pattern_add_color_stop_rgba (pat, 1-t.fg_bd_colour[i][1], rgb_to_r_g_b(t.fg_bd_colour[i])) end cairo_set_source (cr, pat) cairo_move_to(cr,t.beg*scale_x,t.values[t.beg+1]*scale_y) for i=t.beg, t.nb_values-1 do cairo_line_to(cr,i*scale_x,t.values[i+1]*scale_y) end cairo_set_line_width(cr,t.fg_bd_size) cairo_stroke(cr) cairo_pattern_destroy(pat) end cairo_restore(cr) --background border if t.bg_bd_size>0 then local pts=linear_orientation(t.bg_bd_orientation,t.width,t.height) local pat = cairo_pattern_create_linear (pts[1],pts[2],pts[3],pts[4]) for i=1, #t.bg_bd_colour do --print ("i",i,t.colour[i][1], rgb_to_r_g_b(t.colour[i])) cairo_pattern_add_color_stop_rgba (pat, t.bg_bd_colour[i][1], rgb_to_r_g_b(t.bg_bd_colour[i])) end cairo_set_source (cr, pat) cairo_rectangle(cr,0,0,t.width,t.height) cairo_set_line_width(cr,t.bg_bd_size) cairo_stroke(cr) cairo_pattern_destroy(pat) end cairo_restore(cr) end