201 lines
7.3 KiB
Lua
201 lines
7.3 KiB
Lua
-------------------------------------------------
|
|
-- @author Lukas Hrazky <lukkash@email.cz>
|
|
-- @copyright 2009 Gregor Best, Lukas Hrazky
|
|
-- @release @AWESOME_VERSION@
|
|
-------------------------------------------------
|
|
|
|
local setmetatable = setmetatable
|
|
local require = require
|
|
local ipairs = ipairs
|
|
local pairs = pairs
|
|
local type = type
|
|
local insert = table.insert
|
|
local min = math.min
|
|
local max = math.max
|
|
local util = require("awful.util")
|
|
local clone = util.table.clone
|
|
|
|
local margins = awful.widget.layout.margins
|
|
local layout = awful.widget.layout
|
|
|
|
local M = {}
|
|
|
|
|
|
-- Creates an iterator over the cell sizes from the direction string.
|
|
-- It takes the bounds for the grid, the row/column sizes and a direction and returns an iterator
|
|
-- over the slices of the bounds whose sizes are determined by 'widths' or 'heights'. The 'direction'
|
|
-- determines which of these will be used and whether it will be in reverse or not.
|
|
-- @param direction The direction in which to iterate: 'leftright', 'rightleft', 'topdown' or 'bottomup'
|
|
-- @param bounds The bounds for the iterator, will be sliced according to direction
|
|
-- @param widths The widths of the columns in the grid
|
|
-- @param heights The heights of the rows in the grid
|
|
-- @return An iterator over the slices of the bounds
|
|
local function direction_iter(direction, bounds, widths, heights)
|
|
local iter
|
|
local i = 0
|
|
local idx, sizes
|
|
|
|
-- preset the closure upvalues according to the direction
|
|
if direction == "leftright" or direction == "rightleft" then
|
|
idx = layout.regular_index
|
|
sizes = widths
|
|
elseif direction == "topdown" or direction == "bottomup" then
|
|
idx = layout.switched_index
|
|
sizes = heights
|
|
end
|
|
|
|
if direction == "leftright" or direction == "topdown" then
|
|
-- the regular direction iterator
|
|
iter = function(bounds)
|
|
i = i + 1
|
|
if not sizes[i] then return end
|
|
|
|
local b = clone(bounds)
|
|
local width = min(sizes[i], b[idx.width])
|
|
b[idx.width] = width
|
|
bounds[idx.x] = bounds[idx.x] + width + sizes.gap
|
|
bounds[idx.width] = bounds[idx.width] - width
|
|
return b
|
|
end
|
|
elseif direction == "rightleft" or direction == "bottomup" then
|
|
-- the reverse direction iterator
|
|
iter = function(bounds)
|
|
i = i + 1
|
|
if not sizes[i] then return end
|
|
|
|
local b = clone(bounds)
|
|
local width = min(sizes[i], b[idx.width])
|
|
b[idx.x] = b[idx.x] + b[idx.width] - width + sizes.gap
|
|
b[idx.width] = width
|
|
bounds[idx.width] = bounds[idx.width] - width
|
|
return b
|
|
end
|
|
end
|
|
|
|
return iter, bounds
|
|
end
|
|
|
|
-- Places the widgets in a grid.
|
|
-- @see awful.widget.layout for a luadoc
|
|
function M.grid(bounds, widgets, screen)
|
|
local widths = {}
|
|
local heights = {}
|
|
|
|
-- we either have a table with the widths of the cells, or its a number and there is a col_count
|
|
if type(widgets.cell_width) == "table" then
|
|
widths = widgets.cell_width
|
|
else
|
|
for i = 1, widgets.col_count do widths[i] = widgets.cell_width end
|
|
end
|
|
|
|
-- we either have a table with the heights of the cells, or its a number and there is a row_count
|
|
if type(widgets.cell_height) == "table" then
|
|
heights = widgets.cell_height
|
|
else
|
|
for i = 1, widgets.row_count do heights[i] = widgets.cell_height end
|
|
end
|
|
|
|
widths.gap = widgets.col_gap or 0
|
|
heights.gap = widgets.row_gap or 0
|
|
|
|
-- calculate total space required for the grid
|
|
local w = - widths.gap
|
|
local h = - heights.gap
|
|
for _, v in ipairs(widths) do w = w + v + widths.gap end
|
|
for _, v in ipairs(heights) do h = h + v + heights.gap end
|
|
bounds.width = min(bounds.width, w)
|
|
bounds.height = min(bounds.height, h)
|
|
|
|
-- the table for the geometries which will be returned
|
|
-- we clone the bounds to the 'total' attribute. bounds are used to keep the free space
|
|
-- throughout this function. at the end, 'total' is modified to represent the space taken
|
|
-- by all widgets
|
|
local geometries = {total = clone(bounds)}
|
|
|
|
-- i counts the widgets placed in the grid
|
|
local i = 1
|
|
|
|
-- the iterators return the bounds for the cells of the table. first one in secondary direction
|
|
-- returns rows or columns, second one returns cell bounds in that row/column
|
|
for sb in direction_iter(widgets.secondary_dir or "topdown", bounds, widths, heights) do
|
|
for b in direction_iter(widgets.primary_dir or "leftright", sb, widths, heights) do
|
|
-- get the next widget, if there is none, we are done, some cells won't be filled
|
|
local w = widgets[i]
|
|
if not w then break end
|
|
|
|
if type(w) == "table" or type(w) == "widget" then
|
|
local m = margins[w]
|
|
-- shrink the cell bounds by the margins
|
|
b.width = b.width - m.left - m.right
|
|
b.height = b.height - m.top - m.bottom
|
|
b.x = b.x + m.left
|
|
b.y = b.y + m.top
|
|
|
|
if type(w) == "table" then
|
|
-- backup the width and height of the table so we can restore it
|
|
local t_width = w.width
|
|
local t_height = w.height
|
|
|
|
-- if the 'widgets' table has height set and the table itself doesn't, we set it
|
|
if widgets.resize then
|
|
w.width = b.width
|
|
w.height = b.height
|
|
end
|
|
|
|
-- call the layout function recursively on this table
|
|
local layout = w.layout or layout.default
|
|
local g = layout(b, w, screen)
|
|
|
|
-- restore the table's original width and height
|
|
w.width = t_width
|
|
w.height = t_height
|
|
|
|
-- insert all geometries from the table to our geometries
|
|
for _, w in ipairs(g) do
|
|
insert(geometries, w)
|
|
end
|
|
|
|
elseif type(widgets[i]) == "widget" then
|
|
local g = {x = 0, y = 0, width = 0, height = 0}
|
|
|
|
if widgets[i].visible then
|
|
-- get the geometry of the widget
|
|
g = widgets[i]:extents(screen)
|
|
|
|
-- set the coords
|
|
g.x = b.x
|
|
g.y = b.y
|
|
|
|
-- if we are resizing or it doesn't fit inside the bounds, set width/height
|
|
if widgets.resize or g.width > b.width then
|
|
g.width = b.width
|
|
end
|
|
if widgets.resize or g.height > b.height then
|
|
g.height = b.height
|
|
end
|
|
end
|
|
|
|
insert(geometries, g)
|
|
end
|
|
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
-- set zero geometries for any leftover widgets
|
|
-- Hack: if it has been registered as a widget in a wibox,
|
|
-- it's w.len since __len meta does not work on table until Lua 5.2.
|
|
-- Otherwise it's standard #w.
|
|
local len = (widgets.len or #widgets)
|
|
for j = i, len do
|
|
insert(geometries, {x = 0, y = 0, width = 0, height = 0})
|
|
end
|
|
|
|
return geometries
|
|
end
|
|
|
|
return M
|
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|