common: Refactor awful.widget.common to support external extensions

This commit allow user defined delegates to be used as list elements.
This put an end to the endless attempt to cram more features into this
code.

A widget template (non-instantiated) is passed to the arguments and
is created by the common code. It also supports "roles" where some
user defined widgets can replace the old textbox or imagebox.
This commit is contained in:
Emmanuel Lepage Vallee 2017-08-10 00:28:06 -04:00
parent 2e7cd2b2ef
commit f147f0d28a
1 changed files with 94 additions and 50 deletions

View File

@ -9,7 +9,9 @@ local type = type
local ipairs = ipairs local ipairs = ipairs
local capi = { button = button } local capi = { button = button }
local wibox = require("wibox") local wibox = require("wibox")
local gdebug = require("gears.debug")
local dpi = require("beautiful").xresources.apply_dpi local dpi = require("beautiful").xresources.apply_dpi
local base = require("wibox.widget.base")
--- Common utilities for awful widgets --- Common utilities for awful widgets
local common = {} local common = {}
@ -36,33 +38,13 @@ function common.create_buttons(buttons, object)
end end
end end
--- Common update method. local function default_template()
-- @param w The widget. local ib = wibox.widget.imagebox()
-- @tab buttons local tb = wibox.widget.textbox()
-- @func label Function to generate label parameters from an object. local bgb = wibox.container.background()
-- The function gets passed an object from `objects`, and local tbm = wibox.container.margin(tb, dpi(4), dpi(4))
-- has to return `text`, `bg`, `bg_image`, `icon`. local ibm = wibox.container.margin(ib, dpi(4))
-- @tab data Current data/cache, indexed by objects. local l = wibox.layout.fixed.horizontal()
-- @tab objects Objects to be displayed / updated.
function common.list_update(w, buttons, label, data, objects)
-- update the widgets, creating them if needed
w:reset()
for i, o in ipairs(objects) do
local cache = data[o]
local ib, tb, bgb, tbm, ibm, l
if cache then
ib = cache.ib
tb = cache.tb
bgb = cache.bgb
tbm = cache.tbm
ibm = cache.ibm
else
ib = wibox.widget.imagebox()
tb = wibox.widget.textbox()
bgb = wibox.container.background()
tbm = wibox.container.margin(tb, dpi(4), dpi(4))
ibm = wibox.container.margin(ib, dpi(4))
l = wibox.layout.fixed.horizontal()
-- All of this is added in a fixed widget -- All of this is added in a fixed widget
l:fill_space(true) l:fill_space(true)
@ -72,45 +54,107 @@ function common.list_update(w, buttons, label, data, objects)
-- And all of this gets a background -- And all of this gets a background
bgb:set_widget(l) bgb:set_widget(l)
bgb:buttons(common.create_buttons(buttons, o)) return {
data[o] = {
ib = ib, ib = ib,
tb = tb, tb = tb,
bgb = bgb, bgb = bgb,
tbm = tbm, tbm = tbm,
ibm = ibm, ibm = ibm,
primary = l,
} }
end
local function custom_template(args)
local l = base.make_widget_from_value(args.widget_template)
-- The template system requires being able to get children elements by ids.
-- This is not optimal, but for now there is no way around it.
assert(l.get_children_by_id,"The given widget template did not result in a"..
"layout with a 'get_children_by_id' method")
return {
ib = l:get_children_by_id( "icon_role" )[1],
tb = l:get_children_by_id( "text_role" )[1],
bgb = l:get_children_by_id( "background_role" )[1],
tbm = l:get_children_by_id( "text_margin_role" )[1],
ibm = l:get_children_by_id( "icon_margin_role" )[1],
primary = l,
update_callback = l.update_callback,
create_callback = l.create_callback,
}
end
--- Common update method.
-- @param w The widget.
-- @tab buttons
-- @func label Function to generate label parameters from an object.
-- The function gets passed an object from `objects`, and
-- has to return `text`, `bg`, `bg_image`, `icon`.
-- @tab data Current data/cache, indexed by objects.
-- @tab objects Objects to be displayed / updated.
-- @tparam[opt={}] table args
function common.list_update(w, buttons, label, data, objects, args)
-- update the widgets, creating them if needed
w:reset()
for i, o in ipairs(objects) do
local cache = data[o]
if not cache then
cache = (args and args.widget_template) and
custom_template(args) or default_template()
cache.primary:buttons(common.create_buttons(buttons, o))
if cache.create_callback then
cache.create_callback(cache.primary, o, i, objects)
end end
local text, bg, bg_image, icon, args = label(o, tb) data[o] = cache
args = args or {} elseif cache.update_callback then
cache.update_callback(cache.primary, o, i, objects)
end
local text, bg, bg_image, icon, item_args = label(o, cache.tb)
item_args = item_args or {}
-- The text might be invalid, so use pcall. -- The text might be invalid, so use pcall.
if text == nil or text == "" then if cache.tbm and (text == nil or text == "") then
tbm:set_margins(0) cache.tbm:set_margins(0)
else elseif cache.tb then
if not tb:set_markup_silently(text) then if not cache.tb:set_markup_silently(text) then
tb:set_markup("<i>&lt;Invalid text&gt;</i>") cache.tb:set_markup("<i>&lt;Invalid text&gt;</i>")
end end
end end
bgb:set_bg(bg)
if type(bg_image) == "function" then
-- TODO: Why does this pass nil as an argument?
bg_image = bg_image(tb,o,nil,objects,i)
end
bgb:set_bgimage(bg_image)
if icon then
ib:set_image(icon)
else
ibm:set_margins(0)
end
bgb.shape = args.shape if cache.bgb then
bgb.shape_border_width = args.shape_border_width cache.bgb:set_bg(bg)
bgb.shape_border_color = args.shape_border_color
w:add(bgb) --TODO v5 remove this if, it existed only for a removed and
-- undocumented API
if type(bg_image) ~= "function" then
cache.bgb:set_bgimage(bg_image)
else
gdebug.deprecate("If you read this, you used an undocumented API"..
" which has been replaced by the new awful.widget.common "..
"templating system, please migrate now. This feature is "..
"already staged for removal", {
deprecated_in = 4
})
end
cache.bgb.shape = item_args.shape
cache.bgb.shape_border_width = item_args.shape_border_width
cache.bgb.shape_border_color = item_args.shape_border_color
end
if cache.ib and icon then
cache.ib:set_image(icon)
elseif cache.ibm then
cache.ibm:set_margins(0)
end
w:add(cache.primary)
end end
end end