Hi people, as promised in an earlier thread, the attached patch contains a "few" changes to the widget layouts. It merges the code common to vertical and horizontal layouts to reduce code duplication and implements a first version of the topdown layout, which needs more testing and a few bugfixes.
This patch removes the vertical.flex layout, as I want to wait until the
topdown/bottomup layouts are done before merging the flex layouts common
code and adding horizontal.flex and vertical.flex.
Please note that I'm atm under a bit of stress as real life keeps
interfering with my hacking work (i.e. I have a job to find and stuff to
do for university), so I'd be more than glad if anyone else could keep a
bit of the work associated with this of my shoulders.
--
GCS/IT/M d- s+:- a-- C++ UL+++ US UB++ P+++ L+++ E--- W+ N+ o--
K- w--- ?O M-- ?V PS++ PE- Y++ PGP+++ t+ 5 X+ R tv b+++ DI+++
D+++ G+ e h! r y+
Gregor Best
From 1d1acf20c56f137b734abafd5eb03079af418726 Mon Sep 17 00:00:00 2001 From: Gregor Best <[email protected]> Date: Tue, 8 Sep 2009 13:45:08 +0200 Subject: [PATCH] awful.widget.layout: add vertical topdown widget and reduce code duplication This commit merges the code common to horizontal.{leftright|rightleft} and vertical.{topdown|bottomup} and adds calls to horizontal.{leftright|rightleft} and vertical.topdown. vertical.bottomup and vertical.flex are missing at the moment because I did not yet have the time to merge the flex layouts and the topdown layout needs more testing and a few fixes. Signed-off-by: Gregor Best <[email protected]> --- lib/awful/widget/layout/horizontal.lua.in | 188 --------------------- lib/awful/widget/layout/init.lua.in | 252 ++++++++++++++++++++++++++++- lib/awful/widget/layout/vertical.lua.in | 101 ------------ 3 files changed, 249 insertions(+), 292 deletions(-) delete mode 100644 lib/awful/widget/layout/horizontal.lua.in delete mode 100644 lib/awful/widget/layout/vertical.lua.in diff --git a/lib/awful/widget/layout/horizontal.lua.in b/lib/awful/widget/layout/horizontal.lua.in deleted file mode 100644 index 0914fab..0000000 --- a/lib/awful/widget/layout/horizontal.lua.in +++ /dev/null @@ -1,188 +0,0 @@ -------------------------------------------------- --- @author Gregor Best <[email protected]> --- @copyright 2009 Gregor Best --- @release @AWESOME_VERSION@ -------------------------------------------------- - --- Grab environment -local ipairs = ipairs -local type = type -local table = table -local math = math -local util = require("awful.util") -local default = require("awful.widget.layout.default") -local margins = awful.widget.layout.margins - ---- Horizontal widget layout -module("awful.widget.layout.horizontal") - -local function horizontal(direction, bounds, widgets, screen) - local geometries = { } - local x = 0 - - -- we are only interested in tables and widgets - local keys = util.table.keys_filter(widgets, "table", "widget") - - for _, k in ipairs(keys) do - local v = widgets[k] - if type(v) == "table" then - local layout = v.layout or default - if margins[v] then - bounds.width = bounds.width - (margins[v].left or 0) - (margins[v].right or 0) - bounds.height = bounds.height - (margins[v].top or 0) - (margins[v].bottom or 0) - end - local g = layout(bounds, v, screen) - if margins[v] then - x = x + (margins[v].left or 0) - end - for _, v in ipairs(g) do - v.x = v.x + x - v.y = v.y + (margins[v] and (margins[v].top and margins[v].top or 0) or 0) - table.insert(geometries, v) - end - bounds = g.free - if margins[v] then - x = x + g.free.x + (margins[v].right or 0) - bounds.width = bounds.width - (margins[v].right or 0) - (margins[v].left or 0) - else - x = x + g.free.x - end - elseif type(v) == "widget" then - local g - if v.visible then - g = v:extents(screen) - if margins[v] then - g.width = g.width + (margins[v].left or 0) + (margins[v].right or 0) - g.height = g.height + (margins[v].top or 0) + (margins[v].bottom or 0) - end - else - g = { - width = 0, - height = 0, - } - end - - if v.resize and g.width > 0 and g.height > 0 then - local ratio = g.width / g.height - g.width = math.floor(bounds.height * ratio) - g.height = bounds.height - end - - if g.width > bounds.width then - g.width = bounds.width - end - g.height = bounds.height - - if margins[v] then - g.y = (margins[v].top or 0) - else - g.y = 0 - end - - if direction == "leftright" then - if margins[v] then - g.x = x + (margins[v].left or 0) - else - g.x = x - end - x = x + g.width - else - if margins[v] then - g.x = x + bounds.width - g.width + (margins[v].left or 0) - else - g.x = x + bounds.width - g.width - end - end - bounds.width = bounds.width - g.width - - table.insert(geometries, g) - end - end - - geometries.free = util.table.clone(bounds) - geometries.free.x = x - geometries.free.y = 0 - - return geometries -end - -function flex(bounds, widgets, screen) - local geometries = { - free = util.table.clone(bounds) - } - -- the flex layout always uses the complete available place, thus we return - -- no usable free area - geometries.free.width = 0 - - -- we are only interested in tables and widgets - local keys = util.table.keys_filter(widgets, "table", "widget") - local nelements = 0 - - for _, k in ipairs(keys) do - local v = widgets[k] - if type(v) == "table" then - nelements = nelements + 1 - elseif type(v) == "widget" then - local g = v:extents() - if v.resize and g.width > 0 and g.height > 0 then - bounds.width = bounds.width - bounds.height - elseif g.width > 0 and g.height > 0 then - nelements = nelements + 1 - end - end - end - - nelements = (nelements == 0) and 1 or nelements - - local x = 0 - local width = bounds.width / nelements - - for _, k in ipairs(util.table.keys(widgets)) do - local v = widgets[k] - if type(v) == "table" then - local layout = v.layout or default - local g = layout(bounds, v, screen) - for _, v in ipairs(g) do - v.x = v.x + x - table.insert(geometries, v) - end - bounds = g.free - elseif type(v) == "widget" then - local g = v:extents(screen) - g.resize = v.resize - - if v.resize and g.width > 0 and g.height > 0 then - g.width = bounds.height - g.height = bounds.height - g.x = x - g.y = bounds.y - x = x + g.width - elseif g.width > 0 and g.height > 0 then - g.x = x - g.y = bounds.y - g.width = math.floor(width + 0.5) - g.height = bounds.height - x = x + width - else - g.x = 0 - g.y = 0 - g.width = 0 - g.height = 0 - end - - table.insert(geometries, g) - end - end - - return geometries -end - -function leftright(...) - return horizontal("leftright", ...) -end - -function rightleft(...) - return horizontal("rightleft", ...) -end - --- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/lib/awful/widget/layout/init.lua.in b/lib/awful/widget/layout/init.lua.in index f4535ee..3e38fef 100644 --- a/lib/awful/widget/layout/init.lua.in +++ b/lib/awful/widget/layout/init.lua.in @@ -1,5 +1,11 @@ local setmetatable = setmetatable local require = require +local ipairs = ipairs +local type = type +local table = table +local math = math +local util = require("awful.util") +local default = require("awful.widget.layout.default") -- Widget layouts module("awful.widget.layout") @@ -16,8 +22,248 @@ module("awful.widget.layout") -- @class table margins = setmetatable({}, { __mode = 'k' }) -require("awful.widget.layout.horizontal") -require("awful.widget.layout.vertical") -require("awful.widget.layout.default") +horizontal = { } +vertical = { } +local function linear(direction, bounds, widgets, screen) + local geometries = { } + if direction == "topdown" or direction == "bottomup" then + geometries.free = util.table.clone(bounds) + end + local x = 0 + local y = 0 + local maxw = 0 + + -- we are only interested in tables and widgets + local keys = util.table.keys_filter(widgets, "table", "widget") + + for _, k in ipairs(keys) do + local v = widgets[k] + if type(v) == "table" then + local layout = v.layout or default + if margins[v] then + bounds.width = bounds.width - (margins[v].left or 0) - (margins[v].right or 0) + bounds.height = bounds.height - (margins[v].top or 0) - (margins[v].bottom or 0) + end + local g = layout(bounds, v, screen) + if margins[v] then + if direction == "leftright" or direction == "rightleft" then + x = x + (margins[v].left or 0) + else + y = y + (margins[v].top or 0) + end + end + for _, v in ipairs(g) do + if direction == "leftright" or direction == "rightleft" then + v.x = v.x + x + v.y = v.y + (margins[v] and (margins[v].top and margins[v].top or 0) or 0) + else + v.x = v.x + (margins[v] and (margins[v].left and margins[v].left or 0) or 0) + v.y = v.y + y + end + maxw = math.max(maxw, v.x + v.width) + table.insert(geometries, v) + end + bounds = g.free + if margins[v] then + if direction == "leftright" or direction == "rightleft" then + x = x + g.free.x + (margins[v].right or 0) + bounds.width = bounds.width - (margins[v].right or 0) - (margins[v].left or 0) + else + y = y + g.free.y + (margins[v].bottom or 0) + bounds.height = bounds.height - (margins[v].top or 0) - (margins[v].bottom or 0) + end + else + if direction == "leftright" or direction == "rightleft" then + x = x + g.free.x + else + y = y + g.free.y + end + end + elseif type(v) == "widget" then + local g + if v.visible then + g = v:extents(screen) + if margins[v] then + g.width = g.width + (margins[v].left or 0) + (margins[v].right or 0) + g.height = g.height + (margins[v].top or 0) + (margins[v].bottom or 0) + end + else + g = { + width = 0, + height = 0, + } + end + + if v.resize and g.width > 0 and g.height > 0 then + if direction == "leftright" or direction == "rightleft" then + local ratio = g.width / g.height + g.width = math.floor(bounds.height * ratio) + g.height = bounds.height + else + local ratio = g.height / g.width + g.height = math.floor(bounds.width * ratio) + g.width = bounds.width + end + end + + if direction == "leftright" or direction == "rightleft" then + g.width = math.min(g.width, bounds.width) + -- g.height = bounds.height + else + g.height = math.min(g.height, bounds.height) + end + + if direction == "leftright" or direction == "rightleft" then + if margins[v] then + g.y = (margins[v].top or 0) + else + g.y = 0 + end + else + if margins[v] then + g.x = (margins[v].left or 0) + else + g.x = 0 + end + end + + if direction == "leftright" then + if margins[v] then + g.x = x + (margins[v].left or 0) + else + g.x = x + end + x = x + g.width + elseif direction == "rightleft" then + if margins[v] then + g.x = x + bounds.width - g.width + (margins[v].left or 0) + else + g.x = x + bounds.width - g.width + end + elseif direction == "topdown" then + if margins[v] then + g.y = y + (margins[v].top or 0) + else + g.y = y + end + y = y + g.height + end + + if direction == "leftright" or direction == "rightleft" then + bounds.width = bounds.width - g.width + else + bounds.height = bounds.height - g.height + end + + if direction == "topdown" or direction == "bottomup" then + maxw = math.max(maxw, g.x + g.width) + end + + table.insert(geometries, g) + end + end + + if direction == "leftright" or direction == "rightleft" then + geometries.free = util.table.clone(bounds) + geometries.free.x = x + else + geometries.free.x = maxw + geometries.free.width = geometries.free.width - maxw + end + geometries.free.y = y + + return geometries +end + +function horizontal.leftright(...) + return linear("leftright", ...) +end + +function horizontal.rightleft(...) + return linear("rightleft", ...) +end + +function vertical.topdown(...) + return linear("topdown", ...) +end + +function vertical.center(...) + local g = vertical.topdown(...) + for k, v in ipairs(g) do + v.y = v.y + (g.free.height / (#g + 1)) - (v.height / (#g + 1)) + end + return g +end + +function horizontal.flex(bounds, widgets, screen) + local geometries = { + free = util.table.clone(bounds) + } + -- the flex layout always uses the complete available place, thus we return + -- no usable free area + geometries.free.width = 0 + + -- we are only interested in tables and widgets + local keys = util.table.keys_filter(widgets, "table", "widget") + local nelements = 0 + + for _, k in ipairs(keys) do + local v = widgets[k] + if type(v) == "table" then + nelements = nelements + 1 + elseif type(v) == "widget" then + local g = v:extents() + if v.resize and g.width > 0 and g.height > 0 then + bounds.width = bounds.width - bounds.height + elseif g.width > 0 and g.height > 0 then + nelements = nelements + 1 + end + end + end + + nelements = (nelements == 0) and 1 or nelements + + local x = 0 + local width = bounds.width / nelements + + for _, k in ipairs(util.table.keys(widgets)) do + local v = widgets[k] + if type(v) == "table" then + local layout = v.layout or default + local g = layout(bounds, v, screen) + for _, v in ipairs(g) do + v.x = v.x + x + table.insert(geometries, v) + end + bounds = g.free + elseif type(v) == "widget" then + local g = v:extents(screen) + g.resize = v.resize + + if v.resize and g.width > 0 and g.height > 0 then + g.width = bounds.height + g.height = bounds.height + g.x = x + g.y = bounds.y + x = x + g.width + elseif g.width > 0 and g.height > 0 then + g.x = x + g.y = bounds.y + g.width = math.floor(width + 0.5) + g.height = bounds.height + x = x + width + else + g.x = 0 + g.y = 0 + g.width = 0 + g.height = 0 + end + + table.insert(geometries, g) + end + end + + return geometries +end -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/lib/awful/widget/layout/vertical.lua.in b/lib/awful/widget/layout/vertical.lua.in deleted file mode 100644 index 5a17684..0000000 --- a/lib/awful/widget/layout/vertical.lua.in +++ /dev/null @@ -1,101 +0,0 @@ -------------------------------------------------- --- @author Gregor Best <[email protected]> --- @copyright 2009 Gregor Best --- @release @AWESOME_VERSION@ -------------------------------------------------- - --- Grab environment -local ipairs = ipairs -local type = type -local table = table -local math = math -local util = require("awful.util") -local default = require("awful.widget.layout.default") - ---- Vertical widget layout -module("awful.widget.layout.vertical") - -function flex(bounds, widgets, screen) - local geometries = { - free = util.table.clone(bounds) - } - - local y = 0 - - -- we are only interested in tables and widgets - local keys = util.table.keys_filter(widgets, "table", "widget") - local nelements = 0 - for _, k in ipairs(keys) do - local v = widgets[k] - if type(v) == "table" then - nelements = nelements + 1 - else - local e = v:extents() - if v.visible and e.width > 0 and e.height > 0 then - nelements = nelements + 1 - end - end - end - if nelements == 0 then return geometries end - local height = math.floor(bounds.height / nelements) - - for _, k in ipairs(keys) do - local v = widgets[k] - if type(v) == "table" then - local layout = v.layout or default - -- we need to modify the height a bit because vertical layouts always span the - -- whole height - nbounds = util.table.clone(bounds) - nbounds.height = height - local g = layout(nbounds, v, screen) - for _, w in ipairs(g) do - w.y = w.y + y - table.insert(geometries, w) - end - y = y + height - elseif type(v) == "widget" then - local g - if v.visible then - g = v:extents(screen) - else - g = { - ["width"] = 0, - ["height"] = 0 - } - end - - g.ratio = 1 - if g.height > 0 and g.width > 0 then - g.ratio = g.width / g.height - end - g.height = height - if v.resize then - g.width = g.height * g.ratio - end - g.width = math.min(g.width, bounds.width) - geometries.free.x = math.max(geometries.free.x, g.width) - - g.x = 0 - g.y = y - y = y + g.height - bounds.height = bounds.height - g.height - - table.insert(geometries, g) - end - end - - local maxw = 0 - local maxx = 0 - for _, v in ipairs(geometries) do - if v.width > maxw then maxw = v.width end - if v.x > maxx then maxx = v.x end - end - - geometries.free.width = geometries.free.width - maxw - geometries.free.x = geometries.free.x + maxw - - geometries.free.height = nelements * height - geometries.free.y = 0 - - return geometries -end -- 1.6.4.2
pgpAnbXC3RixV.pgp
Description: PGP signature
