aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/ui/statusbar/panel/widgets/linegraph.lua
blob: 9a42632978f691b3d083db59fcf57f335584a63d (plain)
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)