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

Attachment: pgpAnbXC3RixV.pgp
Description: PGP signature

Reply via email to