291 lines
13 KiB
Lua
291 lines
13 KiB
Lua
-------------------------------------------------
|
|
-- @author Gregor Best <farhaven@googlemail.com>, Lukas Hrazky <lukkash@email.cz>
|
|
-- @copyright 2009 Gregor Best, Lukas Hrazky
|
|
-- @release @AWESOME_VERSION@
|
|
-------------------------------------------------
|
|
|
|
local setmetatable = setmetatable
|
|
local require = require
|
|
local ipairs = ipairs
|
|
local type = type
|
|
local insert = table.insert
|
|
local min = math.min
|
|
local max = math.max
|
|
local floor = math.floor
|
|
local util = require("awful.util")
|
|
local clone = util.table.clone
|
|
|
|
local margins = awful.widget.layout.margins
|
|
local layout = awful.widget.layout
|
|
|
|
local linear_common = {}
|
|
|
|
-- Calculates geometries for fixed layouts.
|
|
-- This generic function is used for all layouts exept flex.
|
|
-- It is written for horizontal layouts, but by using a special index 'idx' to access
|
|
-- all the geometry attributes, it is used for vertical layouts too. In that case, 'idx'
|
|
-- returns 'y' for 'x', 'width' for 'height', etc.
|
|
-- @param idx An index table that defines whether horzintal or vertical arrangement will be
|
|
-- calculated. See regular_index and switched_index tables.
|
|
-- @param bounds The geometry of the bounds for the layout.
|
|
-- @param widgets The table of the widgets to layout, can be nested.
|
|
-- @param screen The screen of the wibox.
|
|
-- @return A table of geometries of all the widgets.
|
|
function linear_common.fixed(idx, bounds, widgets, screen)
|
|
-- set bounds width and height to what is preset in the widgets table (if there is something)
|
|
-- we don't need to use idx here since we're treating both directions the same way
|
|
if widgets.width and widgets.width < bounds.width then
|
|
bounds.width = widgets.width
|
|
end
|
|
if widgets.height and widgets.height < bounds.height then
|
|
bounds.height = widgets.height
|
|
end
|
|
|
|
-- 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)}
|
|
-- the height of the heighest widget, will be the height of the total space taken
|
|
local maxh = 0
|
|
|
|
for _, v in ipairs(widgets) do
|
|
if type(v) == "table" or type(v) == "widget" then
|
|
local m = margins[v]
|
|
-- we can shrink the bounds by the horizontal margins right now, they affect our free
|
|
-- space directly (vertical don't, they are different for every item in 'widgets')
|
|
bounds[idx.width] = bounds[idx.width] - m[idx.left] - m[idx.right]
|
|
bounds[idx.x] = bounds[idx.x] + m[idx.left]
|
|
|
|
if type(v) == "table" then
|
|
-- create new bounds for the table and shrink it by the vertical margins
|
|
local t_bounds = clone(bounds)
|
|
t_bounds[idx.height] = t_bounds[idx.height] - m[idx.top] - m[idx.bottom]
|
|
t_bounds[idx.y] = t_bounds[idx.y] + m[idx.top]
|
|
|
|
-- backup the width and height of the table so we can restore it
|
|
local t_width = v.width
|
|
local t_height = v.height
|
|
|
|
-- if the 'widgets' table has height set and the table itself doesn't, we set it
|
|
v[idx.height] = v[idx.height] or widgets[idx.height]
|
|
|
|
-- call the layout function recursively on this table
|
|
local layout = v.layout or layout.default
|
|
local g = layout(t_bounds, v, screen)
|
|
|
|
-- restore the table's original width and height
|
|
v.width = t_width
|
|
v.height = t_height
|
|
|
|
-- subtract the space taken by the table from our bounds - only if the taken space
|
|
-- is either on the left or on the right of our bounds (not in the middle)
|
|
if g.total[idx.x] == bounds[idx.x] or
|
|
g.total[idx.x] + g.total[idx.width] == bounds[idx.x] + bounds[idx.width] then
|
|
bounds[idx.width] = bounds[idx.width] - g.total[idx.width]
|
|
end
|
|
-- we only move the 'x' coord if the taken space is on the left side of our bounds
|
|
if g.total[idx.x] == bounds[idx.x] then
|
|
bounds[idx.x] = bounds[idx.x] + g.total[idx.width] + m[idx.right]
|
|
end
|
|
|
|
-- update the maximum height with this new table
|
|
maxh = max(maxh, g.total[idx.height] + m[idx.top] + m[idx.bottom])
|
|
|
|
-- insert all geometries from the table to our geometries
|
|
for _, w in ipairs(g) do
|
|
insert(geometries, w)
|
|
end
|
|
|
|
elseif type(v) == "widget" then
|
|
local g = {x = 0, y = 0, width = 0, height = 0}
|
|
|
|
if v.visible then
|
|
-- get the geometry of the widget
|
|
g = v:extents(screen)
|
|
|
|
-- resize to fit the height available if requested
|
|
if v.resize and g.width > 0 and g.height > 0 then
|
|
local ratio = g[idx.width] / g[idx.height]
|
|
g[idx.width] = floor(bounds[idx.height] * ratio)
|
|
g[idx.height] = bounds[idx.height]
|
|
end
|
|
|
|
-- set the coords, apply the top margin
|
|
g[idx.y] = bounds[idx.y] + m[idx.top]
|
|
g[idx.x] = bounds[idx.x]
|
|
|
|
-- limit the width of the widget to what's available
|
|
g[idx.width] = min(g[idx.width], bounds[idx.width])
|
|
|
|
-- if the 'widgets' table has height set, we set it to the widget
|
|
g[idx.height] = widgets[idx.height] and
|
|
(widgets[idx.height] - m[idx.top] - m[idx.bottom]) or g[idx.height]
|
|
|
|
-- limit the height of the widget to what's available
|
|
g[idx.height] = min(g[idx.height], bounds[idx.height] - m[idx.top] - m[idx.bottom])
|
|
|
|
-- subtract the space taken by the widget from our bounds
|
|
bounds[idx.width] = bounds[idx.width] - g[idx.width]
|
|
-- move bounds right by the widget's width
|
|
bounds[idx.x] = bounds[idx.x] + g[idx.width] + m[idx.right]
|
|
|
|
-- update the maximum height with height of this widget
|
|
maxh = max(maxh, g[idx.height] + m[idx.top] + m[idx.bottom])
|
|
end
|
|
|
|
insert(geometries, g)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- calculate the total space taken by the widgets
|
|
geometries.total[idx.width] = geometries.total[idx.width] - bounds[idx.width]
|
|
geometries.total[idx.height] = maxh
|
|
-- if the bounds are on the left of what was empty in the beginning of this function,
|
|
-- we move the total to the right. this, however, most probably happened cos of rightleft layout
|
|
-- inside 'widgets', and only if there was nothing aligned to the left
|
|
if geometries.total[idx.x] == bounds[idx.x] then
|
|
geometries.total[idx.x] = geometries.total[idx.x] + bounds[idx.width]
|
|
end
|
|
|
|
return geometries
|
|
end
|
|
|
|
|
|
-- Calculates geometries for flex layouts.
|
|
-- This generic function is used for all flex layouts.
|
|
-- It is written for horizontal layouts, but by using special index 'idx' to access
|
|
-- all the geometry attributes, it is used for vertical layouts too. In that case, 'idx'
|
|
-- returns 'y' for 'x', 'width' for 'height', etc.
|
|
-- @param idx An index table that defines whether horzintal or vertical arrangement will be
|
|
-- calculated. See regular_index and switched_index tables.
|
|
-- @param bounds The geometry of the bounds for the layout.
|
|
-- @param widgets The table of the widgets to layout, can be nested.
|
|
-- @param screen The screen of the wibox.
|
|
-- @return A table of geometries of all the widgets.
|
|
function linear_common.flex(idx, bounds, widgets, screen)
|
|
-- set bounds width and height to what is preset in the widgets table (if there is something)
|
|
-- we don't need to use idx here since we're treating both directions the same way
|
|
if widgets.width and widgets.width < bounds.width then
|
|
bounds.width = widgets.width
|
|
end
|
|
if widgets.height and widgets.height < bounds.height then
|
|
bounds.height = widgets.height
|
|
end
|
|
|
|
-- 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)}
|
|
-- the height of the heighest widget, will be the height of the total space taken
|
|
local maxh = 0
|
|
-- the number of widgets/tables in 'widgets' argument
|
|
local n = 0
|
|
-- get the gap or set to 0
|
|
local gap = widgets.gap or 0
|
|
|
|
-- count the widgets/tables
|
|
for _, v in ipairs(widgets) do
|
|
if type(v) == "table" or (type(v) == "widget" and v.visible) then
|
|
n = n + 1
|
|
end
|
|
end
|
|
|
|
-- calculate the width. these vars keep the floating numbers, while bounds keep the
|
|
-- rounded ones and are set from these on each iteration to ensure proper rounding
|
|
local width = (n > 0) and ((widgets[idx.width] or bounds[idx.width]) - gap * (n - 1)) / n or 0
|
|
local x = bounds[idx.x]
|
|
|
|
-- if max_size is set and it is lower than the calculated width, use it
|
|
width = (widgets.max_size and widgets.max_size < width) and widgets.max_size or width
|
|
|
|
for _, v in ipairs(widgets) do
|
|
-- someone give me freaking continue
|
|
if type(v) == "widget" and not v.visible then
|
|
insert(geometries, {x = 0, y = 0, width = 0, height = 0})
|
|
elseif type(v) == "widget" or type(v) == "table" then
|
|
-- do the floating magic, calculate real_width which will be set to the geometries
|
|
x = x + width
|
|
local real_width = floor(x - bounds[idx.x] + 0.5)
|
|
|
|
local m = margins[v]
|
|
|
|
if type(v) == "table" then
|
|
-- create new bounds for the table and shrink it by the margins
|
|
local t_bounds = {}
|
|
t_bounds[idx.x] = bounds[idx.x] + m[idx.left]
|
|
t_bounds[idx.y] = bounds[idx.y] + m[idx.top]
|
|
t_bounds[idx.width] = real_width - m[idx.left] - m[idx.right]
|
|
t_bounds[idx.height] = bounds[idx.height] - m[idx.top] - m[idx.bottom]
|
|
|
|
-- backup the width and height of the table so we can restore it
|
|
local t_width = v.width
|
|
local t_height = v.height
|
|
|
|
-- set the table's width so it can flex what's inside it
|
|
v[idx.width] = real_width
|
|
|
|
-- if the 'widgets' table has height set and the table itself doesn't, we set it
|
|
v[idx.height] = v[idx.height] or widgets[idx.height]
|
|
|
|
-- call the layout function recursively on this table
|
|
local layout = v.layout or layout.default
|
|
local g = layout(t_bounds, v, screen)
|
|
|
|
-- restore the table's original width and height
|
|
v.width = t_width
|
|
v.height = t_height
|
|
|
|
-- update the maximum height with this new table
|
|
maxh = max(maxh, g.total[idx.height] + m[idx.top] + m[idx.bottom])
|
|
|
|
for _, v in ipairs(g) do
|
|
insert(geometries, v)
|
|
end
|
|
elseif type(v) == "widget" then
|
|
local g = v:extents(screen)
|
|
|
|
-- resize to fit the width available if requested
|
|
if v.resize and g.width > 0 and g.height > 0 then
|
|
local ratio = g[idx.height] / g[idx.width]
|
|
g[idx.height] = real_width * ratio
|
|
end
|
|
|
|
-- set the widget geometry
|
|
g[idx.x] = bounds[idx.x] + m[idx.left]
|
|
g[idx.width] = real_width - m[idx.left] - m[idx.right]
|
|
g[idx.y] = bounds[idx.y] + m[idx.top]
|
|
|
|
-- if the 'widgets' table has height set, we set it to the widget
|
|
g[idx.height] = widgets[idx.height] and
|
|
(widgets[idx.height] - m[idx.top] - m[idx.bottom]) or g[idx.height]
|
|
|
|
-- limit the height of the widget to what's available
|
|
g[idx.height] = min(g[idx.height], bounds[idx.height] - m[idx.top] - m[idx.bottom])
|
|
|
|
-- update the maximum height with height of this widget
|
|
maxh = max(maxh, g[idx.height] + m[idx.top] + m[idx.bottom])
|
|
|
|
insert(geometries, g)
|
|
end
|
|
|
|
-- update the bounds (move it to the right by the widget's width)
|
|
bounds[idx.width] = bounds[idx.width] - real_width - gap
|
|
x = x + gap
|
|
bounds[idx.x] = floor(x + 0.5)
|
|
end
|
|
end
|
|
|
|
-- we have total already from the cloned bounds, just set the height to what we got
|
|
geometries.total[idx.width] = geometries.total[idx.width] - bounds[idx.width]
|
|
geometries.total[idx.height] = maxh
|
|
|
|
return geometries
|
|
end
|
|
|
|
return linear_common
|
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|