123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- -- @author cedlemo
- local setmetatable = setmetatable
- local ipairs = ipairs
- local math = math
- local table = table
- local type = type
- local string = string
- local color = require("gears.color")
- local base = require("wibox.widget.base")
- local helpers = require("blingbling.helpers")
- local superproperties = require('blingbling.superproperties')
- ---Triangular progress graph widget.
- --@module blingbling.triangular_progress_graph
- ---Fill all the widget (width * height) with this color (default is transparent ).
- --@usage myvolume:set_background_color(string) -->"#rrggbbaa"
- --@name set_background_color
- --@class function
- --@param color a string "#rrggbbaa" or "#rrggbb"
- ---Define the form of the graph: use five growing bars instead of a triangle.
- --@usage myvolume:set_bar(boolean) --> true or false
- --@name set_bar
- --@class function
- --@param boolean true or false (default is false)
- ---Define the top and bottom margin for the graph.
- --@usage myvolume:set_v_margin(integer)
- --@name set_v_margin
- --@class function
- --@param margin an integer for top and bottom margin
- ---Define the left and right margin for the graph.
- --@usage myvolume:set_h_margin(integer)
- --@name set_h_margin
- --@class function
- --@param margin an integer for left and right margin
- ---Set the color of the graph background.
- --@usage myvolume:set_filled_color(string) -->"#rrggbbaa"
- --@name set_filled_color
- --@class function
- --@param color a string "#rrggbbaa" or "#rrggbb"
- ----Define the graph color.
- --@usage myvolume:set_graph_color(string) -->"#rrggbbaa"
- --@name set_graph_color
- --@class function
- --@param color a string "#rrggbbaa" or "#rrggbb"
- ---Display text on the graph or not.
- --@usage myvolume:set_show_text(boolean) --> true or false
- --@name set_show_text
- --@class function
- --@param boolean true or false (default is false)
- ---Define the color of the text.
- --@usage myvolume:set_text_color(string) -->"#rrggbbaa"
- --@name set_text_color
- --@class function
- --@param color a string "#rrggbbaa" or "#rrggbb" defaul is white
- ---Define the background color of the text.
- --@usage myvolume:set_text_background_color(string) -->"#rrggbbaa"
- --@name set_text_background_color
- --@class function
- --@param color a string "#rrggbbaa" or "#rrggbb"
- ---Define the text font size.
- --myvolume:set_font_size(integer)
- --@name set_font_size
- --@class function
- --@param graph the graph
- --@param size the font size
- ---Define the template of the text to display.
- --@usage myvolume:set_label(string)
- --By default the text is : (value_send_to_the_widget *100) .. "%"
- --static string: example set_label("Volume:") will display "Volume:" on the graph
- --dynamic string: use $percent in the string example set_label("Volume $percent %") will display "Volume 10%"
- --@name set_label
- --@class function
- --@param graph the graph
- --@param text the text to display
- local triangular_progressgraph = { mt = {} }
- local data = setmetatable({}, { __mode = "k" })
- local properties = {"width", "height", "v_margin", "h_margin", "background_color", "graph_background_color", "graph_color","graph_line_color","show_text", "text_color", "text_background_color" ,"label", "font_size","font", "bar"}
- function triangular_progressgraph.draw(tp_graph, wibox, cr, width, height)
- local v_margin = superproperties.v_margin
- if data[tp_graph].v_margin and data[tp_graph].v_margin <= data[tp_graph].height/4 then
- v_margin = data[tp_graph].v_margin
- end
-
- local h_margin = superproperties.h_margin
- if data[tp_graph].h_margin and data[tp_graph].h_margin <= data[tp_graph].width / 3 then
- h_margin = data[tp_graph].h_margin
- end
-
- local background_color = data[tp_graph].background_color or superproperties.background_color
- local rounded_size = data[tp_graph].rounded_size or superproperties.rounded_size
- local graph_background_color = data[tp_graph].graph_background_color or superproperties.graph_background_color
- local graph_color = data[tp_graph].graph_color or superproperties.graph_color
- local graph_line_color = data[tp_graph].graph_line_color or superproperties.graph_line_color
- local text_color = data[tp_graph].text_color or superproperties.text_color
- local text_background_color = data[tp_graph].text_background_color or superproperties.text_background_color
- local font_size =data[tp_graph].font_size or superproperties.font_size
- local font = data[tp_graph].font or superproperties.font
- --Generate Background (background color and Tiles)
- r,g,b,a = helpers.hexadecimal_to_rgba_percent(background_color)
- cr:set_source_rgba(r,g,b,a)
- cr:paint()
- --Drawn the tp_graph
-
- if data[tp_graph].value > 0 then
- if data[tp_graph].bar == true then
- --4 bar are use to represent data:
- --bar width:
- local nb_bar=5
- local bar_separator = 2
- local bar_width
- bar_width=math.floor((data[tp_graph].width -((2*h_margin) + ((nb_bar - 1) * bar_separator)))/nb_bar)
- local h_rest =data[tp_graph].width -( 2*h_margin +((nb_bar -1)*bar_separator) + nb_bar * bar_width)
- if h_rest ==2 or h_rest == 3 then
- h_rest = 1
- end
- if h_rest == 4 then
- h_rest = 2
- end
- --Drawn background graph
- x=h_margin+h_rest
- y=data[tp_graph].height - v_margin
- for i=1, nb_bar do
- cr:rectangle(x,y-((0.2*i)*(data[tp_graph].height - 2*v_margin)),bar_width,((0.2*i)*(data[tp_graph].height - 2*v_margin)))
- x=x+(bar_width + bar_separator)
- end
- r,g,b,a=helpers.hexadecimal_to_rgba_percent(graph_background_color)
- cr:set_source_rgba(r, g, b, a)
- cr:fill()
- --Drawn the graph
- --find nb column to drawn:
- local ranges={0,0.2,0.4,0.6,0.8,1,1.2}
- nb_bar=0
- for i, limite in ipairs(ranges) do
- if data[tp_graph].value < limite then
- --helpers.dbg({data[tp_graph].value, limite})
- nb_bar = i-1
- break
- end
- end
- x=h_margin+h_rest
- y=data[tp_graph].height - v_margin
- for i=1, nb_bar do
- if i ~= nb_bar then
- cr:rectangle(x,y-((0.2*i)*(data[tp_graph].height - 2*v_margin)),bar_width,(0.2*i)*(data[tp_graph].height - 2*v_margin))
- x=x+(bar_width + bar_separator)
- else
- val_to_display =data[tp_graph].value - ((nb_bar-1) * 0.2)
- cr:rectangle(x,y-((0.2*i)*(data[tp_graph].height - 2*v_margin)),bar_width * (val_to_display/0.2),(0.2*i)*(data[tp_graph].height - 2*v_margin))
- end
- end
-
- r,g,b,a=helpers.hexadecimal_to_rgba_percent(graph_color)
- cr:set_source_rgba(r, g, b, a)
- cr:fill()
- else
- x=h_margin
- y=data[tp_graph].height-(v_margin)
-
- cr:new_path()
- cr:move_to(x,y)
- cr:line_to(x,y)
- y_range=data[tp_graph].height - (2 * v_margin)
- cr:line_to(data[tp_graph].width + h_margin,data[tp_graph].height -( v_margin + y_range ))
- cr:line_to(data[tp_graph].width + h_margin, data[tp_graph].height - (v_margin ))
- cr:line_to(h_margin,data[tp_graph].height-(v_margin))
-
- cr:close_path()
-
- r,g,b,a = helpers.hexadecimal_to_rgba_percent(graph_background_color)
- cr:set_source_rgba(r, g, b,a)
- cr:fill()
-
- x=h_margin
- y=data[tp_graph].height-(v_margin)
-
- cr:new_path()
- cr:move_to(x,y)
- cr:line_to(x,y)
- y_range=data[tp_graph].height - (2 * v_margin)
- cr:line_to(data[tp_graph].width * data[tp_graph].value + h_margin,data[tp_graph].height -( v_margin + (y_range * data[tp_graph].value)))
- cr:line_to(data[tp_graph].width * data[tp_graph].value + h_margin, data[tp_graph].height - (v_margin ))
- cr:line_to(0+h_margin,data[tp_graph].height-(v_margin))
-
- cr:close_path()
- r,g,b,a=helpers.hexadecimal_to_rgba_percent(graph_color)
- cr:set_source_rgba(r, g, b, a)
- cr:fill()
- x=0+h_margin
- y=data[tp_graph].height-(v_margin)
- cr:new_path()
- cr:move_to(x,y)
- cr:line_to(x,y)
- y_range=data[tp_graph].height - (2 * v_margin)
- cr:line_to((data[tp_graph].width * data[tp_graph].value) + h_margin ,data[tp_graph].height -( v_margin + (y_range * data[tp_graph].value)))
- cr:line_to((data[tp_graph].width * data[tp_graph].value) - h_margin, data[tp_graph].height - (v_margin ))
- cr:set_antialias("subpixel")
- cr:set_line_width(1)
- r,g,b,a=helpers.hexadecimal_to_rgba_percent(graph_line_color)
- cr:set_source_rgb(r, g, b)
-
- cr:stroke()
- end
- end
- --Draw Text and it's background
- if data[tp_graph].show_text == true then
- cr:set_font_size(font_size)
-
- if type(font) == "string" then
- cr:select_font_face(font,nil,nil)
- elseif type(font) == "table" then
- cr:select_font_face(font.family or "Sans", font.slang or "normal", font.weight or "normal")
- end
- local value = data[tp_graph].value * 100
-
- if data[tp_graph].label then
- text=string.gsub(data[tp_graph].label,"$percent", value)
- else
- text=value .. "%"
- end
- helpers.draw_text_and_background(cr,
- text,
- h_margin,
- (data[tp_graph].height/2) ,
- text_background_color,
- text_color,
- false,
- true,
- false,
- false)
- end
- end
- function triangular_progressgraph.fit(tp_graph, width, height)
- return data[tp_graph].width, data[tp_graph].height
- end
- ---Set the tp_graph value.
- --@param tp_graph The progress bar.
- --@param value The progress bar value between 0 and 1.
- local function set_value(tp_graph, value)
- local value = value or 0
- local max_value = data[tp_graph].max_value
- data[tp_graph].value = math.min(max_value, math.max(0, value))
- tp_graph:emit_signal("widget::updated")
- return tp_graph
- end
- ---Set the tp_graph height.
- -- @param height The height to set.
- function triangular_progressgraph:set_height( height)
- if height >= 5 then
- data[self].height = height
- self:emit_signal("widget::updated")
- end
- return self
- end
- ---Set the tp_graph width.
- --@param width The width to set.
- function triangular_progressgraph:set_width( width)
- if width >= 5 then
- data[self].width = width
- self:emit_signal("widget::updated")
- end
- return self
- end
- -- Build properties function
- for _, prop in ipairs(properties) do
- if not triangular_progressgraph["set_" .. prop] then
- triangular_progressgraph["set_" .. prop] = function(tp_graph, value)
- data[tp_graph][prop] = value
- tp_graph:emit_signal("widget::updated")
- return tp_graph
- end
- end
- end
- --- Create a tp_graph widget.
- -- @param args Standard widget() arguments. You should add width and height
- -- key to set graph geometry.
- -- @return A graph widget.
- function triangular_progressgraph.new(args)
-
- local args = args or {}
- args.width = args.width or 100
- args.height = args.height or 20
- if args.width < 5 or args.height < 5 then return end
- local tp_graph = base.make_widget()
-
- data[tp_graph] = {}
- for _, v in ipairs(properties) do
- data[tp_graph][v] = args[v]
- end
- data[tp_graph].value = 0
- data[tp_graph].max_value = 1
- -- Set methods
- tp_graph.set_value = set_value
- tp_graph.add_value = set_value
- tp_graph.draw = triangular_progressgraph.draw
- tp_graph.fit = triangular_progressgraph.fit
- for _, prop in ipairs(properties) do
- tp_graph["set_" .. prop] = triangular_progressgraph["set_" .. prop]
- end
- return tp_graph
- end
- function triangular_progressgraph.mt:__call(...)
- return triangular_progressgraph.new(...)
- end
- return setmetatable(triangular_progressgraph, triangular_progressgraph.mt)
|