aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/breaktimer.lua
blob: 6fed30e79f0450e2e8aa7518c98d6fac522e5d2d (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
-- Breaktimer: the phase of breaktimer.sh and the time left in it.
--
-- Everything comes from a cache file written by bin/breaktimer-sample.sh:
-- conky's Lua cannot run a process, so it can neither call `kill -0` to learn
-- whether the daemon is alive nor ask breaktimer.sh itself. The sampler owns
-- that; this card owns only how the state looks.
--
-- The countdown is the big value, coloured by phase: green for a work block,
-- blue during a micro-pause, purple during a long one, yellow when paused, and
-- the dim label colour when the clock is frozen. That is the same phase-to-
-- colour language the old Waybar module used, mapped onto the palette roles.

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

local CACHE = (os.getenv('XDG_CACHE_HOME') or (os.getenv('HOME') .. '/.cache'))
  .. '/udt/breaktimer.txt'

local M = {}

function M.draw(cr, rect, colors)
  local inner = card.card(cr, rect, colors)
  local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end
  local LABEL_F, BIG_F, ROW_F = 0.30, 1.0, 0.32

  local bt = data.breaktimer_parse(data.slurp(CACHE) or '')

  -- No cache at all: the sampler has not run. Name it, as the slackware card
  -- does, rather than leaving a blank cell that is indistinguishable from a
  -- crash. A stopped daemon is NOT this case: the sampler still writes a cache,
  -- with running no, which the card draws as 'fermo'.
  if not bt then
    card.notice(cr, inner, colors, 'BREAKTIMER', 'no breaktimer data',
      'bin/breaktimer-sample.sh')
    return
  end

  local rows = {
    { 'PHASE', bt.phase_label },
    { 'NEXT',  bt.next },
  }

  -- Fluid type: the height budget grows the content to fill the cell, the
  -- measured width fit pulls it back where the phase label would overrun.
  local groups = {
    { { card.title_str(card.ICON.breaktimer, 'BREAKTIMER'), card.FONT_MONO, LABEL_F },
      { bt.countdown, card.FONT_HEAVY, BIG_F } },
  }
  for _, r in ipairs(rows) do
    groups[#groups + 1] = { { r[1], card.FONT_MONO, ROW_F },
                            { tostring(r[2]), card.FONT_MONO, ROW_F } }
  end
  local S = clamp(math.min(inner.h * 0.94 / (1.5 + #rows * 0.66),
    card.fit_unit(cr, inner.w * 0.96, groups, 100)), 10, 72)
  local label_size = S * LABEL_F
  local row_size   = S * ROW_F

  card.font(cr, card.FONT_HEAVY, S * BIG_F, false)
  card.rgba(cr, colors[bt.role] or colors.value)
  card.text_right(cr, inner.x + inner.w, inner.y + S * BIG_F, bt.countdown)

  card.font(cr, card.FONT_MONO, label_size, false)
  card.title(cr, inner.x, inner.y + label_size, card.ICON.breaktimer,
    'BREAKTIMER', colors)

  local ey = inner.y + S * BIG_F + row_size * 1.6
  local step = row_size * 2.0
  card.font(cr, card.FONT_MONO, row_size, false)
  for _, r in ipairs(rows) do
    if ey + step > inner.y + inner.h then break end
    card.rgba(cr, colors.label)
    card.text(cr, inner.x, ey, r[1])
    card.rgba(cr, colors.value)
    card.text_right(cr, inner.x + inner.w, ey, tostring(r[2]))
    ey = ey + step
  end
end

return M