259 lines
8.6 KiB
Lua
259 lines
8.6 KiB
Lua
|
-------------------------------------------------
|
||
|
-- Calendar Widget for Awesome Window Manager
|
||
|
-- Shows the current month and supports scroll up/down to switch month
|
||
|
-- More details could be found here:
|
||
|
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/calendar-widget
|
||
|
|
||
|
-- @author Pavel Makhov
|
||
|
-- @copyright 2019 Pavel Makhov
|
||
|
-------------------------------------------------
|
||
|
|
||
|
local awful = require("awful")
|
||
|
local beautiful = require("beautiful")
|
||
|
local wibox = require("wibox")
|
||
|
local gears = require("gears")
|
||
|
local naughty = require("naughty")
|
||
|
|
||
|
local calendar_widget = {}
|
||
|
|
||
|
local function worker(user_args)
|
||
|
|
||
|
local calendar_themes = {
|
||
|
nord = {
|
||
|
bg = '#2E3440',
|
||
|
fg = '#D8DEE9',
|
||
|
focus_date_bg = '#88C0D0',
|
||
|
focus_date_fg = '#000000',
|
||
|
weekend_day_bg = '#3B4252',
|
||
|
weekday_fg = '#88C0D0',
|
||
|
header_fg = '#E5E9F0',
|
||
|
border = '#4C566A'
|
||
|
},
|
||
|
outrun = {
|
||
|
bg = '#0d0221',
|
||
|
fg = '#D8DEE9',
|
||
|
focus_date_bg = '#650d89',
|
||
|
focus_date_fg = '#2de6e2',
|
||
|
weekend_day_bg = '#261447',
|
||
|
weekday_fg = '#2de6e2',
|
||
|
header_fg = '#f6019d',
|
||
|
border = '#261447'
|
||
|
},
|
||
|
dark = {
|
||
|
bg = '#000000',
|
||
|
fg = '#ffffff',
|
||
|
focus_date_bg = '#ffffff',
|
||
|
focus_date_fg = '#000000',
|
||
|
weekend_day_bg = '#444444',
|
||
|
weekday_fg = '#ffffff',
|
||
|
header_fg = '#ffffff',
|
||
|
border = '#333333'
|
||
|
},
|
||
|
light = {
|
||
|
bg = '#ffffff',
|
||
|
fg = '#000000',
|
||
|
focus_date_bg = '#000000',
|
||
|
focus_date_fg = '#ffffff',
|
||
|
weekend_day_bg = '#AAAAAA',
|
||
|
weekday_fg = '#000000',
|
||
|
header_fg = '#000000',
|
||
|
border = '#CCCCCC'
|
||
|
},
|
||
|
monokai = {
|
||
|
bg = '#272822',
|
||
|
fg = '#F8F8F2',
|
||
|
focus_date_bg = '#AE81FF',
|
||
|
focus_date_fg = '#ffffff',
|
||
|
weekend_day_bg = '#75715E',
|
||
|
weekday_fg = '#FD971F',
|
||
|
header_fg = '#F92672',
|
||
|
border = '#75715E'
|
||
|
},
|
||
|
naughty = {
|
||
|
bg = beautiful.notification_bg or beautiful.bg,
|
||
|
fg = beautiful.notification_fg or beautiful.fg,
|
||
|
focus_date_bg = beautiful.notification_fg or beautiful.fg,
|
||
|
focus_date_fg = beautiful.notification_bg or beautiful.bg,
|
||
|
weekend_day_bg = beautiful.bg_focus,
|
||
|
weekday_fg = beautiful.fg,
|
||
|
header_fg = beautiful.fg,
|
||
|
border = beautiful.border_normal
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
local args = user_args or {}
|
||
|
|
||
|
if args.theme ~= nil and calendar_themes[args.theme] == nil then
|
||
|
naughty.notify({
|
||
|
preset = naughty.config.presets.critical,
|
||
|
title = 'Calendar Widget',
|
||
|
text = 'Theme "' .. args.theme .. '" not found, fallback to default'})
|
||
|
args.theme = 'naughty'
|
||
|
end
|
||
|
|
||
|
local theme = args.theme or 'naughty'
|
||
|
local placement = args.placement or 'top'
|
||
|
local radius = args.radius or 8
|
||
|
local next_month_button = args.next_month_button or 4
|
||
|
local previous_month_button = args.previous_month_button or 5
|
||
|
local start_sunday = args.start_sunday or false
|
||
|
|
||
|
local styles = {}
|
||
|
local function rounded_shape(size)
|
||
|
return function(cr, width, height)
|
||
|
gears.shape.rounded_rect(cr, width, height, size)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
styles.month = {
|
||
|
padding = 4,
|
||
|
bg_color = calendar_themes[theme].bg,
|
||
|
border_width = 0,
|
||
|
}
|
||
|
|
||
|
styles.normal = {
|
||
|
markup = function(t) return t end,
|
||
|
shape = rounded_shape(4)
|
||
|
}
|
||
|
|
||
|
styles.focus = {
|
||
|
fg_color = calendar_themes[theme].focus_date_fg,
|
||
|
bg_color = calendar_themes[theme].focus_date_bg,
|
||
|
markup = function(t) return '<b>' .. t .. '</b>' end,
|
||
|
shape = rounded_shape(4)
|
||
|
}
|
||
|
|
||
|
styles.header = {
|
||
|
fg_color = calendar_themes[theme].header_fg,
|
||
|
bg_color = calendar_themes[theme].bg,
|
||
|
markup = function(t) return '<b>' .. t .. '</b>' end
|
||
|
}
|
||
|
|
||
|
styles.weekday = {
|
||
|
fg_color = calendar_themes[theme].weekday_fg,
|
||
|
bg_color = calendar_themes[theme].bg,
|
||
|
markup = function(t) return '<b>' .. t .. '</b>' end,
|
||
|
}
|
||
|
|
||
|
local function decorate_cell(widget, flag, date)
|
||
|
if flag == 'monthheader' and not styles.monthheader then
|
||
|
flag = 'header'
|
||
|
end
|
||
|
|
||
|
-- highlight only today's day
|
||
|
if flag == 'focus' then
|
||
|
local today = os.date('*t')
|
||
|
if not (today.month == date.month and today.year == date.year) then
|
||
|
flag = 'normal'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local props = styles[flag] or {}
|
||
|
if props.markup and widget.get_text and widget.set_markup then
|
||
|
widget:set_markup(props.markup(widget:get_text()))
|
||
|
end
|
||
|
-- Change bg color for weekends
|
||
|
local d = { year = date.year, month = (date.month or 1), day = (date.day or 1) }
|
||
|
local weekday = tonumber(os.date('%w', os.time(d)))
|
||
|
local default_bg = (weekday == 0 or weekday == 6)
|
||
|
and calendar_themes[theme].weekend_day_bg
|
||
|
or calendar_themes[theme].bg
|
||
|
local ret = wibox.widget {
|
||
|
{
|
||
|
{
|
||
|
widget,
|
||
|
halign = 'center',
|
||
|
widget = wibox.container.place
|
||
|
},
|
||
|
margins = (props.padding or 2) + (props.border_width or 0),
|
||
|
widget = wibox.container.margin
|
||
|
},
|
||
|
shape = props.shape,
|
||
|
shape_border_color = props.border_color or '#000000',
|
||
|
shape_border_width = props.border_width or 0,
|
||
|
fg = props.fg_color or calendar_themes[theme].fg,
|
||
|
bg = props.bg_color or default_bg,
|
||
|
widget = wibox.container.background
|
||
|
}
|
||
|
|
||
|
return ret
|
||
|
end
|
||
|
|
||
|
local cal = wibox.widget {
|
||
|
date = os.date('*t'),
|
||
|
font = beautiful.get_font(),
|
||
|
fn_embed = decorate_cell,
|
||
|
long_weekdays = true,
|
||
|
start_sunday = start_sunday,
|
||
|
widget = wibox.widget.calendar.month
|
||
|
}
|
||
|
|
||
|
local popup = awful.popup {
|
||
|
ontop = true,
|
||
|
visible = false,
|
||
|
shape = rounded_shape(radius),
|
||
|
offset = { y = 5 },
|
||
|
border_width = 1,
|
||
|
border_color = calendar_themes[theme].border,
|
||
|
widget = cal
|
||
|
}
|
||
|
|
||
|
popup:buttons(
|
||
|
awful.util.table.join(
|
||
|
awful.button({}, next_month_button, function()
|
||
|
local a = cal:get_date()
|
||
|
a.month = a.month + 1
|
||
|
cal:set_date(nil)
|
||
|
cal:set_date(a)
|
||
|
popup:set_widget(cal)
|
||
|
end),
|
||
|
awful.button({}, previous_month_button, function()
|
||
|
local a = cal:get_date()
|
||
|
a.month = a.month - 1
|
||
|
cal:set_date(nil)
|
||
|
cal:set_date(a)
|
||
|
popup:set_widget(cal)
|
||
|
end)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
function calendar_widget.toggle()
|
||
|
|
||
|
if popup.visible then
|
||
|
-- to faster render the calendar refresh it and just hide
|
||
|
cal:set_date(nil) -- the new date is not set without removing the old one
|
||
|
cal:set_date(os.date('*t'))
|
||
|
popup:set_widget(nil) -- just in case
|
||
|
popup:set_widget(cal)
|
||
|
popup.visible = not popup.visible
|
||
|
else
|
||
|
if placement == 'top' then
|
||
|
awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() })
|
||
|
elseif placement == 'top_right' then
|
||
|
awful.placement.top_right(popup, { margins = { top = 30, right = 10}, parent = awful.screen.focused() })
|
||
|
elseif placement == 'top_left' then
|
||
|
awful.placement.top_left(popup, { margins = { top = 30, left = 10}, parent = awful.screen.focused() })
|
||
|
elseif placement == 'bottom_right' then
|
||
|
awful.placement.bottom_right(popup, { margins = { bottom = 30, right = 10},
|
||
|
parent = awful.screen.focused() })
|
||
|
elseif placement == 'bottom_left' then
|
||
|
awful.placement.bottom_left(popup, { margins = { bottom = 30, left = 10},
|
||
|
parent = awful.screen.focused() })
|
||
|
else
|
||
|
awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() })
|
||
|
end
|
||
|
|
||
|
popup.visible = true
|
||
|
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return calendar_widget
|
||
|
|
||
|
end
|
||
|
|
||
|
return setmetatable(calendar_widget, { __call = function(_, ...)
|
||
|
return worker(...)
|
||
|
end })
|