wlourf_circle_graph.lua 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. -- @author cedlemo
  2. local setmetatable = setmetatable
  3. local ipairs = ipairs
  4. local math = math
  5. local table = table
  6. local type = type
  7. local string = string
  8. local color = require("gears.color")
  9. local base = require("wibox.widget.base")
  10. local helpers = require("blingbling.helpers")
  11. local superproperties = require('blingbling.superproperties')
  12. local circle_graph = { mt = {} }
  13. ---Circle graph from wlourf.
  14. --@module blingbling.wlourf_circle_graph
  15. ---Define the top and bottom margin for the graph area.
  16. --@usage circle:set_v_margin(integer)
  17. --@name set_v_margin
  18. --@class function
  19. --@param margin an integer for top and bottom margin
  20. ---Define the left and right margin for the graph area.
  21. --@usage circle:set_h_margin()
  22. --@name set_h_margin
  23. --@class function
  24. --@param margin an integer for left and right margin
  25. ---Set the radius of the circle.
  26. --@usage circle:set_radius(integer)
  27. --@name set_radius
  28. --@class function
  29. --@param radius an integer value for the radius of the circle
  30. ---Set the default color for the graph.
  31. --@usage circle:set_graph_color(string) -->"#rrggbbaa"
  32. --@name set_graph_color
  33. --@class function
  34. --@param color a string "#rrggbbaa" or "#rrggbb"
  35. ---Set the colors and theirs ranges for the graph.
  36. --@usage circle:set_graph_colors({{"#88aa00ff",0}, --all value > 0 will be displayed using this color
  37. --{"#d4aa00ff", 0.5},
  38. --{"#d45500ff",0.77}})
  39. --@name set_graph_colors
  40. --@class function
  41. --@param colors a table of tables {color , float } with color a string "#rrggbbaa" or "#rrggbb" and float which is 0<=float<=1
  42. ---Display text on the graph or not.
  43. --@usage circle:set_show_text(boolean) --> true or false
  44. --@name set_show_text
  45. --@class function
  46. --@param boolean true or false (default is false)
  47. ---Define the text's font .
  48. --@usage circle:set_font(string)
  49. --@name set_font
  50. --@class function
  51. --@param font a string that contains the font name family and weight
  52. ---Define the text font size.
  53. --@usage circle:set_font_size(integer)
  54. --@name set_font_size
  55. --@class function
  56. --@param size the font size
  57. ---Define the text to display.
  58. --@usage circle:set_label(string)
  59. --@name set_label
  60. --@class function
  61. --@param text the text to display
  62. local data = setmetatable({}, { __mode = "k" })
  63. local properties = {"width", "height", "h_margin", "v_margin", "radius", "graph_colors", "graph_color", "show_text", "font_size", "font", "label"}
  64. function circle_graph.draw(c_graph, wibox, cr, width, height)
  65. local v_margin = superproperties.v_margin
  66. if data[c_graph].v_margin and data[c_graph].v_margin <= data[c_graph].height/4 then
  67. v_margin = data[c_graph].v_margin
  68. end
  69. local h_margin = superproperties.h_margin
  70. if data[c_graph].h_margin and data[c_graph].h_margin <= data[c_graph].width / 3 then
  71. h_margin = data[c_graph].h_margin
  72. end
  73. local graph_color = data[c_graph].graph_color or superproperties.graph_color
  74. local font_size =data[c_graph].font_size or superproperties.font_size
  75. local font = data[c_graph].font or superproperties.font
  76. local value = data[c_graph].value * 100
  77. local line_width = 1
  78. local radius = data[c_graph].radius or height/2-line_width
  79. local yy = ( height - (v_margin*2))/2
  80. local xx = radius+line_width
  81. local w=height*2
  82. if data[c_graph].graph_colors and type(data[c_graph].graph_colors) == "table" then
  83. for i,table in ipairs(data[c_graph].graph_colors) do
  84. if i == 1 then
  85. if value/100 >= table[2] then
  86. graph_color = table[1]
  87. end
  88. elseif i ~= 1 then
  89. if value/100 >= table[2] then
  90. graph_color = table[1]
  91. end
  92. end
  93. end
  94. end
  95. r,g,b,a=helpers.hexadecimal_to_rgba_percent(graph_color)
  96. cr:set_source_rgba(r,g,b,a)
  97. if data[c_graph].show_text == true and data[c_graph].label ~= nil then
  98. cr:set_font_size(font_size)
  99. if type(font) == "string" then
  100. cr:select_font_face(font,nil,nil)
  101. elseif type(font) == "table" then
  102. cr:select_font_face(font.family or "Sans", font.slang or "normal", font.weight or "normal")
  103. end
  104. te=cr:text_extents(data[c_graph].label)
  105. cr:save()
  106. cr:translate(-te["y_bearing"]+h_margin,(height+te["x_advance"]+te["x_bearing"])/2)
  107. cr:rotate(-math.pi/2)
  108. cr:show_text(data[c_graph].label)
  109. cr:stroke()
  110. cr:restore()
  111. xx= te["height"]-te["y_bearing"]+radius +h_margin
  112. end
  113. data[c_graph].width = te["height"]-te["y_bearing"]+radius*2 + h_margin*2
  114. cr:set_line_cap("butt")
  115. cr:set_line_width(line_width)
  116. cr:arc(xx,yy,radius,0,2*math.pi)
  117. cr:stroke()
  118. cr:move_to(xx,yy)
  119. cr:arc_negative(xx,yy,radius,0,-2*math.pi*value/100)
  120. cr:fill()
  121. end
  122. function circle_graph.fit(c_graph, width, height)
  123. return data[c_graph].width, data[c_graph].height
  124. end
  125. --- Set the c_graph value.
  126. -- @param c_graph The progress bar.
  127. -- @param value The progress bar value between 0 and 1.
  128. local function set_value(c_graph, value)
  129. local value = value or 0
  130. local max_value = data[c_graph].max_value
  131. data[c_graph].value = math.min(max_value, math.max(0, value))
  132. c_graph:emit_signal("widget::updated")
  133. return c_graph
  134. end
  135. --- Set the c_graph height.
  136. -- @param height The height to set.
  137. function circle_graph:set_height( height)
  138. if height >= 5 then
  139. data[self].height = height
  140. self:emit_signal("widget::updated")
  141. end
  142. return self
  143. end
  144. --- Set the graph width.
  145. -- @param width The width to set.
  146. function circle_graph:set_width( width)
  147. if width >= 5 then
  148. data[self].width = width
  149. self:emit_signal("widget::updated")
  150. end
  151. return self
  152. end
  153. -- Build properties function
  154. for _, prop in ipairs(properties) do
  155. if not circle_graph["set_" .. prop] then
  156. circle_graph["set_" .. prop] = function(c_graph, value)
  157. data[c_graph][prop] = value
  158. c_graph:emit_signal("widget::updated")
  159. return c_graph
  160. end
  161. end
  162. end
  163. --- Create a c_graph widget.
  164. -- @param args Standard widget() arguments. You should add width and height
  165. -- key to set graph geometry.
  166. -- @return A graph widget.
  167. function circle_graph.new(args)
  168. local args = args or {}
  169. args.width = args.width or 100
  170. args.height = args.height or 20
  171. if args.width < 5 or args.height < 5 then return end
  172. local c_graph = base.make_widget()
  173. data[c_graph] = {}
  174. for _, v in ipairs(properties) do
  175. data[c_graph][v] = args[v]
  176. end
  177. data[c_graph].value = 0
  178. data[c_graph].max_value = 1
  179. -- Set methods
  180. c_graph.set_value = set_value
  181. c_graph.add_value = set_value
  182. c_graph.draw = circle_graph.draw
  183. c_graph.fit = circle_graph.fit
  184. for _, prop in ipairs(properties) do
  185. c_graph["set_" .. prop] = circle_graph["set_" .. prop]
  186. end
  187. return c_graph
  188. end
  189. function circle_graph.mt:__call(...)
  190. return circle_graph.new(...)
  191. end
  192. return setmetatable(circle_graph, circle_graph.mt)