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-21 12:28:28 +00:00
-- JSON layout builder
local json = require ( " dkjson " )
local gears = require ( " gears " )
local wibox = require ( " wibox " )
local awful = require ( " awful " )
2023-03-05 12:53:37 +00:00
local menu = require ( " context_menu " )
2022-08-21 12:28:28 +00:00
local builtins = {
h_spacer = function ( o )
return {
forced_width = o.size or 3 ,
widget = wibox.container . background
}
end ,
v_spacer = function ( o )
return {
forced_height = o.size or 3 ,
widget = wibox.container . background
}
end
-- Insert your other builtins here
}
-- Load a bunch of builtins from awful.titlebar
for _ , name in pairs ( {
" titlewidget " , " iconwidget " , " floatingbutton " ,
" maximizedbutton " , " minimizebutton " , " closebutton " ,
" ontopbutton " , " stickybutton "
} ) do
builtins [ name ] = function ( o )
o.widget = awful.titlebar . widget [ name ] ( o.client )
return o
end
end
return function ( description , opts )
local style = opts.style or { }
local c = opts.client
local s = opts.screen
local buttons = opts.buttons
-- Build a layout given a JSON description, a style and client
-- (if applicable)
local test , err = json.decode ( description )
if not test then
error ( " Builder failure: " .. err )
end
2023-03-05 13:26:33 +00:00
local function inner_builder ( struct , options , vertical )
2022-08-21 12:28:28 +00:00
if struct.widget then -- External widget descriptions
2023-01-19 13:42:20 +00:00
local args = gears.table . join ( {
2023-03-05 13:26:33 +00:00
layout = ( struct.layout and inner_builder ( struct.layout , options ) ) ,
client = ( struct.client and c ) ,
2023-01-16 12:47:51 +00:00
screen = ( struct.screen and s ) ,
2023-01-19 13:42:20 +00:00
vertical = ( function ( )
if type ( struct.vertical ) ~= " nil " then
return struct.vertical
end
return vertical
end ) ( )
2023-03-05 13:26:33 +00:00
} , struct.options or { } , options.passthrough or { } )
2023-01-19 13:42:20 +00:00
return require ( struct.widget ) ( args )
2022-08-21 12:28:28 +00:00
elseif struct.list then -- List descriptions
local list = {
layout = wibox.layout . fixed [ (
( struct.vertical and " vertical " ) or
" horizontal "
) ] ,
2023-01-27 22:09:24 +00:00
spacing = style.spacing or struct.spacing
2022-08-21 12:28:28 +00:00
}
2023-01-16 12:47:51 +00:00
for _ , v in pairs ( struct.list ) do
2022-08-21 12:28:28 +00:00
if v.draggable then
list.buttons = buttons
else
2023-03-05 13:26:33 +00:00
local new_obj = inner_builder ( v , options , struct.vertical )
2022-08-31 12:51:03 +00:00
if new_obj then
table.insert ( list , new_obj )
end
2022-08-21 12:28:28 +00:00
end
end
return list
elseif struct.align then -- Align structure descriptions
local orient = (
( struct.vertical and " vertical " ) or
" horizontal "
)
local list = {
{
layout = wibox.layout . fixed [ orient ] ,
2023-01-27 22:09:24 +00:00
spacing = style.spacing or struct.spacing
2022-08-21 12:28:28 +00:00
} , {
layout = wibox.layout . flex [ orient ] ,
2023-01-27 22:09:24 +00:00
spacing = style.spacing or struct.spacing
2022-08-21 12:28:28 +00:00
} , {
-- Simulating "spacing" parameter
widget = builtins [ ( struct.vertical and " v_spacer " ) or
" h_spacer " ] ( { size = style.spacing } ) ,
layout = wibox.layout . fixed [ orient ] ,
2023-01-27 22:09:24 +00:00
spacing = style.spacing or struct.spacing
2022-08-21 12:28:28 +00:00
} ,
2023-01-27 22:09:24 +00:00
layout = wibox.layout . align [ orient ] ,
2022-08-21 12:28:28 +00:00
}
for k , v in pairs ( { " left " , " center " , " right " } ) do
for _ , obj in pairs ( struct.align [ v ] ) do
if obj.draggable then
list [ k ] . buttons = buttons
else
2023-03-05 13:26:33 +00:00
local new_obj = inner_builder ( obj , options , struct.vertical )
2022-08-31 12:51:03 +00:00
if new_obj then
table.insert ( list [ k ] , new_obj )
end
2022-08-21 12:28:28 +00:00
end
end
end
-- Part of simulating "spacing" parameter
table.insert ( list [ 1 ] , builtins [ ( struct.vertical and " v_spacer " ) or
" h_spacer " ] ( { size = style.spacing } ) )
return list
elseif struct.builtin then -- Builtin widget descriptions
if not builtins [ struct.builtin ] then
error ( " Builtin not defined: " .. struct.builtin )
end
return builtins [ struct.builtin ] ( gears.table . join ( {
client = ( struct.client and c )
} , struct.options or { } ) )
2023-03-05 13:26:33 +00:00
elseif struct.multimenu then -- Multimenus, or otherwise "Context menu mergers".
-- These merge multiple menus into one using the menu_parent argument.
2023-03-05 12:53:37 +00:00
local multimenu = menu ( { items = { } } )
2023-03-05 13:26:33 +00:00
local newopts = { }
for k , v in pairs ( options ) do
newopts [ k ] = v
2023-03-05 12:53:37 +00:00
end
2023-03-05 13:26:33 +00:00
newopts.passthrough = options.passthrough or { }
newopts.passthrough . menu_parent = multimenu
2023-03-05 12:53:37 +00:00
for _ , v in pairs ( struct.multimenu ) do
2023-03-05 13:26:33 +00:00
inner_builder ( v , newopts , struct.vertical )
2023-03-05 12:53:37 +00:00
end
return multimenu
2023-01-16 12:47:51 +00:00
end
2022-08-21 12:28:28 +00:00
-- If this gets interpreted it's safe to say none of the constructions
-- above got matched.
2023-03-05 12:53:37 +00:00
print ( " Object dump: " )
2023-01-16 12:47:51 +00:00
gears.debug . dump ( struct )
2022-08-21 12:28:28 +00:00
error ( " Builder error: invalid object description " )
end
2023-03-05 13:26:33 +00:00
return inner_builder ( test , opts ) , test.context_options
2022-08-21 12:28:28 +00:00
end