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:
parent
2e7cd2b2ef
commit
f147f0d28a
|
@ -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><Invalid text></i>")
|
cache.tb:set_markup("<i><Invalid text></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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue