From 2820e5f2e86d65462716b70a80f8e471a1d857bd Mon Sep 17 00:00:00 2001 From: Gregor Best Date: Thu, 2 Jul 2009 02:10:32 +0200 Subject: [PATCH] awful.widget: add layouts Signed-off-by: Gregor Best Signed-off-by: Julien Danjou --- lib/awful/widget/init.lua.in | 1 + lib/awful/widget/layout/default.lua.in | 58 ++++++++ lib/awful/widget/layout/horizontal.lua.in | 158 ++++++++++++++++++++++ lib/awful/widget/layout/init.lua.in | 8 ++ lib/awful/widget/layout/vertical.lua.in | 101 ++++++++++++++ lib/awful/widget/prompt.lua.in | 2 + lib/awful/widget/taglist.lua.in | 5 +- lib/awful/widget/tasklist.lua.in | 10 +- 8 files changed, 338 insertions(+), 5 deletions(-) create mode 100644 lib/awful/widget/layout/default.lua.in create mode 100644 lib/awful/widget/layout/horizontal.lua.in create mode 100644 lib/awful/widget/layout/init.lua.in create mode 100644 lib/awful/widget/layout/vertical.lua.in diff --git a/lib/awful/widget/init.lua.in b/lib/awful/widget/init.lua.in index 6d4b51cf..db39ed55 100644 --- a/lib/awful/widget/init.lua.in +++ b/lib/awful/widget/init.lua.in @@ -12,6 +12,7 @@ require("awful.widget.prompt") require("awful.widget.progressbar") require("awful.widget.graph") require("awful.widget.layoutbox") +require("awful.widget.layout") --- Widget module for awful module("awful.widget") diff --git a/lib/awful/widget/layout/default.lua.in b/lib/awful/widget/layout/default.lua.in new file mode 100644 index 00000000..7c73d451 --- /dev/null +++ b/lib/awful/widget/layout/default.lua.in @@ -0,0 +1,58 @@ +------------------------------------------------- +-- @author Gregor Best +-- @copyright 2009 Gregor Best +-- @release @AWESOME_VERSION@ +------------------------------------------------- + +-- Grab environment +local ipairs = ipairs +local type = type +local table = table +local math = math +local setmetatable = setmetatable +local util = require("awful.util") + +--- Simple default layout, emulating the fallback C layout +module("awful.widget.layout.default") + +local function default(bounds, widgets, screen) + local geometries = { + free = { x = 0, y = 0, width = 0, height = bounds.height } + } + + local width = 0 + + 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 + local nbounds = util.table.clone(bounds) + local g = layout(nbounds, v, screen) + for _, w in ipairs(g) do + table.insert(geometries, w) + end + else + if v.visible then + local e = v:extents(screen) + e.x = 0 + e.y = 0 + e.width = math.min(e.width, bounds.width) + e.height = bounds.height + width = math.max(e.width, width) + + table.insert(geometries, e) + else + table.insert(geometries, { x = 0, y = 0, width = 0, height = 0 }) + end + end + end + + geometries.free.width = bounds.width - width + geometries.free.x = width + + return geometries +end + +setmetatable(_M, { __call = function(_, ...) return default(...) end }) diff --git a/lib/awful/widget/layout/horizontal.lua.in b/lib/awful/widget/layout/horizontal.lua.in new file mode 100644 index 00000000..6f6659cb --- /dev/null +++ b/lib/awful/widget/layout/horizontal.lua.in @@ -0,0 +1,158 @@ +------------------------------------------------- +-- @author Gregor Best +-- @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") + +--- 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 + 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 + x = x + g.free.x + 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 then + g.ratio = g.width / g.height + end + if g.width > bounds.width then + g.width = bounds.width + end + g.height = bounds.height + g.y = 0 + + if v.resize and g.width > 0 then + g.width = math.floor(g.height * g.ratio) + end + + if direction == "leftright" then + g.x = x + x = x + g.width + else + g.x = x + bounds.width - g.width + 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 new file mode 100644 index 00000000..087e5cb4 --- /dev/null +++ b/lib/awful/widget/layout/init.lua.in @@ -0,0 +1,8 @@ +require("awful.widget.layout.horizontal") +require("awful.widget.layout.vertical") +require("awful.widget.layout.default") + +-- Widget layouts +module("awful.widget.layout") + +-- 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 new file mode 100644 index 00000000..5a176848 --- /dev/null +++ b/lib/awful/widget/layout/vertical.lua.in @@ -0,0 +1,101 @@ +------------------------------------------------- +-- @author Gregor Best +-- @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 diff --git a/lib/awful/widget/prompt.lua.in b/lib/awful/widget/prompt.lua.in index a071f834..b3dfe031 100644 --- a/lib/awful/widget/prompt.lua.in +++ b/lib/awful/widget/prompt.lua.in @@ -10,6 +10,7 @@ local capi = { widget = widget } local completion = require("awful.completion") local util = require("awful.util") local prompt = require("awful.prompt") +local layout = require("awful.widget.layout") module("awful.widget.prompt") @@ -34,6 +35,7 @@ function new(args) promptbox.widget = capi.widget(args) promptbox.run = run promptbox.prompt = args.prompt or "Run: " + promptbox.layout = args.layout or layout.horizontal.leftright return promptbox end diff --git a/lib/awful/widget/taglist.lua.in b/lib/awful/widget/taglist.lua.in index 00de38c4..f8192d78 100644 --- a/lib/awful/widget/taglist.lua.in +++ b/lib/awful/widget/taglist.lua.in @@ -19,6 +19,7 @@ local common = require("awful.widget.common") local util = require("awful.util") local tag = require("awful.tag") local beautiful = require("beautiful") +local layout = require("awful.widget.layout") --- Taglist widget module for awful module("awful.widget.taglist") @@ -48,7 +49,9 @@ end -- @param label Label function to use. -- @param buttons A table with buttons binding to set. function new(screen, label, buttons) - local w = {} + local w = { + layout = layout.horizontal.leftright + } local widgets = { } widgets.imagebox = { } widgets.textbox = { ["margin"] = { ["left"] = 0, diff --git a/lib/awful/widget/tasklist.lua.in b/lib/awful/widget/tasklist.lua.in index 0d0897c7..cf5b2019 100644 --- a/lib/awful/widget/tasklist.lua.in +++ b/lib/awful/widget/tasklist.lua.in @@ -17,6 +17,7 @@ local common = require("awful.widget.common") local beautiful = require("beautiful") local client = require("awful.client") local util = require("awful.util") +local layout = require("awful.widget.layout") --- Tasklist widget module for awful module("awful.widget.tasklist") @@ -42,11 +43,12 @@ end -- @param label Label function to use. -- @param buttons A table with buttons binding to set. function new(label, buttons) - local w = {} + local w = { + layout = layout.horizontal.flex + } local widgets = { } - widgets.imagebox = { align = "flex" } - widgets.textbox = { align = "flex", - margin = { left = 2, + widgets.imagebox = { } + widgets.textbox = { margin = { left = 2, right = 2 }, bg_resize = true, bg_align = "right"