214 lines
7.4 KiB
Lua
214 lines
7.4 KiB
Lua
---------------------------------------------------------------------------
|
|
-- This module contains helper functions to manage a layout widgets.
|
|
--
|
|
-- This is the boilerplate code to manage a "list" of objects and display
|
|
-- them in a `wibox.layout`. It uses signals to detect when an object change
|
|
-- and its widget be updated.
|
|
--
|
|
-- @author Julien Danjou <julien@danjou.info>
|
|
-- @copyright 2008-2009 Julien Danjou
|
|
-- @classmod awful.widget.common
|
|
---------------------------------------------------------------------------
|
|
|
|
-- Grab environment we need
|
|
local type = type
|
|
local ipairs = ipairs
|
|
local capi = { button = button }
|
|
local wibox = require("wibox")
|
|
local gdebug = require("gears.debug")
|
|
local dpi = require("beautiful").xresources.apply_dpi
|
|
local base = require("wibox.widget.base")
|
|
|
|
--- Common utilities for awful widgets
|
|
local common = {}
|
|
|
|
--- Common method to create buttons.
|
|
-- @tparam table buttons
|
|
-- @param object
|
|
-- @treturn table
|
|
function common.create_buttons(buttons, object)
|
|
local is_formatted = buttons and buttons[1] and (
|
|
type(buttons[1]) == "button" or buttons[1]._is_capi_button) or false
|
|
|
|
if buttons then
|
|
local btns = {}
|
|
for _, src in ipairs(buttons) do
|
|
--TODO v6 Remove this legacy overhead
|
|
for _, b in ipairs(is_formatted and {src} or src) do
|
|
-- Create a proxy button object: it will receive the real
|
|
-- press and release events, and will propagate them to the
|
|
-- button object the user provided, but with the object as
|
|
-- argument.
|
|
local btn = capi.button { modifiers = b.modifiers, button = b.button }
|
|
btn:connect_signal("press", function () b:emit_signal("press", object) end)
|
|
btn:connect_signal("release", function () b:emit_signal("release", object) end)
|
|
btns[#btns + 1] = btn
|
|
end
|
|
end
|
|
|
|
return btns
|
|
end
|
|
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
|
|
|
|
local function default_template()
|
|
return custom_template {
|
|
widget_template = {
|
|
id = 'background_role',
|
|
border_strategy = 'inner',
|
|
widget = wibox.container.background,
|
|
{
|
|
widget = wibox.layout.fixed.horizontal,
|
|
fill_space = true,
|
|
{
|
|
id = 'icon_margin_role',
|
|
widget = wibox.container.margin,
|
|
{
|
|
id = 'icon_role',
|
|
widget = wibox.widget.imagebox,
|
|
left = dpi(4),
|
|
},
|
|
},
|
|
{
|
|
id = 'text_margin_role',
|
|
widget = wibox.container.margin,
|
|
left = dpi(4),
|
|
right = dpi(4),
|
|
{
|
|
id = 'text_role',
|
|
widget = wibox.widget.textbox,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
-- Find all the childrens (without the hierarchy) and set a property.
|
|
function common._set_common_property(widget, property, value)
|
|
if widget["set_"..property] then
|
|
widget["set_"..property](widget, value)
|
|
end
|
|
|
|
if widget.get_children then
|
|
for _, w in ipairs(widget:get_children()) do
|
|
common._set_common_property(w, property, value)
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Common update method.
|
|
-- @param w The widget.
|
|
-- @tparam table 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`.
|
|
-- @tparam table data Current data/cache, indexed by objects.
|
|
-- @tparam table 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]
|
|
|
|
-- Allow the buttons to be replaced.
|
|
if cache and cache._buttons ~= buttons then
|
|
cache = nil
|
|
end
|
|
|
|
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
|
|
|
|
if args and args.create_callback then
|
|
args.create_callback(cache.primary, o, i, objects)
|
|
end
|
|
|
|
cache._buttons = buttons
|
|
data[o] = cache
|
|
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.
|
|
if cache.tbm and (text == nil or text == "") then
|
|
cache.tbm:set_margins(0)
|
|
elseif cache.tb then
|
|
if not cache.tb:set_markup_silently(text) then
|
|
cache.tb:set_markup("<i><Invalid text></i>")
|
|
end
|
|
end
|
|
|
|
if cache.bgb then
|
|
cache.bgb:set_bg(bg)
|
|
|
|
--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.border_width = item_args.shape_border_width
|
|
cache.bgb.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
|
|
|
|
if item_args.icon_size and cache.ib then
|
|
cache.ib.forced_height = item_args.icon_size
|
|
cache.ib.forced_width = item_args.icon_size
|
|
elseif cache.ib then
|
|
cache.ib.forced_height = nil
|
|
cache.ib.forced_width = nil
|
|
end
|
|
|
|
w:add(cache.primary)
|
|
end
|
|
end
|
|
|
|
return common
|
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|