--------------------------------------------------------------------------- -- @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("<Invalid text>") 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