nixos-config/modules/home-manager/ricing/awesomewm/dotfiles/mods/menu.lua
2024-07-12 18:19:30 +09:00

343 lines
7.7 KiB
Lua

local awful = require("awful")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local wibox = require("wibox")
local beautiful = require("beautiful")
local helpers = require("helpers")
local dpi = beautiful.xresources.apply_dpi
local setmetatable = setmetatable
local ipairs = ipairs
local capi = { awesome = awesome, mouse = mouse, tag = tag }
local menu = { mt = {} }
function menu:set_pos(args)
args = args or {}
local coords = args.coords
local wibox = args.wibox
local widget = args.widget
local offset = args.offset or { x = 0, y = 0 }
if offset.x == nil then
offset.x = 0
end
if offset.y == nil then
offset.y = 0
end
local screen_workarea = awful.screen.focused().workarea
local screen_w = screen_workarea.x + screen_workarea.width
local screen_h = screen_workarea.y + screen_workarea.height
if not coords and wibox and widget then
coords = helpers.get_widget_geometry(wibox, widget)
else
coords = args.coords or capi.mouse.coords()
end
if coords.x + self.width > screen_w then
if self.parent_menu ~= nil then
self.x = coords.x - (self.width * 2) - offset.x
else
self.x = coords.x - self.width + offset.x
end
else
self.x = coords.x + offset.x
end
if coords.y + self.height > screen_h then
self.y = screen_h - self.height + offset.y
else
self.y = coords.y + offset.y
end
end
function menu:hide_parents_menus()
if self.parent_menu ~= nil then
self.parent_menu:hide(true)
end
end
function menu:hide_children_menus()
if self.widget then
for _, button in ipairs(self.widget.children) do
if button.sub_menu ~= nil then
button.sub_menu:hide()
end
end
end
end
function menu:hide(hide_parents)
if self.visible == false then
return
end
-- Hide self
self.visible = false
-- Hides all child menus
self:hide_children_menus()
if hide_parents == true then
self:hide_parents_menus()
end
end
function menu:show(args)
if self.visible == true then
return
end
self.can_hide = false
gtimer({
timeout = 0.1,
autostart = true,
call_now = false,
single_shot = true,
callback = function()
self.can_hide = true
end,
})
-- Hide sub menus belonging to the menu of self
if self.parent_menu ~= nil then
for _, button in ipairs(self.parent_menu.widget.children) do
if button.sub_menu ~= nil and button.sub_menu ~= self then
button.sub_menu:hide()
end
end
end
self:set_pos(args)
self.visible = true
capi.awesome.emit_signal("menu::toggled_on", self)
end
function menu:toggle(args)
if self.visible == true then
self:hide()
else
self:show(args)
end
end
function menu:add(widget)
if widget.sub_menu then
widget.sub_menu.parent_menu = self
end
widget.menu = self
self.widget:add(widget)
end
function menu:remove(widget)
self.widget:remove(widget)
end
function menu:reset()
self.widget:reset()
end
function menu.menu(widgets, width)
local widget = awful.popup({
x = 32500,
type = "menu",
visible = false,
ontop = true,
minimum_width = width or dpi(300),
maximum_width = width or dpi(300),
shape = helpers.rrect(9),
bg = beautiful.main_menu_bg,
widget = wibox.layout.fixed.vertical,
})
gtable.crush(widget, menu, true)
awful.mouse.append_client_mousebinding(awful.button({ "Any" }, 1, function(c)
if widget.can_hide == true then
widget:hide(true)
end
end))
awful.mouse.append_client_mousebinding(awful.button({ "Any" }, 3, function(c)
if widget.can_hide == true then
widget:hide(true)
end
end))
awful.mouse.append_global_mousebinding(awful.button({ "Any" }, 1, function(c)
if widget.can_hide == true then
widget:hide(true)
end
end))
awful.mouse.append_global_mousebinding(awful.button({ "Any" }, 3, function(c)
if widget.can_hide == true then
widget:hide(true)
end
end))
capi.tag.connect_signal("property::selected", function(t)
widget:hide(true)
end)
capi.awesome.connect_signal("menu::toggled_on", function(menu)
if menu ~= widget and menu.parent_menu == nil then
widget:hide(true)
end
end)
for _, menu_widget in ipairs(widgets) do
widget:add(menu_widget)
end
return widget
end
function menu.sub_menu_button(args)
args = args or {}
args.icon = args.icon or nil
args.icon_size = args.icon_size or 16
args.text = args.text or ""
args.text_size = args.text_size or 12
args.sub_menu = args.sub_menu or nil
local icon = args.icon ~= nil
and wibox.widget {
font = args.icon.font .. " " .. args.icon_size,
markup = helpers.colorizeText(args.icon.icon, helpers.randomColor()),
widget = wibox.widget.textbox,
halign = "start",
forced_width = 40,
} or nil
local widget = wibox.widget {
{
{
layout = wibox.layout.align.horizontal,
forced_width = dpi(270),
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(10),
icon,
{
font = beautiful.sans .. " " .. args.text_size,
markup = args.text,
widget = wibox.widget.textbox,
halign = "start"
},
},
nil,
{
font = beautiful.icon .. " " .. "18",
markup = "󰅂",
widget = wibox.widget.textbox,
halign = "start"
},
},
widget = wibox.container.margin,
margins = 10
},
bg = beautiful.bg,
forced_height = 48,
shape = helpers.rrect(9),
widget = wibox.container.background,
}
widget:connect_signal("mouse::enter", function(self)
local coords = helpers.get_widget_geometry(self.menu, self)
coords.x = coords.x + self.menu.x + self.menu.width
coords.y = coords.y + self.menu.y
args.sub_menu:show({ coords = coords, offset = { x = -5 } })
end)
widget.sub_menu = args.sub_menu
return widget
end
function menu.button(args)
args = args or {}
args.icon = args.icon or nil
args.icon_size = args.icon_size or 16
args.image = args.image
args.text = args.text or ""
args.text_size = args.text_size or 12
args.on_press = args.on_press or nil
local icon = nil
if args.icon ~= nil then
icon = wibox.widget {
font = args.icon.font .. " " .. args.icon_size,
markup = helpers.colorizeText(args.icon.icon, helpers.randomColor()),
widget = wibox.widget.textbox,
halign = "start"
}
elseif args.image ~= nil then
icon = wibox.widget({
widget = wibox.widget.imagebox,
image = args.image,
})
end
local text_widget = wibox.widget {
font = beautiful.sans .. " " .. args.text_size,
markup = args.text,
widget = wibox.widget.textbox,
halign = "start"
}
local widget = wibox.widget {
{
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(15),
icon,
text_widget,
},
widget = wibox.container.margin,
margins = 10
},
bg = beautiful.bg,
forced_height = 48,
shape = helpers.rrect(9),
buttons = {
awful.button({}, 1, function()
args.on_press(menu, text_widget)
menu:hide(true)
end)
},
widget = wibox.container.background,
}
widget:connect_signal("mouse::enter", function(self)
if self.menu.widget then self.menu:hide_children_menus() end
end)
return widget
end
function menu.separator()
return wibox.widget({
widget = wibox.container.margin,
top = 10,
bottom = 10,
left = 40,
right = 40,
{
widget = wibox.widget.separator,
forced_height = dpi(2),
orientation = "horizontal",
thickness = dpi(1),
color = beautiful.fg .. "29",
},
})
end
function menu.mt:__call(...)
return menu.menu(...)
end
return setmetatable(menu, menu.mt)