progress_graph.lua 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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 displayed text value format string
  63. --@usage mygraph:set_value_format(string) --> "%2.f"
  64. --@name set_value_format
  65. --@class function
  66. --@param graph the graph
  67. --@param printf format string for display text
  68. ---Define the color of the text.
  69. --@usage mygraph:set_text_color(string) -->"#rrggbbaa"
  70. --@name set_text_color
  71. --@class function
  72. --@param graph the graph
  73. --@param color a string "#rrggbbaa" or "#rrggbb" defaul is white
  74. ---Define the background color of the text.
  75. --@usage mygraph:set_text_background_color(string) -->"#rrggbbaa"
  76. --@name set_text_background_color
  77. --@class function
  78. --@param graph the graph
  79. --@param color a string "#rrggbbaa" or "#rrggbb"
  80. ---Define the text font size.
  81. --@usage mygraph:set_font_size(integer)
  82. --@name set_font_size
  83. --@class function
  84. --@param graph the graph
  85. --@param size the font size
  86. ---Define the template of the text to display.
  87. --@usage mygraph:set_label(string)
  88. --By default the text is : (value_send_to_the_widget *100) .. "%"
  89. --static string: example set_label("CPU usage:") will display "CUP usage:" on the graph
  90. --dynamic string: use $percent in the string example set_label("Load $percent %") will display "Load 10%"
  91. --@name set_label
  92. --@class function
  93. --@param graph the graph
  94. --@param text the text to display
  95. ---Define if the graph should increase/decrease horizontaly.
  96. --@usage mygraph:set_horizontal(boolean) --> true or false
  97. --@name set_horizontal
  98. --@class function
  99. --@param graph the graph
  100. --@param boolean true or false (false by default)
  101. local data = setmetatable({}, { __mode = "k" })
  102. local properties = { "width", "height", "v_margin", "h_margin",
  103. "background_color",
  104. "graph_background_color","rounded_size",
  105. "graph_color", "graph_line_color","show_text", "text_color",
  106. "text_background_color" ,"label", "font_size","font","horizontal",
  107. "value_format"}
  108. function progressgraph.draw(p_graph, wibox, cr, width, height)
  109. -- We want one pixel wide lines
  110. cr:set_line_width(1)
  111. -- Set the values we need
  112. local value = data[p_graph].value
  113. local props = helpers.load_properties(properties, data, p_graph, superproperties)
  114. --Generate Background (background widget)
  115. if data[p_graph].background_color then
  116. helpers.draw_rounded_corners_rectangle( cr,
  117. 0,
  118. 0,
  119. width,
  120. height,
  121. props.background_color,
  122. props.rounded_size)
  123. end
  124. --draw a graph with graph_background_color
  125. if props.horizontal == true then
  126. helpers.draw_rounded_corners_horizontal_graph( cr,
  127. props.h_margin,
  128. props.v_margin,
  129. width - props.h_margin,
  130. height - props.v_margin,
  131. props.graph_background_color,
  132. props.graph_color,
  133. props.rounded_size,
  134. value,
  135. props.graph_line_color)
  136. else
  137. helpers.draw_rounded_corners_vertical_graph( cr,
  138. props.h_margin,
  139. props.v_margin,
  140. width - props.h_margin,
  141. height - props.v_margin,
  142. props.graph_background_color,
  143. props.graph_color,
  144. props.rounded_size,
  145. value,
  146. props.graph_line_color)
  147. end
  148. if props.show_text == true then
  149. local font
  150. if type(props.font) == "string" then
  151. font = props.font .. " " .. props.font_size
  152. elseif type(props.font) == "table" then
  153. font = (props.font.family or "Sans") .. " " .. (props.font.slang or "normal") .. " " .. (props.font.weight or "normal") .. " " .. props.font_size
  154. end
  155. value = string.format(props.value_format, data[p_graph].value * 100)
  156. if data[p_graph].label then
  157. text=string.gsub(data[p_graph].label,"$percent", value)
  158. else
  159. text=value .. "%"
  160. end
  161. --if vertical graph, text is at the middle of the width, if vertical bar text is at the middle of the height
  162. if props.horizontal == nil or props.horizontal == false then
  163. helpers.draw_layout_and_background(cr,
  164. text,
  165. width/2,
  166. height/2 ,
  167. font,
  168. props.text_background_color,
  169. props.text_color,
  170. "start",
  171. "middle")
  172. else
  173. helpers.draw_layout_and_background(cr,
  174. text,
  175. props.h_margin,
  176. height/2 ,
  177. font,
  178. props.text_background_color,
  179. props.text_color,
  180. "start",
  181. "middle")
  182. end
  183. end
  184. end
  185. function progressgraph.fit(p_graph, width, height)
  186. return data[p_graph].width, data[p_graph].height
  187. end
  188. --- Set the p_graph value.
  189. -- @param p_graph The progress bar.
  190. -- @param value The progress bar value between 0 and 1.
  191. function set_value(p_graph, value)
  192. if not p_graph then return end
  193. local value = value or 0
  194. local max_value = data[p_graph].max_value or 1
  195. data[p_graph].value = math.min(max_value, math.max(0, value))
  196. p_graph:emit_signal("widget::updated")
  197. return p_graph
  198. end
  199. --- Set the p_graph height.
  200. -- @param height The height to set.
  201. function progressgraph:set_height( height)
  202. data[self].height = height
  203. self:emit_signal("widget::updated")
  204. return self
  205. end
  206. --- Set the p_graph width.
  207. -- @param width The width to set.
  208. function progressgraph:set_width( width)
  209. data[self].width = width
  210. self:emit_signal("widget::updated")
  211. return self
  212. end
  213. -- Build properties function
  214. for _, prop in ipairs(properties) do
  215. if not progressgraph["set_" .. prop] then
  216. progressgraph["set_" .. prop] = function(p_graph, value)
  217. data[p_graph][prop] = value
  218. p_graph:emit_signal("widget::updated")
  219. return p_graph
  220. end
  221. end
  222. end
  223. --- Create a p_graph widget.
  224. -- @param args Standard widget() arguments. You should add width and height
  225. -- key to set p_graph geometry.
  226. -- @return A p_graph widget.
  227. function progressgraph.new(args)
  228. local args = args or {}
  229. args.width = args.width or 100
  230. args.height = args.height or 20
  231. if args.width < 5 or args.height < 5 then return end
  232. local p_graph = base.make_widget()
  233. data[p_graph] = {}
  234. for _, v in ipairs(properties) do
  235. data[p_graph][v] = args[v]
  236. end
  237. data[p_graph].value = 0
  238. data[p_graph].max_value = 1
  239. -- Set methods
  240. for _, prop in ipairs(properties) do
  241. p_graph["set_" .. prop] = progressgraph["set_" .. prop]
  242. end
  243. p_graph.set_value = set_value
  244. p_graph.add_value = set_value
  245. p_graph.draw = progressgraph.draw
  246. p_graph.fit = progressgraph.fit
  247. return p_graph
  248. end
  249. function progressgraph.mt:__call(...)
  250. return progressgraph.new(...)
  251. end
  252. return setmetatable(progressgraph, progressgraph.mt)