-- https://stackoverflow.com/questions/64087640/prevent-content-shrinking-in-awesomewm
-- twily sourced 2024
local base = require("wibox.widget.base")
local layout = {}
-- Calculate the layout.
-- @param context The context in which we are drawn.
-- @param width The available width.
-- @param height The available height.
function layout:layout(context, width, height)
local result = {}
local prepend_width, prepend_height = 0, 0
if self._private.prepend then
prepend_width, prepend_height = base.fit_widget(self, context, self._private.prepend, width, height)
end
local append_width, append_height = 0, 0
if self._private.append then
append_width, append_height = base.fit_widget(self, context, self._private.append, width, height)
end
local width_remains = self._private.dir == "x" and (width - prepend_width - append_width) or width
local height_remains = self._private.dir == "y" and (height - prepend_height - append_height) or height
local main_width, main_height = base.fit_widget(self, context, self._private.main, width_remains, height_remains)
if self._private.prepend then
local x, y, w, h = 0, 0, width, height
if self._private.dir == "x" then
w = prepend_width
elseif self._private.dir == "y" then
h = prepend_height
end
table.insert(result, base.place_widget_at(self._private.prepend, x, y, w, h))
end
if self._private.main then
local x, y, w, h = 0, 0, width, height
if self._private.dir == "x" then
x = prepend_width
w = main_width
elseif self._private.dir == "y" then
y = prepend_height
h = main_height
end
table.insert(result, base.place_widget_at(self._private.main, x, y, w, h))
end
if self._private.append then
local x, y, w, h = 0, 0, width, height
if self._private.dir == "x" then
x = prepend_width + main_width
w = append_width
elseif self._private.dir == "y" then
y = prepend_height + main_height
h = append_height
end
table.insert(result, base.place_widget_at(self._private.append, x, y, w, h))
end
return result
end
--- Set the layout's prepend widget.
-- This is the widget which is before the main widget
-- @property prepend
-- @tparam widget prepend
-- @propemits true false
function layout:set_prepend(widget)
if self._private.prepend == widget then
return
end
self._private.prepend = widget
self:emit_signal("widget::layout_changed")
self:emit_signal("property::prepend", widget)
end
--- Set the layout's main widget. This is the centered one.
-- @property main
-- @tparam widget main
-- @propemits true false
function layout:set_main(widget)
if self._private.main == widget then
return
end
self._private.main = widget
self:emit_signal("widget::layout_changed")
self:emit_signal("property::main", widget)
end
--- Set the layout's append widget.
-- This is the widget which is after the main widget
-- @property append
-- @tparam widget append
-- @propemits true false
function layout:set_append(widget)
if self._private.append == widget then
return
end
self._private.append = widget
self:emit_signal("widget::layout_changed")
self:emit_signal("property::append", widget)
end
for _, prop in ipairs {"prepend", "main", "append" } do
layout["get_"..prop] = function(self)
return self._private[prop]
end
end
function layout:get_children()
return gears.table.from_sparse {self._private.prepend, self._private.main, self._private.append}
end
function layout:set_children(children)
self:set_prepend(children[1])
self:set_main(children[2])
self:set_append(children[3])
end
-- Fit the layout into the given space. The layout will
-- ask for the sum of the sizes of its sub-widgets in its direction
-- and the largest sized sub widget in the other direction.
-- @param context The context in which we are fit.
-- @param orig_width The available width.
-- @param orig_height The available height.
function layout:fit(context, orig_width, orig_height)
local used_in_dir = 0
local used_in_other = 0
for _, v in pairs{self._private.prepend, self._private.main, self._private.append} do
local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
local max = self._private.dir == "y" and w or h
if max > used_in_other then
used_in_other = max
end
used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
end
if self._private.dir == "y" then
return used_in_other, used_in_dir
end
return used_in_dir, used_in_other
end
function layout:reset()
for _, v in pairs({ "prepend", "main", "append" }) do
self[v] = nil
end
self:emit_signal("widget::layout_changed")
end
local function get_layout(dir, prepend, main, append)
local ret = base.make_widget(nil, nil, {enable_properties = true})
ret._private.dir = dir
for k, v in pairs(layout) do
if type(v) == "function" then
rawset(ret, k, v)
end
end
ret:set_prepend(prepend)
ret:set_main(main)
ret:set_append(append)
-- The layout allow set_children to have empty entries
ret.allow_empty_widget = true
return ret
end
--- Returns a new horizontal layout. This layout can display up to three widgets.
-- :set_prepend() sets a widget with a fixed size at the beginning.
-- :set_append() sets a widget with a fixed size at the end.
-- :set_main() sets a widget which shrink if their is not enough space.
-- @tparam[opt] widget prepend Widget to be put to the beginning.
-- @tparam[opt] widget main Widget to be put to the middle.
-- @tparam[opt] widget append Widget to be put to the end.
function layout.horizontal(prepend, main, append)
local ret = get_layout("x", prepend, main, append)
return ret
end
--- Returns a new vertical layout. This layout can display up to three widgets.
-- :set_prepend() sets a widget with a fixed size at the beginning.
-- :set_append() sets a widget with a fixed size at the end.
-- :set_main() sets a widget which shrink if their is not enough space.
-- @tparam[opt] widget prepend Widget to be put to the beginning.
-- @tparam[opt] widget main Widget to be put to the middle.
-- @tparam[opt] widget append Widget to be put to the end.
function layout.vertical(prepend, main, append)
local ret = get_layout("y", prepend, main, append)
return ret
end
return layout
Top