diff --git a/lib/wibox/widget/template.lua b/lib/wibox/widget/template.lua
index 709a0afb3..b67b351bd 100644
--- a/lib/wibox/widget/template.lua
+++ b/lib/wibox/widget/template.lua
@@ -17,11 +17,6 @@
--
--@DOC_wibox_widget_template_basic_textbox_EXAMPLE@
--
--- Alternatively, you can declare the `template` widget instance using the
--- declarative pattern (both variants are strictly equivalent):
---
---@DOC_wibox_widget_template_basic_textbox_declarative_EXAMPLE@
---
-- Usage in libraries
-- ==================
--
@@ -64,36 +59,62 @@ local template = {
queued_updates = {},
}
+local function lazy_load_child(self)
+ if self._private.widget then return self._private.widget end
+
+ local widget_instance = wbase.make_widget_from_value(self._private.widget_template)
+
+ if widget_instance then
+ wbase.check_widget(widget_instance)
+ end
+
+ self._private.widget = widget_instance
+
+ local rem = {}
+
+ for k, conn in ipairs(self._private.connections) do
+ conn.apply()
+
+ if conn.once then
+ if conn.src_obj then
+ conn.src_obj:disconnect_signal("property::"..conn.src_prop, conn.apply)
+ end
+ table.insert(rem, k)
+ end
+ end
+
+ for i = #rem, 1, -1 do
+ table.remove(self._private.connections, rem[i])
+ end
+
+ return self._private.widget
+end
+
-- Layout this layout.
-- @method layout
-- @hidden
function template:layout(_, width, height)
- if not self._private.widget then
- return
- end
+ local w = lazy_load_child(self)
- return { wbase.place_widget_at(self._private.widget, 0, 0, width, height) }
+ if not w then return end
+
+ return { wbase.place_widget_at(w, 0, 0, width, height) }
end
-- Fit this layout into the given area.
-- @method fit
-- @hidden
function template:fit(context, width, height)
- if not self._private.widget then
+ local w = lazy_load_child(self)
+
+ if not w then
return 0, 0
end
- return wbase.fit_widget(self, context, self._private.widget, width, height)
+ return wbase.fit_widget(self, context, w, width, height)
end
--- Draw the widget if it's actually a widget instance
--- @method draw
--- @hidden
-function template:draw(...)
- if type(self._private.widget.draw) == "function" then
- return self._private.widget:draw(...)
- end
-end
+function template:draw() end
-- Call the update widget method now and clean the queue for this widget
-- instance.
@@ -109,14 +130,17 @@ function template:_do_update_now()
end
--- Update the widget.
+--
-- This function will call the `update_callback` function at the end of the
-- current GLib event loop. Updates are batched by event loop, it means that the
-- widget can only be update once by event loop. If the `template:update` method
-- is called multiple times during the same GLib event loop, only the first call
-- will be run.
-- All arguments are passed to the queued `update_callback` call.
--- @tparam[opt] table args A table to pass to the widget update function.
+--
+-- @tparam[opt={}] table args A table to pass to the widget update function.
-- @method update
+-- @noreturn
function template:update(args)
if type(args) == "table" then
self._private.update_args = gtable.crush(
@@ -134,36 +158,158 @@ function template:update(args)
end
--- Change the widget template.
--- @tparam table|widget widget_template The new widget to use as a
+--
+-- Note that this will discard the existing widget instance. Thus, any
+-- `set_property` will no longer be honored. `bind_property`, on the other hand,
+-- will still be honored.
+--
+-- @property template
+-- @tparam[opt=nil] template|nil template The new widget to use as a
-- template.
--- @method set_template
-- @emits widget::redraw_needed
--- @hidden
+-- @emits widget::layout_changed
+-- @propemits true false
+
function template:set_template(widget_template)
- local widget = widget_template or wbase.empty_widget()
+ if widget_template == self._private.widget_template then return end
- local widget_instance = wbase.make_widget_from_value(widget)
-
- if widget_instance then
- wbase.check_widget(widget_instance)
- end
-
- self._private.template = widget
- self._private.widget = widget_instance
-
- -- We need to connect to these signals to actually redraw the template
- -- widget when its child needs to.
- local signals = {
- "widget::redraw_needed",
- "widget::layout_changed",
- }
- for _, signal in pairs(signals) do
- self._private.widget:connect_signal(signal, function(...)
- self:emit_signal(signal, ...)
- end)
- end
+ self._private.widget = nil
+ self._private.widget_template = widget_template
self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ self:emit_signal("property::template", widget_template)
+end
+
+--- Set a property on one or more template sub-widget instances.
+--
+-- This method allows to set a value at any time on any of the sub widget of
+-- the template. To use this, you can set, or document a set of `ids` which
+-- your template support. These are usually referred as "roles" across the
+-- other APIs.
+--
+--@DOC_wibox_widget_template_set_property_existing_EXAMPLE@
+--
+-- It is also possible to take this one step further and apply a property
+-- to the entire sub-widget tree. This allows users to implement their own
+-- template even if it doesn't use the same "roles" as the default one:
+--
+--@DOC_wibox_widget_template_set_property_custom_EXAMPLE@
+--
+-- @method set_property
+-- @tparam string property The property name.
+-- @param value The property value.
+-- @tparam[opt=nil] nil|string|table ids A sub-widget `id` or list of `id`s. Use
+-- `nil` for "all sub widgets".
+-- @noreturn
+-- @see bind_property
+function template:set_property(property, value, ids)
+ local widgets
+ local target = self._private.widget
+
+ -- Lazy load later.
+ if not target then
+ table.insert(self._private.connections, {
+ src_obj = nil,
+ src_prop = nil,
+ once = true,
+ apply = function()
+ self:set_property(property, value, ids)
+ end,
+ })
+ return
+ end
+
+ if ids then
+ widgets = {}
+ for _, id in ipairs(type(ids) == "string" and {ids} or ids) do
+ for _, widget in ipairs(target:get_children_by_id(id)) do
+ table.insert(widgets, widget)
+ end
+ end
+ end
+
+ widgets = widgets or {target}
+
+ for _, widget in ipairs(widgets) do
+ if widget["set_"..property] then
+ widget["set_"..property](widget, value)
+ end
+ end
+end
+
+-- Do not use, backward compatibility only.
+function template:_set_property_on_tree(w, property, value)
+ local apply_property
+ apply_property = function(wdgs)
+ for _, widget in ipairs(wdgs) do
+ if widget["set_"..property] then
+ widget["set_"..property](widget, value)
+ end
+
+ if widget.get_children then
+ apply_property(widget:get_children())
+ end
+ end
+ end
+
+ apply_property({w})
+end
+
+--- Monitor the value of a property on a source object and apply it on a target.
+--
+-- This is the equivalent of:
+--
+-- src_obj:connect_signal(
+-- "property::"..src_prop,
+-- function(v)
+-- self:set_property(dest_prop, v, dest_ids)
+-- end
+-- )
+-- self:set_property(dest_prop, v, dest_ids)
+--
+-- @DOC_sequences_widget_tmpl_bind_property_EXAMPLE@
+--
+-- @method bind_property
+-- @tparam object src_obj The source object (must be derived from `gears.object`).
+-- @tparam string src_prop The source object property name.
+-- @tparam string dest_prop The destination widget property name.
+-- @tparam[opt=nil] table|string|nil dest_ids A sub-widget `id` or list of `id`s.
+-- Use `nil` for "all sub widgets".
+-- @noreturn
+-- @see clear_bindings
+-- @see set_property
+
+function template:bind_property(src_obj, src_prop, dest_prop, dest_ids)
+ local function apply()
+ self:set_property(dest_prop, src_obj[src_prop], dest_ids)
+ end
+
+ table.insert(self._private.connections, {
+ src_obj = src_obj,
+ src_prop = src_prop,
+ apply = apply,
+ })
+
+ src_obj:connect_signal("property::"..src_prop, apply)
+
+ apply()
+end
+
+
+--- Disconnect all signals created in `bind_property`.
+-- @method clear_bindings
+-- @tparam[opt=nil] widget|nil src_obj Disconnect only for this specific object.
+-- @noreturn
+-- @see bind_property
+
+function template:clear_bindings(src_obj)
+ for _, conn in ipairs(self._private.connections) do
+ if conn.src_obj and (conn.src_obj == src_obj or not src_obj) then
+ conn.src_obj:disconnect_signal("property::"..conn.src_prop, conn.apply)
+ end
+ end
+ self._private.connections = {}
end
--- Give the internal widget instance.
@@ -171,7 +317,7 @@ end
-- @method get_widget
-- @hidden
function template:get_widget()
- return self._private.widget
+ return lazy_load_child(self)
end
--- Set the update_callback property.
@@ -200,6 +346,27 @@ function template:set_update_now(update_now)
end
end
+
+--- Create a new `wibox.widget.template` instance using the same template.
+--
+-- This copy will be blank. Note that `set_property`, `bind_property` or
+-- `update_callback` from `self` will **NOT** be transferred over to the copy.
+--
+-- The following example is a new widget to list a bunch of colors. It uses
+-- `wibox.widget.template` to let the module user define their own color
+-- widget. It does so by cloning the original template into new instances. This
+-- example doesn't handle removing or updating them to keep the size small.
+--
+--@DOC_wibox_widget_template_clone1_EXAMPLE@
+--
+-- @method clone
+-- @treturn wibox.widget.template The copy.
+function template:clone()
+ return template {
+ template = self._private.widget_template
+ }
+end
+
--- Create a new `wibox.widget.template` instance.
-- @tparam[opt] table args
-- @tparam[opt] table|widget args.template The widget template to use.
@@ -215,6 +382,7 @@ function template.new(args)
local ret = wbase.make_widget(nil, nil, { enable_properties = true })
gtable.crush(ret, template, true)
+ ret._private.connections = {}
ret:set_template(args.template)
ret:set_update_callback(args.update_callback)
@@ -223,9 +391,32 @@ function template.new(args)
-- Apply the received buttons, visible, forced_width and so on
gtable.crush(ret, args)
+ rawset(ret, "_is_template", true)
+
return ret
end
+--- Create a `wibox.widget.template` from a table.
+--
+-- @staticfct wibox.widget.template.make_from_value
+-- @tparam[opt=nil] table|wibox.widget.template|nil value A template declaration.
+-- @treturn wibox.widget.template The template object.
+function template.make_from_value(value)
+ if not value then return nil end
+
+ assert(
+ not rawget(value, "is_widget"),
+ "This property requires a widget template, not a widget object.\n"..
+ "Use `wibox.template` instead of `wibox.widget`"
+ )
+
+ if rawget(value, "_is_template") then return value:clone() end
+
+ return template.new {
+ template = value
+ }
+end
+
function template.mt:__call(...)
return template.new(...)
end
diff --git a/tests/examples/sequences/widget/tmpl/bind_property.lua b/tests/examples/sequences/widget/tmpl/bind_property.lua
new file mode 100644
index 000000000..b8f1289e2
--- /dev/null
+++ b/tests/examples/sequences/widget/tmpl/bind_property.lua
@@ -0,0 +1,96 @@
+ --DOC_GEN_IMAGE --DOC_HIDE_START --DOC_NO_USAGE
+local module = ...
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local gears = {surface = require("gears.surface")}
+
+client.focus = client.gen_fake{
+ class = "client",
+ name = "A client!",
+ icon = beautiful.awesome_icon,
+}
+
+ --DOC_HIDE_END
+
+ local my_template_widget = wibox.widget.template {
+ template = {
+ {
+ {
+ set_icon = function(self, icon)
+ self.image = gears.surface(icon)
+ end,
+ id = "icon_role",
+ widget = wibox.widget.imagebox
+ },
+ {
+ id = "title_role",
+ widget = wibox.widget.textbox
+ },
+ widget = wibox.layout.fixed.horizontal,
+ },
+ widget = wibox.container.background,
+ id = "background_role",
+ set_urgent = function(self, status)
+ self.bg = status and "#ff0000" or nil
+ end,
+ forced_width = 200, --DOC_HIDE
+ forced_height = 24, --DOC_HIDE
+ }
+ }
+
+--DOC_NEWLINE
+--DOC_HIDE_START
+module.display_widget(my_template_widget, 200, 24)
+
+module.add_event("Original state", function()
+ --DOC_HIDE_END
+
+ -- Use the normal widget properties.
+ my_template_widget:bind_property(client.focus, "name", "text", "title_role")
+ my_template_widget:bind_property(client.focus, "icon", "icon", "icon_role")
+ --DOC_NEWLINE
+ -- This one uses an inline setter method.
+ my_template_widget:bind_property(client.focus, "urgent", "urgent", "background_role")
+
+ --DOC_HIDE_START
+end)
+
+--DOC_NEWLINE
+module.display_widget(my_template_widget, 200, 24)
+
+module.add_event("Change the client name.", function()
+ --DOC_HIDE_END
+ --DOC_NEWLINE
+ -- Change the client name.
+ client.focus.name = "New name!"
+ --DOC_HIDE_START
+end)
+
+--DOC_NEWLINE
+module.display_widget(my_template_widget, 200, 24)
+
+module.add_event("Make urgent", function()
+ --DOC_HIDE_END
+ --DOC_NEWLINE
+ -- Make urgent.
+ client.focus.urgent = true
+ --DOC_HIDE_START
+end)
+
+module.display_widget(my_template_widget, 200, 24)
+
+module.add_event("Make not urgent", function()
+ --DOC_HIDE_END
+ --DOC_NEWLINE
+ -- "Make not urgent.
+ client.focus.urgent = false
+ --DOC_HIDE_START
+end)
+
+module.display_widget(my_template_widget, 200, 24)
+
+
+module.execute { display_screen = false, display_clients = true,
+ display_label = false, display_client_name = true,
+ display_mouse = true ,
+}
diff --git a/tests/examples/wibox/widget/template/basic_textbox_declarative.lua b/tests/examples/wibox/widget/template/basic_textbox_declarative.lua
deleted file mode 100644
index 9dad45fff..000000000
--- a/tests/examples/wibox/widget/template/basic_textbox_declarative.lua
+++ /dev/null
@@ -1,25 +0,0 @@
---DOC_NO_USAGE
-
---DOC_HIDE_START
-local wibox = require("wibox")
---DOC_HIDE_END
-
- local my_template_widget = {
- id = "mytemplatewidget",
- template = wibox.widget.textbox,
- update_callback = function(template_widget, args)
- local text = args.text or "???"
- template_widget.widget.text = text
- end,
- widget = wibox.widget.template,
- }
-
---DOC_HIDE_START
-
--- Generate the widget to use the update method in the example.
--- A better approch would have been to use an ID and the `get_children_by_id`
--- on the parent.
-local widget = wibox.widget(my_template_widget)
-widget:update { text = "Cool text to update the template!" }
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/tests/examples/wibox/widget/template/clone1.lua b/tests/examples/wibox/widget/template/clone1.lua
new file mode 100644
index 000000000..330c6b606
--- /dev/null
+++ b/tests/examples/wibox/widget/template/clone1.lua
@@ -0,0 +1,149 @@
+--DOC_GEN_IMAGE --DOC_NO_USAGE
+
+--DOC_HIDE_START
+local parent = ...
+local wibox = require("wibox")
+local gears = {
+ shape = require("gears.shape"),
+ surface = require("gears.surface"),
+ color = require("gears.color"),
+ table = require("gears.table"),
+}
+local beautiful = require("beautiful")
+
+client.focus = client.gen_fake{
+ class = "client",
+ name = "A client!",
+ icon = beautiful.awesome_icon,
+}
+
+--DOC_HIDE_END
+ -- Put this in a Lua file
+ local module = {}
+ --DOC_NEWLINE
+
+ local default_template = wibox.widget.template {
+ template = {
+ {
+ {
+ {
+ forced_height = 16,
+ forced_width = 16,
+ shape = gears.shape.circle,
+ widget = wibox.widget.separator
+ },
+ margins = 3,
+ widget = wibox.container.margin
+ },
+ {
+ set_color = function(self, color)
+ self.text = color
+ end,
+ text = "N/A",
+ widget = wibox.widget.textbox
+ },
+ spacing = 5,
+ widget = wibox.layout.fixed.horizontal,
+ },
+ set_color = function(self, color)
+ self.border_color = gears.color.to_rgba_string(color):sub(1,7).."44"
+ self.fg = color
+ end,
+ border_width = 1,
+ shape = gears.shape.octogon,
+ widget = wibox.container.background,
+ forced_width = 100, --DOC_HIDE
+ }
+ }
+ --DOC_NEWLINE
+
+ --- Set the widget template.
+ -- @property widget_template
+ -- @tparam[opt=nil] wibox.template|nil
+ function module:set_widget_template(t)
+ self._private.widget_template = wibox.widget.template.make_from_value(t)
+ end
+
+ --DOC_NEWLINE
+ function module:get_widget_template()
+ return self._private.widget_template or default_template
+ end
+ --DOC_NEWLINE
+
+ --- Add a color to the list.
+ function module:add_color(color_name)
+ local instance = self.widget_template:clone()
+ instance:set_property("color", color_name, nil, true)
+
+ self._private.base_layout:add(instance)
+ end
+ --DOC_NEWLINE
+
+ --- my_module_name constructor.
+ --
+ -- @constructorfct my_module_name
+ -- @tparam[opt={}] table args
+ -- @tparam wibox.template args.widget_template A widget template.
+ -- @tparam wibox.layout args.base_layout A layout to use instead of
+ -- `wibox.layout.fixed.vertical`.
+ local function new(_, args)
+ args = args or {}
+
+ --DOC_NEWLINE
+ -- Create the base_layout instance.
+ local l = wibox.widget.base.make_widget_from_value(
+ args.base_layout or wibox.widget {
+ spacing = 5,
+ widget = wibox.layout.fixed.vertical
+ }
+ )
+
+ --DOC_NEWLINE
+ -- Create the base widget as a proxy widget.
+ local ret = wibox.widget.base.make_widget(l, "my_module_name", {
+ enable_properties = true,
+ })
+
+ --DOC_NEWLINE
+ -- Set the default (fallback) template
+ ret._private.base_layout = l
+
+ --DOC_NEWLINE
+ -- Add the methods and apply set the initial properties.
+ gears.table.crush(ret, module, true)
+ gears.table.crush(ret, args)
+
+ --DOC_NEWLINE
+ return ret
+ end
+
+ --[[ --DOC_HIDE
+ return setmetatable(module, {__call = new})
+ ]]--DOC_HIDE
+
+
+--[[ --DOC_HIDE
+--DOC_NEWLINE
+Now, lets use this module to list some colors:
+--DOC_NEWLINE
+ local my_module_name = require("my_module_name")
+--DOC_NEWLINE
+]] --DOC_HIDE
+local my_module_name = new --DOC_HIDE
+--DOC_NEWLINE
+
+ local my_color_list = my_module_name {}
+--DOC_NEWLINE
+
+ my_color_list:add_color("#ff0000")
+ my_color_list:add_color("#00ff00")
+ my_color_list:add_color("#0000ff")
+ my_color_list:add_color("#ff00ff")
+ my_color_list:add_color("#ffff00")
+ my_color_list:add_color("#00ffff")
+
+--DOC_HIDE_START
+
+parent:add(my_color_list)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/tests/examples/wibox/widget/template/concrete_implementation_module.lua b/tests/examples/wibox/widget/template/concrete_implementation_module.lua
index 111b3f1dd..97deb39ec 100644
--- a/tests/examples/wibox/widget/template/concrete_implementation_module.lua
+++ b/tests/examples/wibox/widget/template/concrete_implementation_module.lua
@@ -1,4 +1,4 @@
---DOC_NO_USAGE
+--DOC_NO_USAGE --DOC_GEN_IMAGE
--DOC_HIDE_START
local parent = ...
@@ -6,12 +6,12 @@ local parent = ...
local gears = require("gears")
local wibox = require("wibox")
-local concrete_widget_template_builder
--DOC_HIDE_END
-- Build the default widget used as a fallback if user doesn't provide a template
local default_widget = {
- template = wibox.widget.textclock,
+ template = wibox.widget.textbox,
+ text = "N/A",
update_callback = function(widget_template, args)
local text = args and args.text or "???"
widget_template.widget.text = text
@@ -19,29 +19,28 @@ local concrete_widget_template_builder
}
--DOC_NEWLINE
- function concrete_widget_template_builder(args)
+ local function concrete_widget_template_builder(args)
args = args or {}
--DOC_NEWLINE
-- Build an instance of the template widget with either, the
-- user provided parameters or the default
- local ret = wibox.widget.template(
- args.widget_template and args.widget_template or
- default_widget
- )
+ local ret = wibox.widget.template {
+ template = args.widget_template or default_widget
+ }
--DOC_NEWLINE
- -- Patch the methods and fields the widget instance should have
+ -- Patch the methods and fields the widget instance should have
--DOC_NEWLINE
- -- e.g. Apply the received buttons, visible, forced_width and so on
- gears.table.crush(ret, args)
+ -- e.g. Apply the received buttons, visible, forced_width and so on
+ gears.table.crush(ret, args)
--DOC_NEWLINE
-- Optionally, call update once with parameters to prepare the widget
- ret:update {
- text = "default text",
- }
+ ret:update {
+ text = "default text",
+ }
--DOC_NEWLINE
return ret
diff --git a/tests/examples/wibox/widget/template/set_property_custom.lua b/tests/examples/wibox/widget/template/set_property_custom.lua
new file mode 100644
index 000000000..5123baf3b
--- /dev/null
+++ b/tests/examples/wibox/widget/template/set_property_custom.lua
@@ -0,0 +1,67 @@
+--DOC_GEN_IMAGE --DOC_NO_USAGE
+
+--DOC_HIDE_START
+local parent = ...
+local wibox = require("wibox")
+local gears = {share = require("gears.shape"), surface = require("gears.surface")}
+local beautiful = require("beautiful")
+
+client.focus = client.gen_fake{
+ class = "client",
+ name = "A client!",
+ icon = beautiful.awesome_icon,
+}
+
+--DOC_HIDE_END
+
+ local my_template_widget = wibox.widget.template {
+ template = {
+ {
+ {
+ id = "client_role",
+ set_client = function(self, c)
+ self.image = gears.surface(c.icon)
+ end,
+ widget = wibox.widget.imagebox
+ },
+ {
+ id = "client_role",
+ set_client = function(self, c)
+ -- If the value can change, don't forget to connect
+ -- some signals:
+ local function update()
+ local txt = "Name: "..c.name
+ if c.minimized then
+ txt = txt .. " (minimized)"
+ end
+ self.markup = txt
+ end
+
+ update()
+ c:connect_signal("property::name", update)
+ c:connect_signal("property::minimized", update)
+ end,
+ widget = wibox.widget.textbox
+ },
+ widget = wibox.layout.fixed.horizontal,
+ },
+ bg = "#0000ff",
+ fg = "#ffffff",
+ shape = gears.share.rounded_rect,
+ widget = wibox.container.background,
+ forced_width = 200, --DOC_HIDE
+ forced_height = 24, --DOC_HIDE
+ }
+ }
+
+--DOC_NEWLINE
+ -- Later in the code
+ local c = client.focus
+ my_template_widget:set_property("client", c, "client_role")
+ c.minimized = true
+
+--DOC_HIDE_START
+
+parent:add(my_template_widget)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/tests/examples/wibox/widget/template/set_property_existing.lua b/tests/examples/wibox/widget/template/set_property_existing.lua
new file mode 100644
index 000000000..b915310ea
--- /dev/null
+++ b/tests/examples/wibox/widget/template/set_property_existing.lua
@@ -0,0 +1,52 @@
+--DOC_GEN_IMAGE --DOC_NO_USAGE
+
+--DOC_HIDE_START
+local parent = ...
+local wibox = require("wibox")
+local gears = {share = require("gears.shape"), surface = require("gears.surface")}
+local beautiful = require("beautiful")
+
+client.focus = client.gen_fake{
+ class = "client",
+ name = "A client!",
+ icon = beautiful.awesome_icon,
+}
+
+--DOC_HIDE_END
+
+ local my_template_widget = wibox.widget.template {
+ template = {
+ {
+ {
+ id = "icon_role",
+ widget = wibox.widget.imagebox
+ },
+ {
+ id = "title_role",
+ widget = wibox.widget.textbox
+ },
+ widget = wibox.layout.fixed.horizontal,
+ },
+ id = "background_role",
+ widget = wibox.container.background,
+ forced_width = 200, --DOC_HIDE
+ forced_height = 24, --DOC_HIDE
+ }
+ }
+
+--DOC_NEWLINE
+ -- Later in the code
+ local c = client.focus
+ my_template_widget:set_property("image", gears.surface(c.icon),"icon_role")
+ my_template_widget:set_property("text", c.name, "title_role")
+ my_template_widget:set_property("bg", "#0000ff", "background_role")
+ my_template_widget:set_property("fg", "#ffffff", "background_role")
+ my_template_widget:set_property(
+ "shape", gears.share.rounded_rect, "background_role"
+ )
+
+--DOC_HIDE_START
+
+parent:add(my_template_widget)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80