aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/details.lua
blob: 36ce0166776810ed6b11662745b56d6f999c8f23 (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
-- Details: wind, humidity, UV and air quality, with a wind compass as the
-- big value.
--
-- Adapted from the Conky-Mirage theme's details tiles by alexsson-xexpanderx
-- (see lib/weather.lua). UV and AQI are the measured quantities here, so they
-- carry the ok / warning / critical roles.

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

local M = {}

-- The compass fills the big value's slot: `size` square, its right edge at
-- `right`, its top at `top`.
local function draw_compass(cr, right, top, size, colors, deg)
  local r = size / 2
  local cx, cy = right - r, top + r
  card.rgba(cr, colors.rule, 0.8)
  cairo_set_line_width(cr, 1)
  cairo_new_path(cr)
  cairo_arc(cr, cx, cy, r, 0, math.pi * 2)
  cairo_stroke(cr)

  local size = r * 0.28
  card.font(cr, card.FONT_MONO, size, false)
  card.rgba(cr, colors.label)
  for i, p in ipairs({ 'N', 'E', 'S', 'W' }) do
    local a = (i - 1) * math.pi / 2
    card.text_centre(cr, cx + (r - size) * math.sin(a),
      cy - (r - size) * math.cos(a) + size * 0.35, p)
  end

  if type(deg) ~= 'number' then return end
  -- Open-Meteo gives where the wind comes FROM; the needle points where it goes.
  local a = math.rad(deg + 180)
  local tip = r - size * 1.6
  local sa, ca = math.sin(a), math.cos(a)
  -- A filled arrowhead at the tip, so the needle reads one way only. The shaft
  -- stops at the head's base: a stroke run to the apex would blunt it.
  local head, half = r * 0.22, r * 0.11
  local bx, by = cx + (tip - head) * sa, cy - (tip - head) * ca
  card.rgba(cr, colors.highlight)
  cairo_set_line_width(cr, math.max(2, r * 0.04))
  cairo_move_to(cr, cx - tip * 0.6 * sa, cy + tip * 0.6 * ca)
  cairo_line_to(cr, bx, by)
  cairo_stroke(cr)
  cairo_move_to(cr, cx + tip * sa, cy - tip * ca)
  cairo_line_to(cr, bx + half * ca, by + half * sa)
  cairo_line_to(cr, bx - half * ca, by - half * sa)
  cairo_close_path(cr)
  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, 'DETAILS', 'no weather data', 'bin/weather-fetch.sh')
    return
  end

  local c = w.current
  -- UV is the forecast for the current hour; Open-Meteo's current block has none.
  local uv = (w.hours[1] or {}).uv
  local aqi = w.air and w.air.aqi
  local wind = '--'
  if type(c.wind) == 'number' then
    wind = weather.num(c.wind) .. ' ' .. weather.wind_unit(w.units)
      .. ' ' .. (weather.compass(c.wind_deg) or '')
  end
  local rows = {
    { 'WIND', wind },
    { 'HUMIDITY', weather.num(c.humidity, '%') },
    { 'UV', type(uv) == 'number' and string.format('%.1f', uv) or '--',
      colors[weather.uv_role(uv)] },
    { 'AIR (EAQI)', weather.num(aqi), colors[weather.aqi_role(aqi)] },
  }
  card.standard(cr, inner, colors, {
    icon = card.ICON.details, title = 'DETAILS', rows = rows,
    big = function(cr, right, top, size)
      -- 1.2x the slot: the first row starts lower than the big text ends.
      draw_compass(cr, right, top, size * 1.2, colors, c.wind_deg)
    end,
  })
end

return M