1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
local gcolor = require "gears.color"
local gtable = require "gears.table"
local wibox = require "wibox"
local linegraph = { mt = {} }
function linegraph:fit(_, width, height)
if #self._private.values < 2 then
return 0, 0
end
return width, height
end
function linegraph:draw(_, cr, width, height)
if #self._private.values < 2 then
return
end
local line_width = self._private.line_width
local values = self._private.values
local max, min = self._private.max or 0, self._private.min or 0
if not (self._private.max and self._private.min) then
for _, value in ipairs(values) do
if not self._private.max then
max = max < value and value or max
end
if not self._private.min then
min = min > value and value or min
end
end
end
local usable_height = height - line_width
local min_abs = math.abs(min)
local h_factor = usable_height / (min_abs + max)
local function transform(value)
return usable_height - math.floor((value + min_abs) * h_factor) + line_width / 2
end
local graph_values = {}
for i = 1, #values, math.ceil(#values / width) do
table.insert(graph_values, transform(values[i]))
end
if self._private.draw_bg then
cr:save()
self._private.draw_bg(cr, width, height, min, max, transform)
cr:restore()
end
cr:set_line_width(line_width)
cr:set_source(gcolor(self.color))
cr:move_to(line_width / 2, graph_values[1])
for i = 2, #graph_values do
cr:line_to((width - line_width / 2) / (#graph_values - 1) * (i - 1), graph_values[i])
end
if self._private.fill then
cr:line_to(width - line_width / 2, transform(min))
cr:line_to(line_width / 2, transform(min))
cr:line_to(line_width / 2, graph_values[1])
cr:stroke_preserve()
cr:set_source(gcolor(self.fill_color))
cr:fill()
else
cr:stroke()
end
end
function linegraph:set_values(values)
self._private.values = values
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_values()
return self._private.values
end
function linegraph:set_draw_bg(draw_bg)
self._private.draw_bg = draw_bg
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_draw_bg()
return self._private.draw_bg
end
function linegraph:set_max(max)
self._private.max = max
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_max()
return self._private.max
end
function linegraph:set_min(min)
self._private.max = min
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_min()
return self._private.min
end
function linegraph:set_line_width(line_width)
self._private.line_width = line_width
self:emit_signal "widget::redraw_needed"
end
function linegraph:set_color(color)
self._private.color = color
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_color()
return self._private.color
end
function linegraph:set_fill_color(fill_color)
self._private.fill_color = fill_color
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_fill_color()
return self._private.fill_color
end
function linegraph:set_fill(fill)
self._private.fill = fill
self:emit_signal "widget::redraw_needed"
end
function linegraph:get_fill()
return self._private.fill
end
local function new()
local ret = wibox.widget.base.make_widget(nil, nil, { enable_properties = true })
gtable.crush(ret, linegraph, true)
ret.line_width = 1
ret.color = "#ffffff"
ret.fill_color = "#000000"
return ret
end
function linegraph.mt:__call()
return new()
end
return setmetatable(linegraph, linegraph.mt)
|