Lots of random documentation fixes
[awesome.git] / lib / awful / widget / graph.lua.in
blob4c14e1ed9ebe40df01e648451c3f62ab3cc7a2b8
1 ---------------------------------------------------------------------------
2 -- @author Julien Danjou <julien@danjou.info>
3 -- @copyright 2009 Julien Danjou
4 -- @release @AWESOME_VERSION@
5 ---------------------------------------------------------------------------
7 local setmetatable = setmetatable
8 local ipairs = ipairs
9 local math = math
10 local table = table
11 local type = type
12 local color = require("gears.color")
13 local base = require("wibox.widget.base")
15 --- A graph widget.
16 -- awful.widget.graph
17 local graph = { mt = {} }
19 local data = setmetatable({}, { __mode = "k" })
21 --- Set the graph border color.
22 -- If the value is nil, no border will be drawn.
23 -- @name set_border_color
24 -- @class function
25 -- @param graph The graph.
26 -- @param color The border color to set.
28 --- Set the graph foreground color.
29 -- @name set_color
30 -- @class function
31 -- @param graph The graph.
32 -- @param color The graph color.
34 --- Set the graph background color.
35 -- @name set_background_color
36 -- @class function
37 -- @param graph The graph.
38 -- @param color The graph background color.
40 --- Set the maximum value the graph should handle.
41 -- If "scale" is also set, the graph never scales up below this value, but it
42 -- automatically scales down to make all data fit.
43 -- @name set_max_value
44 -- @class function
45 -- @param graph The graph.
46 -- @param value The value.
48 --- Set the graph to automatically scale its values. Default is false.
49 -- @name set_scale
50 -- @class function
51 -- @param graph The graph.
52 -- @param scale A boolean value
54 --- Set the graph to draw stacks. Default is false.
55 -- @name set_stack
56 -- @class function
57 -- @param graph The graph.
58 -- @param stack A boolean value.
60 --- Set the graph stacking colors. Order matters.
61 -- @name set_stack_colors
62 -- @class function
63 -- @param graph The graph.
64 -- @param stack_colors A table with stacking colors.
66 local properties = { "width", "height", "border_color", "stack",
67 "stack_colors", "color", "background_color",
68 "max_value", "scale" }
70 function graph.draw(_graph, wibox, cr, width, height)
71 local max_value = data[_graph].max_value
72 local values = data[_graph].values
74 cr:set_line_width(1)
76 -- Draw the background first
77 cr:set_source(color(data[_graph].background_color or "#000000aa"))
78 cr:paint()
80 -- Account for the border width
81 cr:save()
82 if data[_graph].border_color then
83 cr:translate(1, 1)
84 width, height = width - 2, height - 2
85 end
87 -- Draw a stacked graph
88 if data[_graph].stack then
90 if data[_graph].scale then
91 for _, v in ipairs(values) do
92 for __, sv in ipairs(v) do
93 if sv > max_value then
94 max_value = sv
95 end
96 end
97 end
98 end
100 for i = 0, width do
101 local rel_i = 0
102 local rel_x = i + 0.5
104 if data[_graph].stack_colors then
105 for idx, col in ipairs(data[_graph].stack_colors) do
106 local stack_values = values[idx]
107 if stack_values and i < #stack_values then
108 local value = stack_values[#stack_values - i] + rel_i
109 cr:move_to(rel_x, height * (1 - (rel_i / max_value)))
110 cr:line_to(rel_x, height * (1 - (value / max_value)))
111 cr:set_source(color(col or "#ff0000"))
112 cr:stroke()
113 rel_i = value
118 else
119 if data[_graph].scale then
120 for _, v in ipairs(values) do
121 if v > max_value then
122 max_value = v
127 -- Draw the background on no value
128 if #values ~= 0 then
129 -- Draw reverse
130 for i = 0, #values - 1 do
131 local value = values[#values - i]
132 if value >= 0 then
133 value = value / max_value
134 cr:move_to(i + 0.5, height * (1 - value))
135 cr:line_to(i + 0.5, height)
138 cr:set_source(color(data[_graph].color or "#ff0000"))
139 cr:stroke()
144 -- Undo the cr:translate() for the border
145 cr:restore()
147 -- Draw the border last so that it overlaps already drawn values
148 if data[_graph].border_color then
149 -- We decremented these by two above
150 width, height = width + 2, height + 2
152 -- Draw the border
153 cr:rectangle(0.5, 0.5, width - 1, height - 1)
154 cr:set_source(color(data[_graph].border_color or "#ffffff"))
155 cr:stroke()
159 function graph.fit(_graph, width, height)
160 return data[_graph].width, data[_graph].height
163 --- Add a value to the graph
164 -- @param _graph The graph.
165 -- @param value The value between 0 and 1.
166 -- @param group The stack color group index.
167 local function add_value(_graph, value, group)
168 if not _graph then return end
170 local value = value or 0
171 local values = data[_graph].values
172 local max_value = data[_graph].max_value
173 value = math.max(0, value)
174 if not data[_graph].scale then
175 value = math.min(max_value, value)
178 if data[_graph].stack and group then
179 if not data[_graph].values[group]
180 or type(data[_graph].values[group]) ~= "table"
181 then
182 data[_graph].values[group] = {}
184 values = data[_graph].values[group]
186 table.insert(values, value)
188 local border_width = 0
189 if data[_graph].border_color then border_width = 2 end
191 -- Ensure we never have more data than we can draw
192 while #values > data[_graph].width - border_width do
193 table.remove(values, 1)
196 _graph:emit_signal("widget::updated")
197 return _graph
201 --- Set the graph height.
202 -- @param height The height to set.
203 function graph:set_height(height)
204 if height >= 5 then
205 data[self].height = height
206 self:emit_signal("widget::updated")
208 return self
211 --- Set the graph width.
212 -- @param graph The graph.
213 -- @param width The width to set.
214 function graph:set_width(width)
215 if width >= 5 then
216 data[self].width = width
217 self:emit_signal("widget::updated")
219 return self
222 -- Build properties function
223 for _, prop in ipairs(properties) do
224 if not graph["set_" .. prop] then
225 graph["set_" .. prop] = function(_graph, value)
226 data[_graph][prop] = value
227 _graph:emit_signal("widget::updated")
228 return _graph
233 --- Create a graph widget.
234 -- @param args Standard widget() arguments. You should add width and height
235 -- key to set graph geometry.
236 -- @return A graph widget.
237 function graph.new(args)
238 local args = args or {}
240 local width = args.width or 100
241 local height = args.height or 20
243 if width < 5 or height < 5 then return end
245 local _graph = base.make_widget()
247 data[_graph] = { width = width, height = height, values = {}, max_value = 1 }
249 -- Set methods
250 _graph.add_value = add_value
251 _graph.draw = graph.draw
252 _graph.fit = graph.fit
254 for _, prop in ipairs(properties) do
255 _graph["set_" .. prop] = graph["set_" .. prop]
258 return _graph
261 function graph.mt:__call(...)
262 return graph.new(...)
265 return setmetatable(graph, graph.mt)
267 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80