diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-18 14:36:07 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-18 14:36:07 +0200 |
| commit | b492fbb4011cc7890b6b218553809e247f506b71 (patch) | |
| tree | 056bd7b01b2a09368f15d028c1e1c41d67a33171 | |
| parent | c72ee8bce374294eca0c14c3f0db142fad40c360 (diff) | |
| download | conky-theme-udt-b492fbb4011cc7890b6b218553809e247f506b71.tar.gz conky-theme-udt-b492fbb4011cc7890b6b218553809e247f506b71.zip | |
feat(sky): sun, moon and daylight-arc card adapted from Conky-Mirage
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
| -rw-r--r-- | widgets/sky.lua | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/widgets/sky.lua b/widgets/sky.lua new file mode 100644 index 0000000..aa0ad43 --- /dev/null +++ b/widgets/sky.lua @@ -0,0 +1,85 @@ +-- Sky: sunrise, sunset, day length and the moon, over the daylight arc. +-- +-- Adapted from the Conky-Mirage theme's sky tile by alexsson-xexpanderx +-- (see lib/weather.lua). The arc is the one the old weather card drew, minus +-- its time labels: the rows carry the times now. + +local card = require 'lib.card' +local data = require 'lib.data' +local weather = require 'lib.weather' + +local M = {} + +-- The dot is placed by evaluating the curve at t rather than by computing a +-- point on a circle: the curve IS the path, so evaluating it keeps the dot on +-- the arc if the control points are ever adjusted. +local function draw_arc(cr, x, y, w, h, colors, rise, set, now) + local pad = math.max(4, w * 0.012) + local x0, x1 = x + pad, x + w - pad + local base = y + h - pad + local top = y + h * 0.08 + + -- Cubic Bezier control points, chosen so the curve peaks near the middle. + local p0 = { x0, base } + local c1 = { x0 + (x1 - x0) * 0.22, top - h * 0.14 } + local c2 = { x1 - (x1 - x0) * 0.22, top - h * 0.14 } + local p3 = { x1, base } + + -- The horizon the sun rises from and sets into. + card.rgba(cr, colors.rule, 0.6) + cairo_set_line_width(cr, 1) + cairo_move_to(cr, x0, base) + cairo_line_to(cr, x1, base) + cairo_stroke(cr) + + card.rgba(cr, colors.rule, 0.9) + cairo_set_line_width(cr, 1.5) + cairo_move_to(cr, p0[1], p0[2]) + cairo_curve_to(cr, c1[1], c1[2], c2[1], c2[2], p3[1], p3[2]) + cairo_stroke(cr) + + local t = weather.sun_t(now, rise, set) or 0 + local function bez(a, b, c, d) + local u = 1 - t + return u * u * u * a + 3 * u * u * t * b + 3 * u * t * t * c + t * t * t * d + end + -- At night the dot is parked at an end, so it takes the dim colour: a bright + -- dot on the horizon would read as a sun that is still up. + card.rgba(cr, weather.is_day(now, rise, set) and colors.body or colors.label) + cairo_new_path(cr) + cairo_arc(cr, bez(p0[1], c1[1], c2[1], p3[1]), bez(p0[2], c1[2], c2[2], p3[2]), + math.max(3, math.min(9, h * 0.045)), 0, math.pi * 2) + cairo_fill(cr) +end + +function M.draw(cr, rect, colors) + local inner = card.card(cr, rect, colors) + local w = weather.parse(data.slurp(weather.CACHE)) + if not w then + card.notice(cr, inner, colors, 'SKY', 'no weather data', 'bin/weather-fetch.sh') + return + end + + local now = os.time() + local rise, set = w.sun.rise, w.sun.set + local phase, lit = weather.moon(now) + local rows = { + { 'SUNRISE', os.date('%H:%M', rise) }, + { 'SUNSET', os.date('%H:%M', set) }, + { 'DAYLIGHT', weather.duration(set - rise) }, + { 'MOON', weather.num(lit * 100, '%') }, + } + local y = card.standard(cr, inner, colors, { + icon = card.ICON.sky, title = 'SKY', + big = weather.moon_icon(phase), big_font = card.FONT_MONO, + big_color = colors.heading, rows = rows, share = 0.65, + }) + + -- An arch taller than about 0.6 of its width reads as a door, not a day. + local arc_h = math.min(inner.y + inner.h - y, inner.w * 0.6) + if arc_h >= 50 then + draw_arc(cr, inner.x, inner.y + inner.h - arc_h, inner.w, arc_h, colors, rise, set, now) + end +end + +return M |
