local phosphor = require "assets.phosphor" local qcolor = require "quarrel.color" local qui = require "quarrel.ui" local wibox = require "wibox" local WEEKDAY_MAP = { 7, 1, 2, 3, 4, 5, 6 } local M = {} local l_grid = wibox.widget { layout = wibox.layout.grid, forced_num_rows = 7, forced_num_cols = 7, border_width = { inner = qui.BORDER_WIDTH, outer = 0, }, border_color = qcolor.palette.border.variant, } local w_month = wibox.widget { widget = wibox.widget.textbox, text = "-", } local w_year = wibox.widget { widget = wibox.widget.textbox, text = "-", } local offset = 0 M.widget = wibox.widget(qui.styled { widget = wibox.container.background, bg = qcolor.palette.bg.high, { widget = wibox.container.margin, margins = qui.BORDER_WIDTH, { { l_grid, { widget = wibox.container.background, bg = qcolor.palette.border(), forced_width = qui.BORDER_WIDTH, }, layout = wibox.layout.fixed.horizontal, }, { widget = wibox.container.margin, margins = qui.BIG_PADDING, { { widget = wibox.container.place, fill_horizontal = true, { { widget = wibox.container.place, w_month, }, qui.separator { size = qui.BORDER_WIDTH }, w_year, layout = wibox.layout.fixed.vertical, spacing = qui.PADDING } }, nil, qui.styled { widget = wibox.container.background, bg = qcolor.palette.bg.highest, { { widget = wibox.container.margin, margins = qui.PADDING, { widget = wibox.container.place, qui.icon { icon = phosphor.caret_up_bold, widget = { forced_height = qui.CHAR_HEIGHT / 2, forced_width = qui.CHAR_HEIGHT / 2, }, }, }, }, { widget = wibox.container.background, bg = qcolor.palette.border.variant, forced_height = qui.BORDER_WIDTH, }, { widget = wibox.container.margin, margins = qui.PADDING, { widget = wibox.container.place, qui.icon { icon = phosphor.caret_down_bold, widget = { forced_height = qui.CHAR_HEIGHT / 2, forced_width = qui.CHAR_HEIGHT / 2, }, }, }, }, layout = wibox.layout.fixed.vertical, }, }, layout = wibox.layout.align.vertical, }, }, layout = wibox.layout.fixed.horizontal, }, }, }) function M:render(grid) for i, row in ipairs(grid) do for j, col in ipairs(row) do local widget = l_grid:get_widgets_at(i, j)[1] widget.widget.widget.widget.text = col[1] if col[2] then widget.bg = qcolor.palette.yellow() widget.fg = qcolor.palette.bg() elseif j % 6 == 0 or j % 7 == 0 then widget.bg = col[3] and qcolor.palette.bg.highest or qcolor.palette.bg.high else widget.bg = col[3] and qcolor.palette.bg.high or qcolor.palette.bg() end if i == 1 then widget.fg = qcolor.palette.fg() elseif not col[2] then widget.fg = qcolor.palette.fg.low end end end end -- Logic heavily inspired by https://github.com/Sinomor/dotfiles/blob/e409f9a84bf40daf1e39c0179ec749232ed827c9/home/.config/awesome/ui/control/moment/calendar.lua#L134-L173 function M:compute(year, month) local grid = { { { "Mo", false, true }, { "Tu", false, true }, { "We", false, true }, { "Th", false, true }, { "Fr", false, true }, { "Sa", false, true }, { "Su", false, true }, }, {}, {}, {}, {}, {}, {}, } local current = os.date("*t", os.time()) local first_day = os.date("*t", os.time { year = year, month = month, day = 1 }) local last_day = os.date("*t", os.time { year = year, month = month + 1, day = 0 }) local days = last_day.day local prev_days = os.date("*t", os.time { year = year, month = month, day = 0 }) local prev_offset = WEEKDAY_MAP[first_day.wday] - 1 local prev_month = month - 1 == -1 and 12 or month - 1 local prev_year = prev_month == 12 and year - 1 or year if prev_offset ~= -1 then for offset = prev_offset, 1, -1 do local day = prev_days.day - offset + 1 table.insert( grid[2], { day, day == current.day and prev_month == current.month and prev_year == current.year, false } ) end end do local row = 2 local weekday = WEEKDAY_MAP[first_day.wday] for day = 1, days do table.insert( grid[row], { day, day == current.day and month == current.month and year == current.year, true } ) if weekday == 7 then row = row + 1 weekday = 1 else weekday = weekday + 1 end end local next_month = month + 1 == 13 and 1 or month + 1 local next_year = next_month == 1 and year + 1 or year for day = 1, 42 - prev_offset - days do table.insert( grid[row], { day, day == current.day and next_month + 1 == current.month and next_year == current.year, false } ) if weekday == 7 then row = row + 1 weekday = 1 else weekday = weekday + 1 end end end w_month.text = month w_year.text = year self:render(grid) end -- Set up the widget for _ = 1, 49 do local cell = wibox.widget { widget = wibox.container.background, bg = qcolor.palette.bg.high, { widget = wibox.container.margin, margins = qui.PADDING * 1.5, { widget = wibox.container.place, forced_height = qui.CHAR_HEIGHT, forced_width = qui.CHAR_HEIGHT, { widget = wibox.widget.textbox, markup = "", }, }, }, } l_grid:add(cell) end local current_time = os.date "*t" M:compute(current_time.year, current_time.month) l_grid:add_row_border(2, qui.BORDER_WIDTH, { color = qcolor.palette.border() }) return M