aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 12:21:39 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 12:21:39 +0200
commita2a06d5d3e5b4b2352b0b327aa5d558b48174ab9 (patch)
tree7d8933f3a2c9bf950acfc5514dc5d799c09f5874
parent9a479e198142a486413270c0e5dec8ed4405e023 (diff)
downloadconky-theme-udt-a2a06d5d3e5b4b2352b0b327aa5d558b48174ab9.tar.gz
conky-theme-udt-a2a06d5d3e5b4b2352b0b327aa5d558b48174ab9.zip
feat: add bar, vbar, ring and threshold primitives
-rw-r--r--lib/card.lua91
1 files changed, 91 insertions, 0 deletions
diff --git a/lib/card.lua b/lib/card.lua
index 3352c4b..8e04e0b 100644
--- a/lib/card.lua
+++ b/lib/card.lua
@@ -123,4 +123,95 @@ function M.label(cr, x, y, s, colors)
M.text(cr, x, y, s:upper())
end
+-- Colour for a value against two thresholds.
+--
+-- One function so all four system cards agree on the rule instead of each
+-- re-deriving it, and so "what counts as busy" is stated in a single place.
+-- `v`, `warn` and `crit` share whatever unit the caller is using: percent for
+-- a filesystem, degrees for a sensor.
+function M.threshold(v, warn, crit, colors)
+ if type(v) ~= 'number' then return colors.label end
+ if v >= crit then return colors.critical end
+ if v >= warn then return colors.warning end
+ return colors.ok
+end
+
+-- A horizontal bar: a dim full-width track with a filled portion over it.
+--
+-- frac is clamped rather than trusted: a filesystem at 100% and a load that
+-- briefly computes above 1.0 must not draw past the track.
+function M.bar(cr, x, y, w, h, frac, colour, colors)
+ frac = tonumber(frac) or 0
+ if frac < 0 then frac = 0 elseif frac > 1 then frac = 1 end
+
+ M.rgba(cr, colors.rule, 0.5)
+ M.rounded_path(cr, x, y, w, h, h / 2)
+ cairo_fill(cr)
+
+ if frac > 0 then
+ M.rgba(cr, colour, 1)
+ M.rounded_path(cr, x, y, math.max(w * frac, h), h, h / 2)
+ cairo_fill(cr)
+ end
+end
+
+-- A vertical bar, rising from its baseline. The equaliser's element.
+function M.vbar(cr, x, base_y, w, max_h, frac, colour, colors)
+ frac = tonumber(frac) or 0
+ if frac < 0 then frac = 0 elseif frac > 1 then frac = 1 end
+
+ M.rgba(cr, colors.rule, 0.5)
+ cairo_rectangle(cr, x, base_y - max_h, w, max_h)
+ cairo_fill(cr)
+
+ local h = max_h * frac
+ if h > 0 then
+ M.rgba(cr, colour, 1)
+ cairo_rectangle(cr, x, base_y - h, w, h)
+ cairo_fill(cr)
+ end
+end
+
+-- A ring gauge, after idea2.png: a dim full circle with an arc over it
+-- covering `frac`, leaving the centre free for a glyph.
+--
+-- The arc starts at twelve o'clock and sweeps clockwise, which is what reads
+-- as a gauge. Cairo's zero angle is at three o'clock and it sweeps clockwise
+-- already, so the start is offset by -pi/2 rather than the direction being
+-- reversed.
+function M.ring(cr, cx, cy, r, frac, colour, colors, width)
+ frac = tonumber(frac) or 0
+ if frac < 0 then frac = 0 elseif frac > 1 then frac = 1 end
+ width = width or math.max(3, r * 0.18)
+
+ cairo_set_line_width(cr, width)
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND)
+
+ M.rgba(cr, colors.rule, 0.5)
+ cairo_arc(cr, cx, cy, r, 0, math.pi * 2)
+ cairo_stroke(cr)
+
+ if frac > 0 then
+ M.rgba(cr, colour, 1)
+ cairo_arc(cr, cx, cy, r, -math.pi / 2, -math.pi / 2 + math.pi * 2 * frac)
+ cairo_stroke(cr)
+ end
+ -- Leave the cap as it was found: a later stroke inheriting ROUND would get
+ -- visibly rounded ends on the card's hairlines.
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT)
+end
+
+-- Bytes to a short human string: 1181116006 -> '1.1G'.
+-- The card formats its own numbers because the samplers pass raw bytes.
+function M.human(bytes)
+ local n = tonumber(bytes)
+ if not n then return '--' end
+ local units = { 'B', 'K', 'M', 'G', 'T', 'P' }
+ local i = 1
+ while n >= 1024 and i < #units do n = n / 1024; i = i + 1 end
+ if i == 1 then return string.format('%d%s', n, units[i]) end
+ if n >= 100 then return string.format('%.0f%s', n, units[i]) end
+ return string.format('%.1f%s', n, units[i])
+end
+
return M