progress_graph.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. --@author cedlemo
  2. local setmetatable = setmetatable
  3. local ipairs = ipairs
  4. local type = type
  5. local math = math
  6. local string = string
  7. local helpers = require('blingbling.helpers')
  8. local base = require("wibox.widget.base")
  9. local color = require("gears.color")
  10. local superproperties = require('blingbling.superproperties')
  11. --- A progress graph widget.
  12. --@module blingbling.progress_graph
  13. local progressgraph = { mt = {} }
  14. ---Fill all the widget (width * height) with this color (default is none ).
  15. --@usage mygraph:set_background_color(string) -->"#rrggbbaa"
  16. --@name set_background_color
  17. --@class function
  18. --@param graph the graph
  19. --@param color a string "#rrggbbaa" or "#rrggbb"
  20. ---Fill the graph area background with this color (default is none).
  21. --@usage mygraph:set_graph_background_color(string) -->"#rrggbbaa"
  22. --@name set_graph_background_color
  23. --@class function
  24. --@param graph the graph
  25. --@param color a string "#rrggbbaa" or "#rrggbb"
  26. ---Set rounded corners for background and graph background.
  27. --@usage mygraph:set_rounded_size(a) -> a in [0,1]
  28. --@name set_rounded_size
  29. --@class function
  30. --@param graph the graph
  31. --@param rounded_size float in [0,1]
  32. ---Define the top and bottom margin for the graph area.
  33. --@usage mygraph:set_v_margin(integer)
  34. --@name set_v_margin
  35. --@class function
  36. --@param graph the graph
  37. --@param margin an integer for top and bottom margin
  38. ---Define the left and right margin for the graph area.
  39. --@usage mygraph:set_h_margin(integer)
  40. --@name set_h_margin
  41. --@class function
  42. --@param graph the graph
  43. --@param margin an integer for left and right margin
  44. ---Define the graph color.
  45. --@usage mygraph:set_graph_color(string) -->"#rrggbbaa"
  46. --@name set_graph_color
  47. --@class function
  48. --@param graph the graph
  49. --@param color a string "#rrggbbaa" or "#rrggbb"
  50. ---Define the graph outline.
  51. --@usage mygraph:set_graph_line_color(string) -->"#rrggbbaa"
  52. --@name set_graph_line_color
  53. --@class function
  54. --@param graph the graph
  55. --@param color a string "#rrggbbaa" or "#rrggbb"
  56. ---Display text on the graph or not.
  57. --@usage mygraph:set_show_text(boolean) --> true or false
  58. --@name set_show_text
  59. --@class function
  60. --@param graph the graph
  61. --@param boolean true or false (default is false)
  62. ---Define the color of the text.
  63. --@usage mygraph:set_text_color(string) -->"#rrggbbaa"
  64. --@name set_text_color
  65. --@class function
  66. --@param graph the graph
  67. --@param color a string "#rrggbbaa" or "#rrggbb" defaul is white
  68. ---Define the background color of the text.
  69. --@usage mygraph:set_text_background_color(string) -->"#rrggbbaa"
  70. --@name set_text_background_color
  71. --@class function
  72. --@param graph the graph
  73. --@param color a string "#rrggbbaa" or "#rrggbb"
  74. ---Define the text font size.
  75. --@usage mygraph:set_font_size(integer)
  76. --@name set_font_size
  77. --@class function
  78. --@param graph the graph
  79. --@param size the font size
  80. ---Define the template of the text to display.
  81. --@usage mygraph:set_label(string)
  82. --By default the text is : (value_send_to_the_widget *100) .. "%"
  83. --static string: example set_label("CPU usage:") will display "CUP usage:" on the graph
  84. --dynamic string: use $percent in the string example set_label("Load $percent %") will display "Load 10%"
  85. --@name set_label
  86. --@class function
  87. --@param graph the graph
  88. --@param text the text to display
  89. ---Define if the graph should increase/decrease horizontaly.
  90. --@usage mygraph:set_horizontal(boolean) --> true or false
  91. --@name set_horizontal
  92. --@class function
  93. --@param graph the graph
  94. --@param boolean true or false (false by default)
  95. local data = setmetatable({}, { __mode = "k" })
  96. local properties = { "width", "height", "v_margin", "h_margin",
  97. "background_color",
  98. "graph_background_color","rounded_size",
  99. "graph_color", "graph_line_color","show_text", "text_color",
  100. "text_background_color" ,"label", "font_size","font","horizontal"}
  101. function progressgraph.draw(p_graph, wibox, cr, width, height)
  102. -- We want one pixel wide lines
  103. cr:set_line_width(1)
  104. -- Set the values we need
  105. local value = data[p_graph].value
  106. local v_margin = superproperties.v_margin
  107. if data[p_graph].v_margin and data[p_graph].v_margin <= data[p_graph].height/4 then
  108. v_margin = data[p_graph].v_margin
  109. end
  110. local h_margin = superproperties.h_margin
  111. if data[p_graph].h_margin and data[p_graph].h_margin <= data[p_graph].width / 3 then
  112. h_margin = data[p_graph].h_margin
  113. end
  114. local background_color = data[p_graph].background_color or superproperties.background_color
  115. local rounded_size = data[p_graph].rounded_size or superproperties.rounded_size
  116. local graph_background_color = data[p_graph].graph_background_color or superproperties.graph_background_color
  117. local graph_color = data[p_graph].graph_color or superproperties.graph_color
  118. local graph_line_color = data[p_graph].graph_line_color or superproperties.graph_line_color
  119. local text_color = data[p_graph].text_color or superproperties.text_color
  120. local text_background_color = data[p_graph].text_background_color or superproperties.text_background_color
  121. local font_size =data[p_graph].font_size or superproperties.font_size
  122. local font = data[p_graph].font or superproperties.font
  123. --Generate Background (background widget)
  124. if data[p_graph].background_color then
  125. helpers.draw_rounded_corners_rectangle( cr,
  126. 0,
  127. 0,
  128. data[p_graph].width,
  129. data[p_graph].height,
  130. background_color,
  131. rounded_size)
  132. end
  133. --draw a graph with graph_background_color
  134. if data[p_graph].horizontal == true then
  135. helpers.draw_rounded_corners_horizontal_graph( cr,
  136. h_margin,
  137. v_margin,
  138. data[p_graph].width - h_margin,
  139. data[p_graph].height - v_margin,
  140. graph_background_color,
  141. graph_color,
  142. rounded_size,
  143. value,
  144. graph_line_color)
  145. else
  146. helpers.draw_rounded_corners_vertical_graph( cr,
  147. h_margin,
  148. v_margin,
  149. data[p_graph].width - h_margin,
  150. data[p_graph].height - v_margin,
  151. graph_background_color,
  152. graph_color,
  153. rounded_size,
  154. value,
  155. graph_line_color)
  156. end
  157. if data[p_graph].show_text == true then
  158. cr:set_font_size(font_size)
  159. if type(font) == "string" then
  160. cr:select_font_face(font,nil,nil)
  161. elseif type(font) == "table" then
  162. cr:select_font_face(font.family or "Sans", font.slang or "normal", font.weight or "normal")
  163. end
  164. local value = data[p_graph].value * 100
  165. if data[p_graph].label then
  166. text=string.gsub(data[p_graph].label,"$percent", value)
  167. else
  168. text=value .. "%"
  169. end
  170. --if vertical graph, text is at the middle of the width, if vertical bar text is at the middle of the height
  171. if data[p_graph].horizontal == nil or data[p_graph].horizontal == false then
  172. helpers.draw_text_and_background(cr,
  173. text,
  174. data[p_graph].width/2,
  175. data[p_graph].height/2 ,
  176. text_background_color,
  177. text_color,
  178. true,
  179. true,
  180. false,
  181. false)
  182. else
  183. helpers.draw_text_and_background(cr,
  184. text,
  185. h_margin,
  186. data[p_graph].height/2 ,
  187. text_background_color,
  188. text_color,
  189. false,
  190. true,
  191. false,
  192. false)
  193. end
  194. end
  195. end
  196. function progressgraph.fit(p_graph, width, height)
  197. return data[p_graph].width, data[p_graph].height
  198. end
  199. --- Set the p_graph value.
  200. -- @param p_graph The progress bar.
  201. -- @param value The progress bar value between 0 and 1.
  202. function set_value(p_graph, value)
  203. if not p_graph then return end
  204. local value = value or 0
  205. local max_value = data[p_graph].max_value or 1
  206. data[p_graph].value = math.min(max_value, math.max(0, value))
  207. p_graph:emit_signal("widget::updated")
  208. return p_graph
  209. end
  210. --- Set the p_graph height.
  211. -- @param height The height to set.
  212. function progressgraph:set_height( height)
  213. data[self].height = height
  214. self:emit_signal("widget::updated")
  215. return self
  216. end
  217. --- Set the p_graph width.
  218. -- @param width The width to set.
  219. function progressgraph:set_width( width)
  220. data[self].width = width
  221. self:emit_signal("widget::updated")
  222. return self
  223. end
  224. -- Build properties function
  225. for _, prop in ipairs(properties) do
  226. if not progressgraph["set_" .. prop] then
  227. progressgraph["set_" .. prop] = function(p_graph, value)
  228. data[p_graph][prop] = value
  229. p_graph:emit_signal("widget::updated")
  230. return p_graph
  231. end
  232. end
  233. end
  234. --- Create a p_graph widget.
  235. -- @param args Standard widget() arguments. You should add width and height
  236. -- key to set p_graph geometry.
  237. -- @return A p_graph widget.
  238. function progressgraph.new(args)
  239. local args = args or {}
  240. args.width = args.width or 100
  241. args.height = args.height or 20
  242. if args.width < 5 or args.height < 5 then return end
  243. local p_graph = base.make_widget()
  244. data[p_graph] = {}
  245. for _, v in ipairs(properties) do
  246. data[p_graph][v] = args[v]
  247. end
  248. data[p_graph].value = 0
  249. data[p_graph].max_value = 1
  250. -- Set methods
  251. for _, prop in ipairs(properties) do
  252. p_graph["set_" .. prop] = progressgraph["set_" .. prop]
  253. end
  254. p_graph.set_value = set_value
  255. p_graph.add_value = set_value
  256. p_graph.draw = progressgraph.draw
  257. p_graph.fit = progressgraph.fit
  258. return p_graph
  259. end
  260. function progressgraph.mt:__call(...)
  261. return progressgraph.new(...)
  262. end
  263. return setmetatable(progressgraph, progressgraph.mt)
  264. -- vim: filetype=lua:expandtab:shiftwidth=2:tabstop=8:softtabstop=2:textwidth=80