2010-10-06 12:42:56 +02:00
|
|
|
---------------------------------------------------------------------------
|
2021-12-21 06:54:15 +01:00
|
|
|
-- Place many widgets in a column or row, until the available space is used up.
|
|
|
|
--
|
2021-07-13 22:44:50 +02:00
|
|
|
-- A `fixed` layout may be initialized with any number of child widgets, and
|
|
|
|
-- during runtime widgets may be added and removed dynamically.
|
|
|
|
--
|
|
|
|
-- On the main axis, child widgets are given a fixed size of exactly as much
|
|
|
|
-- space as they ask for. The layout will then resize according to the sum of
|
|
|
|
-- all child widgets. If the space available to the layout is not enough to
|
|
|
|
-- include all child widgets, the excessive ones are not drawn at all.
|
|
|
|
--
|
|
|
|
-- Additionally, the layout allows adding empty spacing or even placing a custom
|
|
|
|
-- spacing widget between the child widget.
|
|
|
|
--
|
|
|
|
-- On its secondary axis, the layout's size is determined by the largest child
|
|
|
|
-- widget. Smaller child widgets are then placed with the same size.
|
|
|
|
-- Therefore, child widgets may ignore their `forced_width` or `forced_height`
|
|
|
|
-- properties for vertical and horizontal layouts respectively.
|
2016-05-25 21:17:16 +02:00
|
|
|
--
|
|
|
|
--@DOC_wibox_layout_defaults_fixed_EXAMPLE@
|
2021-07-13 22:44:50 +02:00
|
|
|
--
|
2010-10-06 12:42:56 +02:00
|
|
|
-- @author Uli Schlachter
|
|
|
|
-- @copyright 2010 Uli Schlachter
|
2019-06-06 08:19:03 +02:00
|
|
|
-- @layoutmod wibox.layout.fixed
|
2021-03-27 20:05:10 +01:00
|
|
|
-- @supermodule wibox.widget.base
|
2010-10-06 12:42:56 +02:00
|
|
|
---------------------------------------------------------------------------
|
|
|
|
|
2016-02-27 13:55:34 +01:00
|
|
|
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
2016-01-18 08:51:09 +01:00
|
|
|
local base = require("wibox.widget.base")
|
2010-10-06 12:42:56 +02:00
|
|
|
local table = table
|
|
|
|
local pairs = pairs
|
2017-03-08 21:18:33 +01:00
|
|
|
local gtable = require("gears.table")
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2012-06-12 15:29:52 +02:00
|
|
|
local fixed = {}
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2016-05-09 07:36:32 +02:00
|
|
|
-- Layout a fixed layout. Each widget gets just the space it asks for.
|
2015-08-08 13:18:54 +02:00
|
|
|
-- @param context The context in which we are drawn.
|
2010-10-06 12:42:56 +02:00
|
|
|
-- @param width The available width.
|
|
|
|
-- @param height The available height.
|
2015-06-14 16:12:44 +02:00
|
|
|
function fixed:layout(context, width, height)
|
|
|
|
local result = {}
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
local spacing = self._private.spacing or 0
|
2017-08-07 22:12:29 +02:00
|
|
|
local is_y = self._private.dir == "y"
|
|
|
|
local is_x = not is_y
|
|
|
|
local abspace = math.abs(spacing)
|
|
|
|
local spoffset = spacing < 0 and 0 or spacing
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
local widgets_nr = #self._private.widgets
|
|
|
|
local spacing_widget
|
|
|
|
local x, y = 0, 0
|
|
|
|
|
|
|
|
spacing_widget = spacing ~= 0 and self._private.spacing_widget or nil
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2021-07-13 22:30:52 +02:00
|
|
|
for index, widget in pairs(self._private.widgets) do
|
2021-05-31 10:19:25 +02:00
|
|
|
local w, h, local_spacing = width - x, height - y, spacing
|
|
|
|
|
|
|
|
-- Some widget might be zero sized either because this is their
|
|
|
|
-- minimum space or just because they are really empty. In this case,
|
|
|
|
-- they must still be added to the layout. Otherwise, if their size
|
|
|
|
-- change and this layout is resizable, they are lost "forever" until
|
|
|
|
-- a full relayout is called on this fixed layout object.
|
|
|
|
local zero = false
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
|
2017-08-07 22:12:29 +02:00
|
|
|
if is_y then
|
2021-07-13 22:30:52 +02:00
|
|
|
if index ~= widgets_nr or not self._private.fill_space then
|
|
|
|
h = select(2, base.fit_widget(self, context, widget, w, h))
|
2021-05-31 10:19:25 +02:00
|
|
|
zero = h == 0
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
if y - spacing >= height then
|
|
|
|
-- pop the spacing widget added in previous iteration if used
|
|
|
|
if spacing_widget then
|
|
|
|
table.remove(result)
|
2021-05-31 10:19:25 +02:00
|
|
|
|
|
|
|
-- Avoid adding zero-sized widgets at an out-of-bound
|
|
|
|
-- position.
|
|
|
|
y = y - spacing
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Never display "random" widgets as soon as a non-zero sized
|
|
|
|
-- one doesn't fit.
|
|
|
|
if not zero then
|
|
|
|
break
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
else
|
2021-07-13 22:30:52 +02:00
|
|
|
if index ~= widgets_nr or not self._private.fill_space then
|
|
|
|
w = select(1, base.fit_widget(self, context, widget, w, h))
|
2021-05-31 10:19:25 +02:00
|
|
|
zero = w == 0
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
if x - spacing >= width then
|
|
|
|
-- pop the spacing widget added in previous iteration if used
|
|
|
|
if spacing_widget then
|
|
|
|
table.remove(result)
|
2021-05-31 10:19:25 +02:00
|
|
|
|
|
|
|
-- Avoid adding zero-sized widgets at an out-of-bound
|
|
|
|
-- position.
|
|
|
|
x = x - spacing
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Never display "random" widgets as soon as a non-zero sized
|
|
|
|
-- one doesn't fit.
|
|
|
|
if not zero then
|
|
|
|
break
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
end
|
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
2017-08-07 22:12:29 +02:00
|
|
|
|
2021-05-31 10:19:25 +02:00
|
|
|
if zero then
|
|
|
|
local_spacing = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Place widget, even if it has zero width/height. Otherwise
|
|
|
|
-- any layout change for zero-sized widget would become invisible.
|
2021-07-13 22:30:52 +02:00
|
|
|
table.insert(result, base.place_widget_at(widget, x, y, w, h))
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
|
2021-05-31 10:19:25 +02:00
|
|
|
x = is_x and x + w + local_spacing or x
|
|
|
|
y = is_y and y + h + local_spacing or y
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
|
|
|
|
-- Add the spacing widget (if needed)
|
2021-07-13 22:30:52 +02:00
|
|
|
if index < widgets_nr and spacing_widget then
|
2017-08-07 22:12:29 +02:00
|
|
|
table.insert(result, base.place_widget_at(
|
2021-07-13 22:33:32 +02:00
|
|
|
spacing_widget,
|
|
|
|
is_x and (x - spoffset) or x,
|
|
|
|
is_y and (y - spoffset) or y,
|
|
|
|
is_x and abspace or w,
|
|
|
|
is_y and abspace or h
|
2017-08-07 22:12:29 +02:00
|
|
|
))
|
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
layout/fixed: Prevent overloading widgets with negative spacing
For each widget, the layout function checks whether placing it would
make the function exceed the allowed geometry.
If not, the function places both the widget and a spacing widget.
This check ignores the size of the spacing widget itself, this can cause
overloading of widgets on top of each other.
For example, the following scenario with these widgets:
widgets: widget1 { width = 10, height = 10 }
widget2 { width = 10, height = 10 }
widget3 { width = 10, height = 10 }
and a call to horizontal layout with the
{ width = 10, height = 10, spacing = -5 } parameters.
The function would layout the widgets the following way:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget2: { x = 5, y = 0, width = 5, height = 10 }
spacing: { x = 5, y = 0, width = 5, height = 10 }
widget3: { x = 5, y = 0, width = 5, height = 10 }
}
This behaviour would be the same for any number of widgets for negative
layout.
This patch changes the layout function to check whether the current
widget uses up the whole space.
It also removes 'pos' variable. Its purpose isn't intuitive in the
presence of x and y. This helps to understand where each widget is
placed now that x, y don't hold the end location of the widget in the
previous loop iteration.
The result of the previous example becomes:
{
widget1: { x = 0, y = 0, width = 10, height = 10 }
}
While this might not be the wanted behaviour exactly, distinguishing
between the scenario where 2 widgets are drawn and a scenario where 3
are drawn might complicate the layout function too much.
This patch also adds unit testing that catches the described behaviour.
Signed-off-by: Shay Agroskin <agrosshay@gmail.com>
2021-01-01 20:13:19 +01:00
|
|
|
|
2015-06-14 16:12:44 +02:00
|
|
|
return result
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2019-11-29 07:22:50 +01:00
|
|
|
--- Add some widgets to the given layout.
|
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @method add
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @tparam widget ... Widgets that should be added (must at least be one).
|
2022-07-05 10:37:14 +02:00
|
|
|
-- @noreturn
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @interface layout
|
2015-09-28 21:00:49 +02:00
|
|
|
function fixed:add(...)
|
|
|
|
-- No table.pack in Lua 5.1 :-(
|
|
|
|
local args = { n=select('#', ...), ... }
|
|
|
|
assert(args.n > 0, "need at least one widget to add")
|
|
|
|
for i=1, args.n do
|
2018-12-27 05:54:10 +01:00
|
|
|
local w = base.make_widget_from_value(args[i])
|
|
|
|
base.check_widget(w)
|
|
|
|
table.insert(self._private.widgets, w)
|
2015-09-28 21:00:49 +02:00
|
|
|
end
|
2015-06-14 16:12:44 +02:00
|
|
|
self:emit_signal("widget::layout_changed")
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2016-01-18 05:23:50 +01:00
|
|
|
|
2019-11-29 07:22:50 +01:00
|
|
|
--- Remove a widget from the layout.
|
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @method remove
|
2016-01-18 05:23:50 +01:00
|
|
|
-- @tparam number index The widget index to remove
|
|
|
|
-- @treturn boolean index If the operation is successful
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @interface layout
|
2016-01-18 05:23:50 +01:00
|
|
|
function fixed:remove(index)
|
2016-05-27 01:41:58 +02:00
|
|
|
if not index or index < 1 or index > #self._private.widgets then return false end
|
2016-01-18 05:23:50 +01:00
|
|
|
|
2016-05-27 01:41:58 +02:00
|
|
|
table.remove(self._private.widgets, index)
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
self:emit_signal("widget::layout_changed")
|
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2019-11-29 07:22:50 +01:00
|
|
|
--- Remove one or more widgets from the layout.
|
|
|
|
--
|
2016-01-18 05:23:50 +01:00
|
|
|
-- The last parameter can be a boolean, forcing a recursive seach of the
|
|
|
|
-- widget(s) to remove.
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @method remove_widgets
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @tparam widget ... Widgets that should be removed (must at least be one)
|
2016-01-18 05:23:50 +01:00
|
|
|
-- @treturn boolean If the operation is successful
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @interface layout
|
2016-01-18 05:23:50 +01:00
|
|
|
function fixed:remove_widgets(...)
|
|
|
|
local args = { ... }
|
|
|
|
|
|
|
|
local recursive = type(args[#args]) == "boolean" and args[#args]
|
|
|
|
|
|
|
|
local ret = true
|
|
|
|
for k, rem_widget in ipairs(args) do
|
|
|
|
if recursive and k == #args then break end
|
|
|
|
|
|
|
|
local idx, l = self:index(rem_widget, recursive)
|
|
|
|
|
|
|
|
if idx and l and l.remove then
|
|
|
|
l:remove(idx, false)
|
|
|
|
else
|
|
|
|
ret = false
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
return #args > (recursive and 1 or 0) and ret
|
|
|
|
end
|
|
|
|
|
|
|
|
function fixed:get_children()
|
2016-05-27 01:41:58 +02:00
|
|
|
return self._private.widgets
|
2016-01-18 05:23:50 +01:00
|
|
|
end
|
|
|
|
|
2016-02-04 07:11:10 +01:00
|
|
|
function fixed:set_children(children)
|
2016-02-27 13:55:34 +01:00
|
|
|
self:reset()
|
|
|
|
if #children > 0 then
|
|
|
|
self:add(unpack(children))
|
|
|
|
end
|
2016-02-04 07:11:10 +01:00
|
|
|
end
|
|
|
|
|
2019-11-29 07:22:50 +01:00
|
|
|
--- Replace the first instance of `widget` in the layout with `widget2`.
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @method replace_widget
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @tparam widget widget The widget to replace
|
|
|
|
-- @tparam widget widget2 The widget to replace `widget` with
|
2016-01-18 05:23:50 +01:00
|
|
|
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
|
|
|
|
-- @treturn boolean If the operation is successful
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @interface layout
|
2016-01-18 05:23:50 +01:00
|
|
|
function fixed:replace_widget(widget, widget2, recursive)
|
|
|
|
local idx, l = self:index(widget, recursive)
|
|
|
|
|
|
|
|
if idx and l then
|
|
|
|
l:set(idx, widget2)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function fixed:swap(index1, index2)
|
2016-05-27 01:41:58 +02:00
|
|
|
if not index1 or not index2 or index1 > #self._private.widgets
|
|
|
|
or index2 > #self._private.widgets then
|
2016-01-18 05:23:50 +01:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2016-05-27 01:41:58 +02:00
|
|
|
local widget1, widget2 = self._private.widgets[index1], self._private.widgets[index2]
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
self:set(index1, widget2)
|
|
|
|
self:set(index2, widget1)
|
|
|
|
|
2016-08-08 08:39:43 +02:00
|
|
|
self:emit_signal("widget::swapped", widget1, widget2, index2, index1)
|
|
|
|
|
2016-01-18 05:23:50 +01:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function fixed:swap_widgets(widget1, widget2, recursive)
|
|
|
|
base.check_widget(widget1)
|
|
|
|
base.check_widget(widget2)
|
|
|
|
|
|
|
|
local idx1, l1 = self:index(widget1, recursive)
|
|
|
|
local idx2, l2 = self:index(widget2, recursive)
|
|
|
|
|
2016-03-04 06:24:38 +01:00
|
|
|
if idx1 and l1 and idx2 and l2 and (l1.set or l1.set_widget) and (l2.set or l2.set_widget) then
|
|
|
|
if l1.set then
|
|
|
|
l1:set(idx1, widget2)
|
2016-08-08 08:39:43 +02:00
|
|
|
if l1 == self then
|
|
|
|
self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1)
|
|
|
|
end
|
2016-03-04 06:24:38 +01:00
|
|
|
elseif l1.set_widget then
|
|
|
|
l1:set_widget(widget2)
|
|
|
|
end
|
|
|
|
if l2.set then
|
|
|
|
l2:set(idx2, widget1)
|
2016-08-08 08:39:43 +02:00
|
|
|
if l2 == self then
|
|
|
|
self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1)
|
|
|
|
end
|
2016-03-04 06:24:38 +01:00
|
|
|
elseif l2.set_widget then
|
|
|
|
l2:set_widget(widget1)
|
|
|
|
end
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function fixed:set(index, widget2)
|
2016-05-27 01:41:58 +02:00
|
|
|
if (not widget2) or (not self._private.widgets[index]) then return false end
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
base.check_widget(widget2)
|
|
|
|
|
2016-08-08 08:39:43 +02:00
|
|
|
local w = self._private.widgets[index]
|
|
|
|
|
2016-05-27 01:41:58 +02:00
|
|
|
self._private.widgets[index] = widget2
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
self:emit_signal("widget::layout_changed")
|
2016-08-08 08:39:43 +02:00
|
|
|
self:emit_signal("widget::replaced", widget2, w, index)
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2021-07-13 22:45:15 +02:00
|
|
|
--- A widget to insert as a separator between child widgets.
|
2017-08-07 22:12:29 +02:00
|
|
|
--
|
2021-07-13 22:45:15 +02:00
|
|
|
-- If this property is a valid widget and `spacing` is greater than `0`, a
|
|
|
|
-- copy of this widget is inserted between each child widget, with its size in
|
|
|
|
-- the layout's main direction determined by `spacing`.
|
|
|
|
--
|
|
|
|
-- By default no widget is used and any `spacing` is applied as an empty offset.
|
2017-08-07 22:12:29 +02:00
|
|
|
--
|
|
|
|
--@DOC_wibox_layout_fixed_spacing_widget_EXAMPLE@
|
|
|
|
--
|
|
|
|
-- @property spacing_widget
|
2022-08-22 08:02:26 +02:00
|
|
|
-- @tparam[opt=nil] widget|nil spacing_widget
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @propemits true false
|
|
|
|
-- @interface layout
|
2017-08-07 22:12:29 +02:00
|
|
|
|
|
|
|
function fixed:set_spacing_widget(wdg)
|
|
|
|
self._private.spacing_widget = base.make_widget_from_value(wdg)
|
|
|
|
self:emit_signal("widget::layout_changed")
|
2019-11-29 07:22:50 +01:00
|
|
|
self:emit_signal("property::spacing_widget", wdg)
|
2017-08-07 22:12:29 +02:00
|
|
|
end
|
|
|
|
|
2019-06-06 22:32:53 +02:00
|
|
|
--- Insert a new widget in the layout at position `index`.
|
2019-11-29 07:22:50 +01:00
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @method insert
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @tparam number index The position.
|
|
|
|
-- @tparam widget widget The widget.
|
|
|
|
-- @treturn boolean If the operation is successful.
|
|
|
|
-- @emits widget::inserted
|
|
|
|
-- @emitstparam widget::inserted widget self The fixed layout.
|
|
|
|
-- @emitstparam widget::inserted widget widget index The inserted widget.
|
|
|
|
-- @emitstparam widget::inserted number count The widget count.
|
|
|
|
-- @interface layout
|
2016-01-18 05:23:50 +01:00
|
|
|
function fixed:insert(index, widget)
|
2016-05-27 01:41:58 +02:00
|
|
|
if not index or index < 1 or index > #self._private.widgets + 1 then return false end
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
base.check_widget(widget)
|
2016-05-27 01:41:58 +02:00
|
|
|
table.insert(self._private.widgets, index, widget)
|
2016-01-18 05:23:50 +01:00
|
|
|
self:emit_signal("widget::layout_changed")
|
2016-08-08 08:39:43 +02:00
|
|
|
self:emit_signal("widget::inserted", widget, #self._private.widgets)
|
2016-01-18 05:23:50 +01:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2019-06-06 22:32:53 +02:00
|
|
|
-- Fit the fixed layout into the given space.
|
2015-08-08 13:43:35 +02:00
|
|
|
-- @param context The context in which we are fit.
|
2010-10-06 12:42:56 +02:00
|
|
|
-- @param orig_width The available width.
|
|
|
|
-- @param orig_height The available height.
|
2015-08-08 13:43:35 +02:00
|
|
|
function fixed:fit(context, orig_width, orig_height)
|
2021-01-01 20:05:39 +01:00
|
|
|
local width_left, height_left = orig_width, orig_height
|
|
|
|
local spacing = self._private.spacing or 0
|
2021-01-01 18:07:33 +01:00
|
|
|
local widgets_nr = #self._private.widgets
|
2021-01-01 20:05:39 +01:00
|
|
|
local is_y = self._private.dir == "y"
|
|
|
|
local used_max = 0
|
|
|
|
|
|
|
|
-- when no widgets exist the function can be called with orig_width or
|
|
|
|
-- orig_height equal to nil. Exit early in this case.
|
2021-01-01 18:07:33 +01:00
|
|
|
if widgets_nr == 0 then
|
2021-01-01 20:05:39 +01:00
|
|
|
return 0, 0
|
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2021-01-01 18:07:33 +01:00
|
|
|
for k, v in pairs(self._private.widgets) do
|
2021-01-01 20:05:39 +01:00
|
|
|
local w, h = base.fit_widget(self, context, v, width_left, height_left)
|
|
|
|
local max
|
|
|
|
|
|
|
|
if is_y then
|
|
|
|
max = w
|
|
|
|
height_left = height_left - h
|
2010-10-06 12:42:56 +02:00
|
|
|
else
|
2021-01-01 20:05:39 +01:00
|
|
|
max = h
|
|
|
|
width_left = width_left - w
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
2021-01-01 20:05:39 +01:00
|
|
|
|
2010-10-06 12:42:56 +02:00
|
|
|
if max > used_max then
|
|
|
|
used_max = max
|
|
|
|
end
|
|
|
|
|
2021-01-01 18:07:33 +01:00
|
|
|
if k < widgets_nr then
|
|
|
|
if is_y then
|
|
|
|
height_left = height_left - spacing
|
2010-10-06 12:42:56 +02:00
|
|
|
else
|
2021-01-01 18:07:33 +01:00
|
|
|
width_left = width_left - spacing
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-01 20:05:39 +01:00
|
|
|
if width_left <= 0 or height_left <= 0 then
|
2021-01-01 18:07:33 +01:00
|
|
|
-- this complicated two lines determine whether we're out-of-space
|
|
|
|
-- because of spacing, or if the last widget doesn't fit in
|
2021-01-01 20:05:39 +01:00
|
|
|
if is_y then
|
2021-01-01 18:07:33 +01:00
|
|
|
height_left = k < widgets_nr and height_left + spacing or height_left
|
|
|
|
height_left = height_left < 0 and 0 or height_left
|
2010-10-06 12:42:56 +02:00
|
|
|
else
|
2021-01-01 18:07:33 +01:00
|
|
|
width_left = k < widgets_nr and width_left + spacing or width_left
|
|
|
|
width_left = width_left < 0 and 0 or width_left
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-01 20:05:39 +01:00
|
|
|
if is_y then
|
2021-01-01 18:07:33 +01:00
|
|
|
return used_max, orig_height - height_left
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
2021-01-01 20:05:39 +01:00
|
|
|
|
2021-01-01 18:07:33 +01:00
|
|
|
return orig_width - width_left, used_max
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2012-11-18 20:44:03 +01:00
|
|
|
function fixed:reset()
|
2016-05-27 01:41:58 +02:00
|
|
|
self._private.widgets = {}
|
2015-06-14 16:12:44 +02:00
|
|
|
self:emit_signal("widget::layout_changed")
|
2016-08-08 08:39:43 +02:00
|
|
|
self:emit_signal("widget::reseted")
|
2019-11-29 07:22:50 +01:00
|
|
|
self:emit_signal("widget::reset")
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
--- Set the layout's fill_space property. If this property is true, the last
|
|
|
|
-- widget will get all the space that is left. If this is false, the last widget
|
|
|
|
-- won't be handled specially and there can be space left unused.
|
2016-05-27 01:41:58 +02:00
|
|
|
-- @property fill_space
|
2022-08-22 08:02:26 +02:00
|
|
|
-- @tparam[opt=false] boolean fill_space
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @propemits true false
|
2016-05-27 01:41:58 +02:00
|
|
|
|
2012-11-18 20:44:03 +01:00
|
|
|
function fixed:fill_space(val)
|
2016-05-27 01:41:58 +02:00
|
|
|
if self._private.fill_space ~= val then
|
|
|
|
self._private.fill_space = not not val
|
2015-06-21 14:58:13 +02:00
|
|
|
self:emit_signal("widget::layout_changed")
|
2019-11-29 07:22:50 +01:00
|
|
|
self:emit_signal("property::fill_space", val)
|
2015-06-21 14:58:13 +02:00
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2015-09-28 21:00:49 +02:00
|
|
|
local function get_layout(dir, widget1, ...)
|
2016-05-27 01:41:58 +02:00
|
|
|
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
2013-01-05 16:12:47 +01:00
|
|
|
|
2017-03-08 21:18:33 +01:00
|
|
|
gtable.crush(ret, fixed, true)
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2016-05-27 01:41:58 +02:00
|
|
|
ret._private.dir = dir
|
|
|
|
ret._private.widgets = {}
|
2015-06-21 14:58:13 +02:00
|
|
|
ret:set_spacing(0)
|
|
|
|
ret:fill_space(false)
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2015-09-28 21:00:49 +02:00
|
|
|
if widget1 then
|
|
|
|
ret:add(widget1, ...)
|
|
|
|
end
|
|
|
|
|
2010-10-06 12:42:56 +02:00
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
2021-07-13 22:44:50 +02:00
|
|
|
--- Creates and returns a new horizontal fixed layout.
|
|
|
|
--
|
2015-09-28 21:00:49 +02:00
|
|
|
-- @tparam widget ... Widgets that should be added to the layout.
|
2019-06-07 20:59:34 +02:00
|
|
|
-- @constructorfct wibox.layout.fixed.horizontal
|
2015-09-28 21:00:49 +02:00
|
|
|
function fixed.horizontal(...)
|
|
|
|
return get_layout("x", ...)
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2021-07-13 22:44:50 +02:00
|
|
|
--- Creates and returns a new vertical fixed layout.
|
|
|
|
--
|
2015-09-28 21:00:49 +02:00
|
|
|
-- @tparam widget ... Widgets that should be added to the layout.
|
2019-06-07 20:59:34 +02:00
|
|
|
-- @constructorfct wibox.layout.fixed.vertical
|
2015-09-28 21:00:49 +02:00
|
|
|
function fixed.vertical(...)
|
|
|
|
return get_layout("y", ...)
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2021-07-13 22:45:15 +02:00
|
|
|
--- The amount of space inserted between the child widgets.
|
|
|
|
--
|
|
|
|
-- If a `spacing_widget` is defined, this value is used for its size.
|
2017-08-07 22:12:29 +02:00
|
|
|
--
|
|
|
|
--@DOC_wibox_layout_fixed_spacing_EXAMPLE@
|
|
|
|
--
|
2016-05-27 01:41:58 +02:00
|
|
|
-- @property spacing
|
2022-08-22 08:02:26 +02:00
|
|
|
-- @tparam[opt=0] number spacing Spacing between widgets.
|
|
|
|
-- @negativeallowed true
|
2019-11-29 07:22:50 +01:00
|
|
|
-- @propemits true false
|
|
|
|
-- @interface layout
|
2016-05-27 01:41:58 +02:00
|
|
|
|
2014-10-18 07:17:46 +02:00
|
|
|
function fixed:set_spacing(spacing)
|
2016-05-27 01:41:58 +02:00
|
|
|
if self._private.spacing ~= spacing then
|
|
|
|
self._private.spacing = spacing
|
2015-06-21 14:58:13 +02:00
|
|
|
self:emit_signal("widget::layout_changed")
|
2019-11-29 07:22:50 +01:00
|
|
|
self:emit_signal("property::spacing", spacing)
|
2015-06-21 14:58:13 +02:00
|
|
|
end
|
2014-10-18 07:17:46 +02:00
|
|
|
end
|
|
|
|
|
2016-05-27 01:41:58 +02:00
|
|
|
function fixed:get_spacing()
|
|
|
|
return self._private.spacing or 0
|
|
|
|
end
|
|
|
|
|
2017-10-21 01:54:36 +02:00
|
|
|
--@DOC_fixed_COMMON@
|
|
|
|
|
2012-06-12 15:29:52 +02:00
|
|
|
return fixed
|
|
|
|
|
2011-09-11 16:50:01 +02:00
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|