X-Git-Url: https://git.madduck.net/etc/awesome.git/blobdiff_plain/91882180214426b521217649e40adbb0055ed71e..012c6b6215d2b3aad14778e8f55c511e32960c3b:/widget/cal.lua diff --git a/widget/cal.lua b/widget/cal.lua index 7a81c68..11c4bf2 100644 --- a/widget/cal.lua +++ b/widget/cal.lua @@ -11,80 +11,154 @@ local awful = require("awful") local naughty = require("naughty") local floor = math.floor local os = os +local pairs = pairs local string = string -local ipairs = ipairs 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 = { - weekStart = args.weekStart or 2, 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.hide() - if not cal.notification then return end - naughty.destroy(cal.notification) - cal.notification = nil + function cal.get_week_number(m, st_day, x) + return string.format(cal.week_number_format, os.date("%V", m) + (x ~= 0 and floor((x + st_day) / 7) - 1 or 0)) end - function cal.show(timeout, month, year) + 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 mthDays, stDay, cmonth = d.day, (d.wday-d.day-cal.weekStart+1)%7, os.date("%B %Y", t) - local notifytable = { [1] = string.format("%s%s\n", string.rep(" ", floor((28 - cmonth:len())/2)), markup.bold(cmonth)) } - for x = 0,6 do notifytable[#notifytable+1] = os.date("%a ", os.time { year=2006, month=1, day=x+cal.weekStart }) end - notifytable[#notifytable] = string.format("%s\n%s", notifytable[#notifytable]:sub(1, -2), string.rep(" ", stDay*4)) - for x = 1,mthDays do - local strx = x ~= today and x or markup.bold(markup.color(cal.notification_preset.bg, cal.notification_preset.fg, x) .. " ") + 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 x = 0,6 do notifytable[#notifytable+1] = os.date("%a ", os.time { year=2006, month=1, day=x+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+stDay)%7==0 and x ~= mthDays and "\n" or "") + 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 = 0 } + 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) + cal.notification_preset.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) + cal.notification_preset.text = string.format("%s\n\n%s\n\n%s", + tconcat(cal.build(prev_month, prev_year)), cal.notification_preset.text, + tconcat(cal.build(next_month, next_year))) + cal.month, cal.year = current_month, current_year end - cal.notification_preset.text = tconcat(notifytable) cal.hide() cal.notification = naughty.notify { preset = cal.notification_preset, + screen = cal.followtag and awful.screen.focused() or scr or 1, icon = cal.icon, - timeout = timeout or cal.notification_preset.timeout or 5 + timeout = type(seconds) == "number" and seconds or cal.notification_preset.timeout or 5 } - cal.month, cal.year = d.month, d.year end function cal.hover_on() cal.show(0) end - function cal.hover_off() cal.hide() end - function cal.prev() - cal.month = cal.month - 1 - if cal.month == 0 then - cal.month = 12 - cal.year = cal.year - 1 - end - cal.show(0, cal.month, cal.year) - end - function cal.next() - cal.month = cal.month + 1 - if cal.month == 13 then - cal.month = 1 - cal.year = cal.year + 1 - end + function cal.move(offset) + local 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.hover_off) + widget:connect_signal("mouse::leave", cal.hide) widget:buttons(awful.util.table.join( awful.button({}, 1, cal.prev), awful.button({}, 3, cal.next), @@ -93,7 +167,7 @@ local function factory(args) awful.button({}, 4, cal.next))) end - for _, widget in ipairs(cal.attach_to) do cal.attach(widget) end + for _, widget in pairs(cal.attach_to) do cal.attach(widget) end return cal end