Change Lua builtin layouts to classes

This commit is contained in:
Ottatop 2024-03-16 19:58:38 -05:00
parent 17d0760e43
commit 88988701e6
2 changed files with 287 additions and 191 deletions

View file

@ -89,24 +89,19 @@ require("pinnacle").setup(function(Pinnacle)
-- Layouts -- -- Layouts --
-------------------- --------------------
-- TODO: convert layouts into objs, deep_copy doesn't work on fns
local master_stack_right = Util.deep_copy(Layout.builtins.master_stack)
master_stack_right.master_side = "right"
local master_stack_top = Util.deep_copy(Layout.builtins.master_stack)
master_stack_top.master_side = "top"
local master_stack_bottom = Util.deep_copy(Layout.builtins.master_stack)
master_stack_bottom.master_side = "bottom"
local layout_manager = Layout.new_cycling_manager({ local layout_manager = Layout.new_cycling_manager({
Layout.builtins.master_stack, Layout.builtins.master_stack(),
master_stack_right, Layout.builtins.master_stack({ master_side = "right" }),
master_stack_top, Layout.builtins.master_stack({ master_side = "top" }),
master_stack_bottom, Layout.builtins.master_stack({ master_side = "bottom" }),
Layout.builtins.dwindle, Layout.builtins.dwindle(),
Layout.builtins.spiral, Layout.builtins.spiral(),
Layout.builtins.corner, Layout.builtins.corner(),
Layout.builtins.fair, Layout.builtins.corner({ corner_loc = "top_right" }),
Layout.builtins.corner({ corner_loc = "bottom_left" }),
Layout.builtins.corner({ corner_loc = "bottom_right" }),
Layout.builtins.fair(),
Layout.builtins.fair({ direction = "horizontal" }),
}) })
Layout.set_manager(layout_manager) Layout.set_manager(layout_manager)

View file

@ -43,45 +43,19 @@ end
---Generate an array of geometries from the given `LayoutArgs`. ---Generate an array of geometries from the given `LayoutArgs`.
---@field layout fun(self: self, args: LayoutArgs): { x: integer, y: integer, width: integer, height: integer }[] ---@field layout fun(self: self, args: LayoutArgs): { x: integer, y: integer, width: integer, height: integer }[]
---Builtin layout generators.
---
---This contains functions that create various builtin generators.
---@class Builtin
local builtins = {}
----------------------------------------
-- Master Stack --
----------------------------------------
---A `LayoutGenerator` that has one master area to one side ---A `LayoutGenerator` that has one master area to one side
---and a stack of windows next to it. ---and a stack of windows next to it.
---@class Builtin.MasterStack: LayoutGenerator ---@class Builtin.MasterStack: LayoutGenerator
---@field gaps integer | { inner: integer, outer: integer }
---@field master_factor number
---@field master_side "left"|"right"|"top"|"bottom"
---@field master_count integer
---A `LayoutGenerator` that lays out windows in a shrinking fashion
---towards the bottom right corner.
---@class Builtin.Dwindle : LayoutGenerator
---@field gaps integer | { inner: integer, outer: integer }
---@field split_factors table<integer, number>
---A `LayoutGenerator` that has one main corner window and a
---horizontal and vertical stack flanking it on the other two sides.
---@class Builtin.Corner : LayoutGenerator
---@field gaps integer | { inner: integer, outer: integer }
---@field corner_width_factor number
---@field corner_height_factor number
---@field corner_loc "top_left"|"top_right"|"bottom_left"|"bottom_right"
---A `LayoutGenerator` that lays out windows in a spiral.
---
---This is similar to the dwindle layout but in a spiral instead of
---towards the borrom right corner.
---@class Builtin.Spiral : LayoutGenerator
---@field gaps integer | { inner: integer, outer: integer }
---@field split_factors table<integer, number>
---A `LayoutGenerator` that attempts to layout windows such that
---they are the same size.
---@class Builtin.Fair : LayoutGenerator
---@field gaps integer | { inner: integer, outer: integer }
---@field direction "horizontal"|"vertical"
local builtins = {
---@type Builtin.MasterStack
master_stack = {
---Gaps between windows, in pixels. ---Gaps between windows, in pixels.
--- ---
---This can be an integer or the table { inner: integer, outer: integer }. ---This can be an integer or the table { inner: integer, outer: integer }.
@ -93,133 +67,35 @@ local builtins = {
--- ---
---This means that, for example, `inner = 2` will cause the gap ---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window. ---width between windows to be 4; 2 around each window.
--- ---@field gaps integer | { inner: integer, outer: integer }
---Defaults to 8.
gaps = 8,
---The proportion of the output taken up by the master window(s). ---The proportion of the output taken up by the master window(s).
--- ---
---This is a float that will be clamped between 0.1 and 0.9 ---This is a float that will be clamped between 0.1 and 0.9.
---similarly to River. ---@field master_factor number
--- ---The side the master window(s) will be on.
---@field master_side "left"|"right"|"top"|"bottom"
---How many windows the master side will have.
---@field master_count integer
local MasterStack = {
---Defaults to 8.
gaps = 8,
---Defaults to 0.5. ---Defaults to 0.5.
master_factor = 0.5, master_factor = 0.5,
---The side the master window(s) will be on. ---Defaults to "left".
---
---Defaults to `"left"`.
master_side = "left", master_side = "left",
---How many windows the master side will have.
---
---Defaults to 1. ---Defaults to 1.
master_count = 1, master_count = 1,
},
---@type Builtin.Dwindle
dwindle = {
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---
---Defaults to 8.
gaps = 8,
---Factors applied to each split.
---
---The first split will use the factor at [1],
---the second at [2], and so on.
---
---Defaults to 0.5 if there is no factor at [n].
split_factors = {},
},
---@type Builtin.Corner
corner = {
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---
---Defaults to 8.
gaps = 8,
---How much of the output the corner window's width will take up.
---
---Defaults to 0.5.
corner_width_factor = 0.5,
---How much of the output the corner window's height will take up.
---
---Defaults to 0.5.
corner_height_factor = 0.5,
---Which side the corner window will be in.
---
---Defaults to "top_left".
corner_loc = "top_left",
},
---@type Builtin.Spiral
spiral = {
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---
---Defaults to 8.
gaps = 8,
---Factors applied to each split.
---
---The first split will use the factor at [1],
---the second at [2], and so on.
---
---Defaults to 0.5 if there is no factor at [n].
split_factors = {},
},
---@type Builtin.Fair
fair = {
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---
---Defaults to 8.
gaps = 8,
---The direction of the window lines.
---
---Defaults to "vertical".
direction = "vertical",
},
} }
---@class Builtin.MasterStack.Args
---@field gaps? integer | { inner: integer, outer: integer }
---@field master_factor? number
---@field master_side? "left"|"right"|"top"|"bottom"
---@field master_count? integer
---@param args LayoutArgs ---@param args LayoutArgs
---
---@return { x: integer, y: integer, width: integer, height: integer }[] ---@return { x: integer, y: integer, width: integer, height: integer }[]
function builtins.master_stack:layout(args) function MasterStack:layout(args)
local win_count = #args.windows local win_count = #args.windows
if win_count == 0 then if win_count == 0 then
@ -355,10 +231,59 @@ function builtins.master_stack:layout(args)
return geos return geos
end end
---Create a master stack layout generator.
---
---Pass in `settings` to override the defaults.
---
---@param settings? Builtin.MasterStack.Args
---
---@return Builtin.MasterStack
function builtins.master_stack(settings)
local master_stack = settings or {}
setmetatable(master_stack, { __index = MasterStack })
---@cast master_stack Builtin.MasterStack
return master_stack
end
----------------------------------------
-- Dwindle --
----------------------------------------
---A `LayoutGenerator` that lays out windows in a shrinking fashion
---towards the bottom right corner.
---@class Builtin.Dwindle: LayoutGenerator
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---@field gaps integer | { inner: integer, outer: integer }
---The proportions that each split will split at.
---
---The first split will use the factor at [1],
---the second at [2], and so on.
---@field split_factors table<integer, number>
local Dwindle = {
---Defaults to 8.
gaps = 8,
---Defaults to 0.5 if there is no factor at [n].
split_factors = {},
}
---@class Builtin.Dwindle.Args
---@field gaps? integer | { inner: integer, outer: integer }
---@field split_factors? table<integer, number>
---@param args LayoutArgs ---@param args LayoutArgs
--- ---
---@return { x: integer, y: integer, width: integer, height: integer }[] ---@return { x: integer, y: integer, width: integer, height: integer }[]
function builtins.dwindle:layout(args) function Dwindle:layout(args)
local win_count = #args.windows local win_count = #args.windows
if win_count == 0 then if win_count == 0 then
@ -438,7 +363,66 @@ function builtins.dwindle:layout(args)
return geos return geos
end end
function builtins.corner:layout(args) ---Create a dwindle layout generator.
---
---Pass in `settings` to override the defaults.
---
---@param settings? Builtin.Dwindle.Args
---
---@return Builtin.Dwindle
function builtins.dwindle(settings)
local dwindle = settings or {}
setmetatable(dwindle, { __index = Dwindle })
---@cast dwindle Builtin.Dwindle
return dwindle
end
----------------------------------------
-- Corner --
----------------------------------------
---A `LayoutGenerator` that has one main corner window and a
---horizontal and vertical stack flanking it on the other two sides.
---@class Builtin.Corner: LayoutGenerator
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---@field gaps integer | { inner: integer, outer: integer }
---How much of the output the corner window's width will take up.
---@field corner_width_factor number
---How much of the output the corner window's height will take up.
---@field corner_height_factor number
---Which corner the corner window will be in.
---@field corner_loc "top_left"|"top_right"|"bottom_left"|"bottom_right"
local Corner = {
---Defaults to 8.
gaps = 8,
---Defaults to 0.5.
corner_width_factor = 0.5,
---Defaults to 0.5.
corner_height_factor = 0.5,
---Defaults to "top_left".
corner_loc = "top_left",
}
---@class Builtin.Corner.Args
---@field gaps? integer | { inner: integer, outer: integer }
---@field corner_width_factor? number
---@field corner_height_factor? number
---@field corner_loc? "top_left"|"top_right"|"bottom_left"|"bottom_right"
---@param args LayoutArgs
---
---@return { x: integer, y: integer, width: integer, height: integer }[]
function Corner:layout(args)
local win_count = #args.windows local win_count = #args.windows
if win_count == 0 then if win_count == 0 then
@ -568,9 +552,61 @@ function builtins.corner:layout(args)
return geos return geos
end end
-- Spiral is a copy-paste of dwindle with a minor change, yikes ---Create a corner layout generator.
---
---Pass in `settings` to override the defaults.
---
---@param settings? Builtin.Corner.Args
---
---@return Builtin.Corner
function builtins.corner(settings)
local corner = settings or {}
setmetatable(corner, { __index = Corner })
---@cast corner Builtin.Corner
return corner
end
function builtins.spiral:layout(args) ----------------------------------------
-- Spiral --
----------------------------------------
---A `LayoutGenerator` that lays out windows in a spiral.
---
---This is similar to the dwindle layout but in a spiral instead of
---towards the borrom right corner.
---@class Builtin.Spiral : LayoutGenerator
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---@field gaps integer | { inner: integer, outer: integer }
---The proportions that each split will split at.
---
---The first split will use the factor at [1],
---the second at [2], and so on.
---@field split_factors table<integer, number>
local Spiral = {
---Defaults to 8.
gaps = 8,
---Defaults to 0.5 if there is no factor at [n].
split_factors = {},
}
---@class Builtin.Spiral.Args
---@field gaps? integer | { inner: integer, outer: integer }
---@field split_factors? table<integer, number>
---@param args LayoutArgs
---
---@return { x: integer, y: integer, width: integer, height: integer }[]
function Spiral:layout(args)
local win_count = #args.windows local win_count = #args.windows
if win_count == 0 then if win_count == 0 then
@ -655,7 +691,56 @@ function builtins.spiral:layout(args)
return geos return geos
end end
function builtins.fair:layout(args) ---Create a spiral layout generator.
---
---Pass in `settings` to override the defaults.
---
---@param settings? Builtin.Spiral.Args
---
---@return Builtin.Spiral
function builtins.spiral(settings)
local spiral = settings or {}
setmetatable(spiral, { __index = Spiral })
---@cast spiral Builtin.Spiral
return spiral
end
----------------------------------------
-- Fair --
----------------------------------------
---A `LayoutGenerator` that attempts to layout windows such that
---they are the same size.
---@class Builtin.Fair : LayoutGenerator
---Gaps between windows, in pixels.
---
---This can be an integer or the table { inner: integer, outer: integer }.
---If it is an integer, all gaps will be that amount of pixels wide.
---If it is a table, `outer` denotes the amount of pixels around the
---edge of the output area that will become a gap, and
---`inner` denotes the amount of pixels around each window that
---will become a gap.
---
---This means that, for example, `inner = 2` will cause the gap
---width between windows to be 4; 2 around each window.
---@field gaps integer | { inner: integer, outer: integer }
---The direction of the window lines.
---@field direction "horizontal"|"vertical"
local Fair = {
---Defaults to 8.
gaps = 8,
---Defaults to "vertical".
direction = "vertical",
}
---@class Builtin.Fair.Args
---@field gaps? integer | { inner: integer, outer: integer }
---@field direction? "horizontal"|"vertical"
---@param args LayoutArgs
---
---@return { x: integer, y: integer, width: integer, height: integer }[]
function Fair:layout(args)
local win_count = #args.windows local win_count = #args.windows
if win_count == 0 then if win_count == 0 then
@ -794,6 +879,20 @@ function builtins.fair:layout(args)
return geos return geos
end end
---Create a fair layout generator.
---
---Pass in `settings` to override the defaults.
---
---@param settings? Builtin.Fair.Args
---
---@return Builtin.Fair
function builtins.fair(settings)
local fair = settings or {}
setmetatable(fair, { __index = Fair })
---@cast fair Builtin.Fair
return fair
end
---@class Layout ---@class Layout
---@field private stream H2Stream? ---@field private stream H2Stream?
local layout = { local layout = {
@ -804,6 +903,8 @@ local layout = {
--- ---
---It will manage layout requests from the compositor. ---It will manage layout requests from the compositor.
--- ---
---Only one layout manager can manage layouts at a time.
---
---@param manager LayoutManager ---@param manager LayoutManager
function layout.set_manager(manager) function layout.set_manager(manager)
layout.stream = client.bidirectional_streaming_request( layout.stream = client.bidirectional_streaming_request(