2022-08-31 12:20:58 +00:00
-- This file is part of Reno desktop.
--
-- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
--
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
2022-08-23 13:03:15 +00:00
-- POLYMENU - brutal deluxe
-- This isn't in the widgets folder because it's too meta to be there
local awful = require ( " awful " )
local gears = require ( " gears " )
local menubar_utils = require ( " menubar.utils " )
local wibox = require ( " wibox " )
local awmtk2 = require ( " awmtk2 " )
local function position_popup ( popup , widget , style )
-- Position the popup somewhere nearby our original widget
popup : move_next_to ( mouse.current_wibox )
-- Figure out the geometry of the base widget
local widget_geo
2022-08-25 15:27:31 +00:00
for k , v in pairs ( mouse.current_widgets or { } ) do
2022-09-04 12:05:41 +00:00
if ( widget == v ) and mouse.current_widget_geometries then
2022-08-23 13:03:15 +00:00
widget_geo = mouse.current_widget_geometries [ k ]
end
end
-- Align y coordinate of the popup to the button
if widget_geo then
local wibox_geo = mouse.current_wibox : geometry ( )
if popup.current_anchor == " front " then
popup.y = widget_geo.y + wibox_geo.y - style.popup . margins
else
popup.y = widget_geo.y + wibox_geo.y + style.popup . margins + widget_geo.height - popup : geometry ( ) . height
end
end
-- Finally, make widget visible
popup.visible = true
end
return function ( args )
2022-08-25 15:27:31 +00:00
-- A way to communicate that all widgets in menu got closed
args.on_close = args.on_close or function ( ) end
2022-09-05 21:54:11 +00:00
local style = awmtk2.create_style ( " menu " ,
awmtk2.generic . menu , args.style )
2022-08-23 13:03:15 +00:00
local templates = awmtk2.create_template_lib ( " menu " , awmtk2.templates , args.templates )
local t = awmtk2.build_templates ( templates , style )
local function menu_builder ( element , layer , root_layer )
local new_element = wibox.widget ( t.button ( t.article ( {
icon = element [ 3 ] ,
resize = true ,
title = element [ 1 ]
} ) , {
forced_width = style.button . forced_width ,
forced_height = style.button . forced_height
} ) )
2022-08-25 15:27:31 +00:00
local onpress = function ( widget )
style.button . onrelease ( widget )
2022-09-03 11:55:09 +00:00
widget : emit_signal ( " cascade::kill " )
2022-08-25 15:27:31 +00:00
if root_layer.focused then
root_layer.focused : emit_signal ( " cascade::kill " )
end
end
2022-08-23 13:03:15 +00:00
if type ( element [ 2 ] ) == " string " then
new_element : connect_signal ( " button::press " , style.button . onpress )
new_element : connect_signal ( " button::press " , function ( widget )
awful.spawn ( element [ 2 ] )
end )
2022-08-25 15:27:31 +00:00
new_element : connect_signal ( " button::release " , onpress )
2022-08-23 13:03:15 +00:00
elseif type ( element [ 2 ] ) == " function " then
new_element : connect_signal ( " button::press " , style.button . onpress )
new_element : connect_signal ( " button::press " , element [ 2 ] )
2022-08-25 15:27:31 +00:00
new_element : connect_signal ( " button::release " , onpress )
2022-08-23 13:03:15 +00:00
elseif type ( element [ 2 ] ) == " table " then
local layout = {
spacing = style.base . spacing ,
layout = wibox.layout . fixed.vertical
}
for k , v in pairs ( element [ 2 ] ) do
table.insert ( layout , menu_builder ( v , layout , root_layer ) )
end
local next_layer = awful.popup ( t.popup ( layout , {
visible = false ,
ontop = true ,
preferred_positions = { " right " , " left " } ,
preferred_anchors = { " front " , " back " } ,
} ) )
local function open_layer ( widget )
if layer.focused == widget and
next_layer.visible then
return
end
if layer.focused then
2022-08-25 15:27:31 +00:00
layer.focused : emit_signal ( " cascade::close " )
2022-08-23 13:03:15 +00:00
end
layer.focused = widget
position_popup ( next_layer , new_element , style )
end
2022-08-25 15:27:31 +00:00
local onclose = function ( )
2022-08-23 13:03:15 +00:00
style.button . onrelease ( new_element )
if layout.focused then
2022-08-25 15:27:31 +00:00
layout.focused : emit_signal ( " cascade::close " )
2022-08-23 13:03:15 +00:00
end
next_layer.visible = false
2022-08-25 15:27:31 +00:00
end
new_element : connect_signal ( " cascade::close " , onclose )
new_element : connect_signal ( " cascade::kill " , onclose )
2022-08-23 13:03:15 +00:00
-- that sweet "just move the mouse 4head" navigation
if style.base . menu_slide then
new_element : connect_signal ( " mouse::enter " , open_layer )
new_element : connect_signal ( " mouse::enter " , style.button . onpress )
else
new_element : connect_signal ( " button::press " , style.button . onpress )
new_element : connect_signal ( " button::press " , open_layer )
end
end
return new_element
end
local root_layer = {
layout = wibox.layout . fixed.vertical ,
id = " menu_root " ,
spacing = style.base . spacing
}
for k , v in pairs ( args.items ) do
table.insert ( root_layer , menu_builder ( v , root_layer , root_layer ) )
end
return root_layer
end