wlourf_circle_graph.lua 5.9 KB

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