template: Bring to feature parity with the awful.widget.common implementation.
`awful.widget.common` has the ability to set "roles" and apply properties to the entire widget tree. This was missing from the previous commit.
This commit is contained in:
parent
495922c31c
commit
67b2b26683
|
@ -17,11 +17,6 @@
|
||||||
--
|
--
|
||||||
--@DOC_wibox_widget_template_basic_textbox_EXAMPLE@
|
--@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
|
-- Usage in libraries
|
||||||
-- ==================
|
-- ==================
|
||||||
--
|
--
|
||||||
|
@ -64,36 +59,62 @@ local template = {
|
||||||
queued_updates = {},
|
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.
|
-- Layout this layout.
|
||||||
-- @method layout
|
-- @method layout
|
||||||
-- @hidden
|
-- @hidden
|
||||||
function template:layout(_, width, height)
|
function template:layout(_, width, height)
|
||||||
if not self._private.widget then
|
local w = lazy_load_child(self)
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
-- Fit this layout into the given area.
|
-- Fit this layout into the given area.
|
||||||
-- @method fit
|
-- @method fit
|
||||||
-- @hidden
|
-- @hidden
|
||||||
function template:fit(context, width, height)
|
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
|
return 0, 0
|
||||||
end
|
end
|
||||||
|
|
||||||
return wbase.fit_widget(self, context, self._private.widget, width, height)
|
return wbase.fit_widget(self, context, w, width, height)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Draw the widget if it's actually a widget instance
|
function template:draw() end
|
||||||
-- @method draw
|
|
||||||
-- @hidden
|
|
||||||
function template:draw(...)
|
|
||||||
if type(self._private.widget.draw) == "function" then
|
|
||||||
return self._private.widget:draw(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Call the update widget method now and clean the queue for this widget
|
-- Call the update widget method now and clean the queue for this widget
|
||||||
-- instance.
|
-- instance.
|
||||||
|
@ -109,14 +130,17 @@ function template:_do_update_now()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Update the widget.
|
--- Update the widget.
|
||||||
|
--
|
||||||
-- This function will call the `update_callback` function at the end of the
|
-- 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
|
-- 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
|
-- 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
|
-- is called multiple times during the same GLib event loop, only the first call
|
||||||
-- will be run.
|
-- will be run.
|
||||||
-- All arguments are passed to the queued `update_callback` call.
|
-- 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
|
-- @method update
|
||||||
|
-- @noreturn
|
||||||
function template:update(args)
|
function template:update(args)
|
||||||
if type(args) == "table" then
|
if type(args) == "table" then
|
||||||
self._private.update_args = gtable.crush(
|
self._private.update_args = gtable.crush(
|
||||||
|
@ -134,36 +158,158 @@ function template:update(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Change the widget template.
|
--- 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.
|
-- template.
|
||||||
-- @method set_template
|
|
||||||
-- @emits widget::redraw_needed
|
-- @emits widget::redraw_needed
|
||||||
-- @hidden
|
-- @emits widget::layout_changed
|
||||||
|
-- @propemits true false
|
||||||
|
|
||||||
function template:set_template(widget_template)
|
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)
|
self._private.widget = nil
|
||||||
|
self._private.widget_template = widget_template
|
||||||
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:emit_signal("widget::redraw_needed")
|
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
|
end
|
||||||
|
|
||||||
--- Give the internal widget instance.
|
--- Give the internal widget instance.
|
||||||
|
@ -171,7 +317,7 @@ end
|
||||||
-- @method get_widget
|
-- @method get_widget
|
||||||
-- @hidden
|
-- @hidden
|
||||||
function template:get_widget()
|
function template:get_widget()
|
||||||
return self._private.widget
|
return lazy_load_child(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the update_callback property.
|
--- Set the update_callback property.
|
||||||
|
@ -200,6 +346,27 @@ function template:set_update_now(update_now)
|
||||||
end
|
end
|
||||||
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.
|
--- Create a new `wibox.widget.template` instance.
|
||||||
-- @tparam[opt] table args
|
-- @tparam[opt] table args
|
||||||
-- @tparam[opt] table|widget args.template The widget template to use.
|
-- @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 })
|
local ret = wbase.make_widget(nil, nil, { enable_properties = true })
|
||||||
|
|
||||||
gtable.crush(ret, template, true)
|
gtable.crush(ret, template, true)
|
||||||
|
ret._private.connections = {}
|
||||||
|
|
||||||
ret:set_template(args.template)
|
ret:set_template(args.template)
|
||||||
ret:set_update_callback(args.update_callback)
|
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
|
-- Apply the received buttons, visible, forced_width and so on
|
||||||
gtable.crush(ret, args)
|
gtable.crush(ret, args)
|
||||||
|
|
||||||
|
rawset(ret, "_is_template", true)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
end
|
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(...)
|
function template.mt:__call(...)
|
||||||
return template.new(...)
|
return template.new(...)
|
||||||
end
|
end
|
||||||
|
|
|
@ -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 ,
|
||||||
|
}
|
|
@ -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
|
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
||||||
--DOC_NO_USAGE
|
--DOC_NO_USAGE --DOC_GEN_IMAGE
|
||||||
|
|
||||||
--DOC_HIDE_START
|
--DOC_HIDE_START
|
||||||
local parent = ...
|
local parent = ...
|
||||||
|
@ -6,12 +6,12 @@ local parent = ...
|
||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
local concrete_widget_template_builder
|
|
||||||
--DOC_HIDE_END
|
--DOC_HIDE_END
|
||||||
|
|
||||||
-- Build the default widget used as a fallback if user doesn't provide a template
|
-- Build the default widget used as a fallback if user doesn't provide a template
|
||||||
local default_widget = {
|
local default_widget = {
|
||||||
template = wibox.widget.textclock,
|
template = wibox.widget.textbox,
|
||||||
|
text = "N/A",
|
||||||
update_callback = function(widget_template, args)
|
update_callback = function(widget_template, args)
|
||||||
local text = args and args.text or "???"
|
local text = args and args.text or "???"
|
||||||
widget_template.widget.text = text
|
widget_template.widget.text = text
|
||||||
|
@ -19,29 +19,28 @@ local concrete_widget_template_builder
|
||||||
}
|
}
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
function concrete_widget_template_builder(args)
|
local function concrete_widget_template_builder(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
-- Build an instance of the template widget with either, the
|
-- Build an instance of the template widget with either, the
|
||||||
-- user provided parameters or the default
|
-- user provided parameters or the default
|
||||||
local ret = wibox.widget.template(
|
local ret = wibox.widget.template {
|
||||||
args.widget_template and args.widget_template or
|
template = args.widget_template or default_widget
|
||||||
default_widget
|
}
|
||||||
)
|
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
-- Patch the methods and fields the widget instance should have
|
-- Patch the methods and fields the widget instance should have
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
-- e.g. Apply the received buttons, visible, forced_width and so on
|
-- e.g. Apply the received buttons, visible, forced_width and so on
|
||||||
gears.table.crush(ret, args)
|
gears.table.crush(ret, args)
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
-- Optionally, call update once with parameters to prepare the widget
|
-- Optionally, call update once with parameters to prepare the widget
|
||||||
ret:update {
|
ret:update {
|
||||||
text = "default text",
|
text = "default text",
|
||||||
}
|
}
|
||||||
|
|
||||||
--DOC_NEWLINE
|
--DOC_NEWLINE
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -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 = "<b>Name: </b>"..c.name
|
||||||
|
if c.minimized then
|
||||||
|
txt = txt .. "<i> (minimized)</i>"
|
||||||
|
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
|
|
@ -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
|
Loading…
Reference in New Issue