aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/week.lua
blob: 262121f2637ca1661bc44e98b5e30c2a95dd4592 (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
-- Week: seven days of glyph and min-to-max range bar.
--
-- Adapted from the Conky-Mirage theme's week tile by alexsson-xexpanderx
-- (see lib/weather.lua). Each bar sits on the week's overall min..max scale,
-- so a warm day reads as a bar further right, not just a longer one.

local card = require 'lib.card'
local data = require 'lib.data'
local weather = require 'lib.weather'

local M = {}

local function draw_days(cr, x, y, w, h, colors, days, S)
  local n = #days
  if n == 0 then return end
  local step = h / n
  local size = math.min(S * 0.32, step * 0.55)
  if size < 8 then return end

  local lo, hi = math.huge, -math.huge
  for _, d in ipairs(days) do
    if d.min then lo = math.min(lo, d.min) end
    if d.max then hi = math.max(hi, d.max) end
  end
  local span = (hi > lo) and (hi - lo) or 1
  -- Columns as fractions of the width: day | glyph | min | bar | max.
  local gx, minx = x + w * 0.20, x + w * 0.42
  local bx0, bx1 = x + w * 0.46, x + w * 0.84
  local function bx(t) return bx0 + (bx1 - bx0) * (t - lo) / span end

  cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND)
  for i, d in ipairs(days) do
    local by = y + step * (i - 0.5) + size * 0.35   -- baseline, centred in the row
    card.font(cr, card.FONT_MONO, size, false)
    card.rgba(cr, colors.label)
    card.text(cr, x, by, i == 1 and 'TODAY'
      or (d.t and os.date('%a', d.t):upper() or '--'))
    card.rgba(cr, colors.highlight)
    card.text(cr, gx, by, weather.icon(d.code, true))
    card.rgba(cr, colors.value)
    card.text_right(cr, minx, by, weather.deg(d.min))
    card.text_right(cr, x + w, by, weather.deg(d.max))

    -- The track spans the week; the fill is this day.
    local my = by - size * 0.35
    cairo_set_line_width(cr, size * 0.35)
    card.rgba(cr, colors.rule, 0.35)
    cairo_move_to(cr, bx0, my)
    cairo_line_to(cr, bx1, my)
    cairo_stroke(cr)
    if d.min and d.max then
      card.rgba(cr, colors.highlight)
      cairo_move_to(cr, bx(d.min), my)
      cairo_line_to(cr, bx(d.max), my)
      cairo_stroke(cr)
    end
  end
  cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT)
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, 'WEEK', 'no weather data', 'bin/weather-fetch.sh')
    return
  end
  local y, S = card.standard(cr, inner, colors, {
    icon = card.ICON.week, title = 'WEEK', share = 0.25,
  })
  draw_days(cr, inner.x, y, inner.w, inner.y + inner.h - y, colors, w.days, S)
end

return M