227 lines
6.4 KiB
Lua
227 lines
6.4 KiB
Lua
--[[
|
|
|
|
Licensed under GNU General Public License v2
|
|
* (c) 2018, Luca CPZ
|
|
|
|
--]]
|
|
|
|
local helpers = require('lain.helpers')
|
|
local markup = require('lain.util.markup')
|
|
local awful = require('awful')
|
|
local naughty = require('naughty')
|
|
local floor = math.floor
|
|
local os = os
|
|
local pairs = pairs
|
|
local string = string
|
|
local tconcat = table.concat
|
|
local type = type
|
|
local tonumber = tonumber
|
|
local tostring = tostring
|
|
|
|
-- Calendar notification
|
|
-- lain.widget.cal
|
|
|
|
local function factory(args)
|
|
args = args or {}
|
|
local cal = {
|
|
attach_to = args.attach_to or {},
|
|
week_start = args.week_start or 2,
|
|
three = args.three or false,
|
|
followtag = args.followtag or false,
|
|
week_number = args.week_number or 'none',
|
|
week_number_format = args.week_number_format or args.week_number == 'left' and '%3d | ' or '| %-3d',
|
|
icons = args.icons or helpers.icons_dir .. 'cal/white/',
|
|
notification_preset = args.notification_preset or {
|
|
font = 'Monospace 10',
|
|
fg = '#FFFFFF',
|
|
bg = '#000000',
|
|
},
|
|
}
|
|
|
|
function cal.get_week_number(m, st_day, x)
|
|
local date = os.date('*t', m)
|
|
|
|
local week_step = (x ~= 0 and floor((x + st_day) / 7) - 1 or 0)
|
|
|
|
local display_time = os.time({
|
|
year = date.year,
|
|
month = date.month,
|
|
day = date.day + 7 * week_step,
|
|
})
|
|
|
|
return string.format(cal.week_number_format, os.date('%V', display_time))
|
|
end
|
|
|
|
function cal.sum_week_days(x, y)
|
|
return (x + y) % 7
|
|
end
|
|
|
|
function cal.build(month, year)
|
|
local current_month, current_year = tonumber(os.date('%m')), tonumber(os.date('%Y'))
|
|
local is_current_month = (not month or not year) or (month == current_month and year == current_year)
|
|
local today = is_current_month and tonumber(os.date('%d')) -- otherwise nil and not highlighted
|
|
local t = os.time({ year = year or current_year, month = month and month + 1 or current_month + 1, day = 0 })
|
|
local d = os.date('*t', t)
|
|
local mth_days, st_day, this_month = d.day, (d.wday - d.day - cal.week_start + 1) % 7, os.date('%B %Y', t)
|
|
local notifytable = {
|
|
[1] = string.format('%s%s\n', string.rep(' ', floor((28 - this_month:len()) / 2)), markup.bold(this_month)),
|
|
}
|
|
for day_num = 0, 6 do
|
|
notifytable[#notifytable + 1] = string.format(
|
|
'%3s ',
|
|
os.date('%a', os.time({ year = 2006, month = 1, day = day_num + cal.week_start }))
|
|
)
|
|
end
|
|
notifytable[#notifytable] =
|
|
string.format('%s\n%s', notifytable[#notifytable]:sub(1, -2), string.rep(' ', st_day * 4))
|
|
local strx
|
|
for x = 1, mth_days do
|
|
strx = x
|
|
if x == today then
|
|
if x < 10 then
|
|
x = ' ' .. x
|
|
end
|
|
strx = markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. ' ')
|
|
end
|
|
strx = string.format('%s%s', string.rep(' ', 3 - tostring(x):len()), strx)
|
|
notifytable[#notifytable + 1] =
|
|
string.format('%-4s%s', strx, (x + st_day) % 7 == 0 and x ~= mth_days and '\n' or '')
|
|
end
|
|
if string.len(cal.icons or '') > 0 and today then
|
|
cal.icon = cal.icons .. today .. '.png'
|
|
end
|
|
cal.month, cal.year = d.month, d.year
|
|
|
|
if cal.week_number ~= 'none' then
|
|
local m = os.time({ year = year or current_year, month = month and month or current_month, day = 1 })
|
|
local head_prepend = string.rep(' ', tostring(string.format(cal.week_number_format, 0)):len())
|
|
|
|
if cal.week_number == 'left' then
|
|
notifytable[1] = head_prepend .. notifytable[1] -- month-year row
|
|
notifytable[2] = head_prepend .. notifytable[2] -- weekdays row
|
|
notifytable[8] = notifytable[8]:gsub('\n', '\n' .. cal.get_week_number(m, st_day, 0)) -- first week of the month
|
|
|
|
for x = 10, #notifytable do
|
|
if cal.sum_week_days(st_day, x) == 2 then
|
|
notifytable[x] = cal.get_week_number(m, st_day, x) .. notifytable[x]
|
|
end
|
|
end
|
|
elseif cal.week_number == 'right' then
|
|
notifytable[8] = notifytable[8]:gsub('\n', head_prepend .. '\n') -- weekdays row
|
|
for x = 9, #notifytable do
|
|
if cal.sum_week_days(st_day, x) == 1 then
|
|
notifytable[x] = notifytable[x]:gsub('\n', cal.get_week_number(m, st_day, x - 7) .. '\n')
|
|
end
|
|
end
|
|
-- last week of the month
|
|
local end_days = cal.sum_week_days(st_day, mth_days)
|
|
if end_days ~= 0 then
|
|
end_days = 7 - end_days
|
|
end
|
|
notifytable[#notifytable] = notifytable[#notifytable]
|
|
.. string.rep(' ', 4 * end_days)
|
|
.. cal.get_week_number(m, st_day, mth_days + end_days)
|
|
end
|
|
end
|
|
|
|
return notifytable
|
|
end
|
|
|
|
function cal.getdate(month, year, offset)
|
|
if not month or not year then
|
|
month = tonumber(os.date('%m'))
|
|
year = tonumber(os.date('%Y'))
|
|
end
|
|
|
|
month = month + offset
|
|
|
|
while month > 12 do
|
|
month = month - 12
|
|
year = year + 1
|
|
end
|
|
|
|
while month < 1 do
|
|
month = month + 12
|
|
year = year - 1
|
|
end
|
|
|
|
return month, year
|
|
end
|
|
|
|
function cal.hide()
|
|
if not cal.notification then
|
|
return
|
|
end
|
|
naughty.destroy(cal.notification)
|
|
cal.notification = nil
|
|
end
|
|
|
|
function cal.show(seconds, month, year, scr)
|
|
local text = tconcat(cal.build(month, year))
|
|
|
|
if cal.three then
|
|
local current_month, current_year = cal.month, cal.year
|
|
local prev_month, prev_year = cal.getdate(cal.month, cal.year, -1)
|
|
local next_month, next_year = cal.getdate(cal.month, cal.year, 1)
|
|
text = string.format(
|
|
'%s\n\n%s\n\n%s',
|
|
tconcat(cal.build(prev_month, prev_year)),
|
|
text,
|
|
tconcat(cal.build(next_month, next_year))
|
|
)
|
|
cal.month, cal.year = current_month, current_year
|
|
end
|
|
|
|
if cal.notification then
|
|
local title = cal.notification_preset.title or nil
|
|
naughty.replace_text(cal.notification, title, text)
|
|
return
|
|
end
|
|
|
|
cal.notification = naughty.notify({
|
|
preset = cal.notification_preset,
|
|
screen = cal.followtag and awful.screen.focused() or scr or 1,
|
|
--icon = cal.icon,
|
|
timeout = type(seconds) == 'number' and seconds or cal.notification_preset.timeout or 5,
|
|
text = text,
|
|
})
|
|
end
|
|
|
|
function cal.hover_on()
|
|
cal.show(0)
|
|
end
|
|
function cal.move(offset)
|
|
offset = offset or 0
|
|
cal.month, cal.year = cal.getdate(cal.month, cal.year, offset)
|
|
cal.show(0, cal.month, cal.year)
|
|
end
|
|
function cal.prev()
|
|
cal.move(-1)
|
|
end
|
|
function cal.next()
|
|
cal.move(1)
|
|
end
|
|
|
|
function cal.attach(widget)
|
|
widget:connect_signal('mouse::enter', cal.hover_on)
|
|
widget:connect_signal('mouse::leave', cal.hide)
|
|
widget:buttons(
|
|
awful.util.table.join(
|
|
awful.button({}, 1, cal.prev),
|
|
awful.button({}, 3, cal.next),
|
|
awful.button({}, 2, cal.hover_on),
|
|
awful.button({}, 5, cal.prev),
|
|
awful.button({}, 4, cal.next)
|
|
)
|
|
)
|
|
end
|
|
|
|
for _, widget in pairs(cal.attach_to) do
|
|
cal.attach(widget)
|
|
end
|
|
|
|
return cal
|
|
end
|
|
|
|
return factory
|