feat(w.c.conditional): Implement conditional container

This container allows showing or hiding a child widget based on a boolean
state property.
This commit is contained in:
Lucas Schwiderski 2022-06-29 17:11:01 +02:00
parent 02fa372d9e
commit 3b1a80a9ce
No known key found for this signature in database
GPG Key ID: AA12679AAA6DF4D8
4 changed files with 220 additions and 0 deletions

View File

@ -0,0 +1,109 @@
---------------------------------------------------------------------------
-- A simple container that will hide its child widget based a
-- boolean state variable.
--
--@DOC_wibox_container_conditional_comparison_EXAMPLE@
--
-- @author Lucas Schwiderski
-- @copyright 2022 Lucas Schwiderski
-- @containermod wibox.container.conditional
-- @supermodule wibox.widget.base
---------------------------------------------------------------------------
local base = require("wibox.widget.base")
local gtable = require("gears.table")
local gobject = require("gears.object")
local conditional = { mt = {} }
function conditional:fit(context, width, height)
if not self._private.state then
return 0, 0
end
return base.fit_widget(self, context, self._private.widget, width, height)
end
function conditional:layout(_, width, height)
if not self._private.state then
return {}
end
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
end
--- The conditional state.
--
-- The child widget is shown or hidden based on this state.
--
-- @property state
-- @tparam boolean state
-- @propemits true false
function conditional:set_state(state)
state = not (not state)
if self._private.state == state then
return
end
self._private.state = state
self:emit_signal("widget::layout_changed")
self:emit_signal("property::state", state)
end
function conditional:get_state()
return self._private.state
end
--- The widget to be displayed based on the state.
-- @property widget
-- @tparam widget widget
-- @propemits true false
-- @interface container
conditional.set_widget = base.set_widget_common
function conditional:get_widget()
return self._private.widget
end
function conditional:set_children(widgets)
self:set_widget(widgets[1])
end
function conditional:get_children()
return { self._private.widget }
end
local function new(widget, state)
local ret = base.make_widget(nil, nil, { enable_properties = true})
gtable.crush(ret, conditional, true)
ret.widget_name = gobject.modulename(2)
ret._private.widget = widget
if type(state) == "boolean" then
ret._private.state = state
else
ret._private.state = true
end
return ret
end
function conditional.mt:__call(...)
return new(...)
end
return setmetatable(conditional, conditional.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -18,6 +18,7 @@ return setmetatable({
arcchart = require("wibox.container.arcchart");
place = require("wibox.container.place");
tile = require("wibox.container.tile");
conditional = require("wibox.container.conditional");
}, {__call = function(_, args) return base.make_widget_declarative(args) end})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -0,0 +1,48 @@
---------------------------------------------------------------------------
-- @author Lucas Schwiderski
-- @copyright 2022 Lucas Schwiderski
---------------------------------------------------------------------------
local conditional = require("wibox.container.conditional")
local utils = require("wibox.test_utils")
local base = require("wibox.widget.base")
local p = require("wibox.widget.base").place_widget_at
describe("wibox.container.conditional", function()
it("implements the common API", function()
utils.test_container(conditional())
end)
describe("constructor", function()
it("applies arguments", function()
local inner = base.empty_widget()
local state = false
local widget = conditional(inner, state)
assert.is.equal(inner, widget.widget)
assert.is.equal(state, widget.state)
end)
it("defaults to state == true", function()
local widget = conditional()
assert.is_true(widget.state)
end)
end)
it("hides the child widget when state == false", function()
local inner = utils.widget_stub(10, 10)
local widget = conditional(inner)
assert.widget_fit(widget, { 10, 10 }, { 10, 10 })
assert.widget_layout(widget, { 10, 10 }, {
p(inner, 0, 0, 10, 10),
})
widget.state = false
assert.widget_fit(widget, { 10, 10 }, { 0, 0 })
assert.widget_layout(widget, { 0, 0 }, {})
end)
end)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -0,0 +1,62 @@
--DOC_HIDE_START --DOC_GEN_IMAGE
local parent = ...
local wibox = require("wibox")
local beautiful = require("beautiful")
parent.spacing = 10
parent:add(wibox.widget {
layout = wibox.layout.fixed.vertical,
spacing = 2,
{
markup = "state == <b>true</b>",
widget = wibox.widget.textbox
},
--DOC_HIDE_END
{
{
{
text = "Hello, World!",
widget = wibox.widget.textbox,
},
state = true,
widget = wibox.container.conditional,
},
bg = beautiful.bg_normal,
widget = wibox.container.background,
},
--DOC_HIDE_START
})
parent:add(wibox.widget {
layout = wibox.layout.fixed.vertical,
spacing = 2,
{
markup = "state == <b>false</b>",
widget = wibox.widget.textbox
},
--DOC_HIDE_END
{
{ --DOC_HIDE
{
{
text = "Hello, World!",
widget = wibox.widget.textbox,
},
state = false,
widget = wibox.container.conditional,
},
--DOC_HIDE_START
strategy = "min",
width = 100,
height = 18,
widget = wibox.container.constraint,
},
--DOC_HIDE_END
bg = beautiful.bg_normal,
widget = wibox.container.background,
},
--DOC_HIDE_START
})
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80