Merge pull request #630 from Elv13/upstream_dynamic_p5

Multiple `wibox.layout` enhancements
This commit is contained in:
Emmanuel Lepage Vallée 2016-02-04 03:09:38 -05:00
commit 19437930a2
11 changed files with 369 additions and 56 deletions

View File

@ -399,6 +399,45 @@ function util.table.join(...)
return ret
end
--- Override elements in the first table by the one in the second
-- @tparam table t the table to be overriden
-- @tparam table set the table used to override members of `t`
-- @treturn table t (for convenience)
function util.table.crush(t, set)
for k, v in pairs(set) do
t[k] = v
end
return t
end
--- Pack all elements with an integer key into a new table
-- While both lua and luajit implement __len over sparse
-- table, the standard define it as an implementation
-- detail.
--
-- This function remove any non numeric keys from the value set
--
-- @tparam table t A potentially sparse table
-- @treturn table A packed table with all numeric keys
function util.table.from_sparse(t)
local keys= {}
for k,v in pairs(t) do
if type(k) == "number" then
keys[#keys+1] = k
end
end
table.sort(keys)
local ret = {}
for _,v in ipairs(keys) do
ret[#ret+1] = t[v]
end
return ret
end
--- Check if a table has an item and return its key.
-- @param t The table.
-- @param item The item to look for in values of the table.
@ -532,10 +571,12 @@ end
--- Merge items from the one table to another one
-- @tparam table t the container table
-- @tparam table set the mixin table
-- @treturn table Return `t` for convenience
function util.table.merge(t, set)
for _, v in ipairs(set) do
table.insert(t, v)
end
return t
end

View File

@ -10,6 +10,7 @@ local table = table
local pairs = pairs
local type = type
local floor = math.floor
local util = require("awful.util")
local base = require("wibox.widget.base")
local align = {}
@ -164,6 +165,12 @@ function align:set_third(widget)
self:emit_signal("widget::layout_changed")
end
--- Get all children of this layout
-- @treturn table a list of all widgets
function align:get_children()
return util.from_sparse {self.first, self.second, self.third}
end
--- Fit the align layout into the given space. The align 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.

View File

@ -44,6 +44,12 @@ function constraint:set_widget(widget)
self:emit_signal("widget::layout_changed")
end
--- Get the number of children element
-- @treturn table The children
function constraint:get_children()
return {self.widget}
end
--- Set the strategy to use for the constraining. Valid values are 'max',
-- 'min' or 'exact'. Throws an error on invalid values.
function constraint:set_strategy(val)

View File

@ -5,9 +5,10 @@
-- @classmod wibox.layout.fixed
---------------------------------------------------------------------------
local base = require("wibox.widget.base")
local base = require("wibox.widget.base")
local table = table
local pairs = pairs
local util = require("awful.util")
local fixed = {}
@ -50,7 +51,7 @@ function fixed:layout(context, width, height)
end
--- Add some widgets to the given fixed layout
-- @tparam widget ... Widgets that should be added (must at least be one)
-- @param ... Widgets that should be added (must at least be one)
function fixed:add(...)
-- No table.pack in Lua 5.1 :-(
local args = { n=select('#', ...), ... }
@ -62,6 +63,140 @@ function fixed:add(...)
self:emit_signal("widget::layout_changed")
end
--- Remove a widget from the layout
-- @tparam number index The widget index to remove
-- @treturn boolean index If the operation is successful
function fixed:remove(index)
if not index or index < 1 or index > #self.widgets then return false end
table.remove(self.widgets, index)
self:emit_signal("widget::layout_changed")
return true
end
--- Remove one or more widgets from the layout
-- The last parameter can be a boolean, forcing a recursive seach of the
-- widget(s) to remove.
-- @param widget ... Widgets that should be removed (must at least be one)
-- @treturn boolean If the operation is successful
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
--- Get all children of this layout
-- @treturn table a list of all widgets
function fixed:get_children()
return self.widgets
end
--- Replace the first instance of `widget` in the layout with `widget2`
-- @param widget The widget to replace
-- @param widget2 The widget to replace `widget` with
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
-- @treturn boolean If the operation is successful
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
--- Swap 2 widgets in a layout
-- @tparam number index1 The first widget index
-- @tparam number index2 The second widget index
-- @treturn boolean If the operation is successful
function fixed:swap(index1, index2)
if not index1 or not index2 or index1 > #self.widgets
or index2 > #self.widgets then
return false
end
local widget1, widget2 = self.widgets[index1], self.widgets[index2]
self:set(index1, widget2)
self:set(index2, widget1)
return true
end
--- Swap 2 widgets in a layout
-- If widget1 is present multiple time, only the first instance is swapped
-- @param widget1 The first widget
-- @param widget2 The second widget
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
-- @treturn boolean If the operation is successful
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)
if idx1 and l1 and idx2 and l2 then
l1:set(idx1, widget2)
l2:set(idx2, widget1)
return true
end
return false
end
--- Set a widget at a specific index, replace the current one
-- @tparam number index A widget or a widget index
-- @param widget2 The widget to take the place of the first one
-- @treturn boolean If the operation is successful
function fixed:set(index, widget2)
if (not widget2) or (not self.widgets[index]) then return false end
base.check_widget(widget2)
self.widgets[index] = widget2
self:emit_signal("widget::layout_changed")
return true
end
--- Insert a new widget in the layout at position `index`
-- @tparam number index The position
-- @param widget The widget
-- @treturn boolean If the operation is successful
function fixed:insert(index, widget)
if not index or index < 1 or index > #self.widgets + 1 then return false end
base.check_widget(widget)
table.insert(self.widgets, index, widget)
self:emit_signal("widget::layout_changed")
return true
end
--- Fit the fixed layout into the given space
-- @param context The context in which we are fit.
-- @param orig_width The available width.
@ -122,11 +257,7 @@ end
local function get_layout(dir, widget1, ...)
local ret = base.make_widget()
for k, v in pairs(fixed) do
if type(v) == "function" then
ret[k] = v
end
end
util.table.crush(ret, fixed)
ret.dir = dir
ret.widgets = {}

View File

@ -6,16 +6,101 @@
---------------------------------------------------------------------------
local base = require("wibox.widget.base")
local fixed = require("wibox.layout.fixed")
local table = table
local pairs = pairs
local floor = math.floor
local round = require("awful.util").round
local util = require("awful.util")
local flex = {}
local function round(x)
return floor(x + 0.5)
end
--- Layout a fixed layout. Each widget gets just the space it asks for.
-- @param layout The layout you are modifying.
-- @param context The context in which we are drawn.
-- @param width The available width.
-- @param height The available height.
-- @name layout
-- @class function
--- Get all children of this layout
-- @param layout The layout you are modifying.
-- @warning If the widget contain itself and recursive is true, this will cause
-- a stack overflow
-- @param[opt] recursive Also add all widgets of childrens
-- @return a list of all widgets
-- @name get_children
-- @class function
--- Add some widgets to the given fixed layout
-- @param layout The layout you are modifying.
-- @tparam widget ... Widgets that should be added (must at least be one)
-- @name add
-- @class function
--- Set a widget at a specific index, replace the current one
-- @tparam number index A widget or a widget index
-- @param widget2 The widget to take the place of the first one
-- @treturn boolean If the operation is successful
-- @name set
-- @class function
--- Remove a widget from the layout
-- @tparam index The widget index to remove
-- @treturn boolean index If the operation is successful
-- @name remove
-- @class function
--- Remove one or more widgets from the layout
-- The last parameter can be a boolean, forcing a recursive seach of the
-- widget(s) to remove.
-- @param widget ... Widgets that should be removed (must at least be one)
-- @treturn boolean If the operation is successful
-- @name remove_widgets
-- @class function
--- Fit the fixed layout into the given space
-- @param layout The layout you are modifying.
-- @param context The context in which we are fit.
-- @param orig_width The available width.
-- @param orig_height The available height.
-- @name fit
-- @class function
--- Reset a fixed layout. This removes all widgets from the layout.
-- @param layout The layout you are modifying.
-- @name reset
-- @class function
--- Replace the first instance of `widget` in the layout with `widget2`
-- @param widget The widget to replace
-- @param widget2 The widget to replace `widget` with
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
-- @treturn boolean If the operation is successful
-- @name replace_widget
-- @class function
--- Swap 2 widgets in a layout
-- @tparam number index1 The first widget index
-- @tparam number index2 The second widget index
-- @treturn boolean If the operation is successful
-- @name swap
-- @class function
--- Swap 2 widgets in a layout
-- If widget1 is present multiple time, only the first instance is swapped
-- @param widget1 The first widget
-- @param widget2 The second widget
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
-- @treturn boolean If the operation is successful
-- @name swap_widgets
-- @class function
--- Insert a new widget in the layout at position `index`
-- @tparam number index The position
-- @param widget The widget
-- @treturn boolean If the operation is successful
-- @name insert
-- @class function
--- Layout a flex layout. Each widget gets an equal share of the available space.
-- @param context The context in which we are drawn.
@ -41,12 +126,13 @@ function flex:layout(context, width, height)
for k, v in pairs(self.widgets) do
local x, y, w, h
if self.dir == "y" then
x, y = 0, round(pos)
x, y = 0, util.round(pos)
w, h = width, floor(space_per_item)
else
x, y = round(pos), 0
x, y = util.round(pos), 0
w, h = floor(space_per_item), height
end
table.insert(result, base.place_widget_at(v, x, y, w, h))
pos = pos + space_per_item + spacing
@ -96,19 +182,6 @@ function flex:fit(context, orig_width, orig_height)
return used_in_dir + spacing, used_in_other
end
--- Add some widgets to the given flex layout
-- @tparam widget ... Widgets that should be added (must at least be one)
function flex: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
base.check_widget(args[i])
table.insert(self.widgets, args[i])
end
self:emit_signal("widget::layout_changed")
end
--- Set the maximum size the widgets in this layout will take (that is,
-- maximum width for horizontal and maximum height for vertical).
-- @param val The maximum size of the widget.
@ -119,37 +192,12 @@ function flex:set_max_widget_size(val)
end
end
--- Add spacing between each layout widgets
-- @param spacing Spacing between widgets.
function flex:set_spacing(spacing)
if self._spacing ~= spacing then
self._spacing = spacing
self:emit_signal("widget::layout_changed")
end
end
function flex:reset()
self.widgets = {}
self._max_widget_size = nil
self:emit_signal("widget::layout_changed")
end
local function get_layout(dir, widget1, ...)
local ret = base.make_widget()
local ret = fixed[dir](widget1, ...)
for k, v in pairs(flex) do
if type(v) == "function" then
ret[k] = v
end
end
util.table.crush(ret, flex)
ret.dir = dir
ret.widgets = {}
ret:set_spacing(0)
if widget1 then
ret:add(widget1, ...)
end
ret.fill_space = nil
return ret
end
@ -158,14 +206,14 @@ end
-- equally among all widgets. Widgets can be added via :add(widget).
-- @tparam widget ... Widgets that should be added to the layout.
function flex.horizontal(...)
return get_layout("x", ...)
return get_layout("horizontal", ...)
end
--- Returns a new vertical flex layout. A flex layout shares the available space
-- equally among all widgets. Widgets can be added via :add(widget).
-- @tparam widget ... Widgets that should be added to the layout.
function flex.vertical(...)
return get_layout("y", ...)
return get_layout("vertical", ...)
end
return flex

View File

@ -72,6 +72,12 @@ function margin:set_widget(widget)
self:emit_signal("widget::layout_changed")
end
--- Get the number of children element
-- @treturn table The children
function margin:get_children()
return {self.widget}
end
--- Set all the margins to val.
function margin:set_margins(val)
self.left = val

View File

@ -58,6 +58,12 @@ function mirror:set_widget(widget)
self:emit_signal("widget::layout_changed")
end
--- Get the number of children element
-- @treturn table The children
function mirror:get_children()
return {self.widget}
end
--- Reset this layout. The widget will be removed and the axes reset.
function mirror:reset()
self.horizontal = false

View File

@ -66,6 +66,12 @@ function rotate:set_widget(widget)
self:emit_signal("widget::layout_changed")
end
--- Get the number of children element
-- @treturn table The children
function rotate:get_children()
return {self.widget}
end
--- Reset this layout. The widget will be removed and the rotation reset.
function rotate:reset()
self.direction = nil

View File

@ -261,6 +261,12 @@ function scroll:set_widget(widget)
self:emit_signal("widget::redraw_needed")
end
--- Get the number of children element
-- @treturn table The children
function scroll:get_children()
return {self.widget}
end
--- Specify the expand mode that is used for extra space.
-- @tparam boolean expand If true, the widget is expanded to include the extra
-- space. If false, the extra space is simply left empty.

View File

@ -69,6 +69,12 @@ function background:set_widget(widget)
self:emit_signal("widget::layout_changed")
end
--- Get the number of children element
-- @treturn table The children
function background:get_children()
return {self.widget}
end
--- Set the background to use
function background:set_bg(bg)
if bg then

View File

@ -73,6 +73,56 @@ function base.widget:set_height(s)
end
end
--- Get all direct children widgets
-- This method should be re-implemented by the relevant widgets
-- @treturn table The children
function base.widget:get_children()
return {}
end
-- It could have been merged into `get_all_children`, but it's not necessary
local function digg_children(ret, tlw)
for k, w in ipairs(tlw:get_children()) do
table.insert(ret, w)
digg_children(ret, w)
end
end
--- Get all direct and indirect children widgets
-- This will scan all containers recursively to find widgets
-- Warning: This method it prone to stack overflow id the widget, or any of its
-- children, contain (directly or indirectly) itself.
-- @treturn table The children
function base.widget:get_all_children()
local ret = {}
digg_children(ret, self)
return ret
end
--- Get a widex index
-- @param widget The widget to look for
-- @param[opt] recursive Also check sub-widgets
-- @param[opt] ... Aditional widgets to add at the end of the "path"
-- @return The index
-- @return The parent layout
-- @return The path between "self" and "widget"
function base.widget:index(widget, recursive, ...)
local widgets = self:get_children()
for idx, w in ipairs(widgets) do
if w == widget then
return idx, self, {...}
elseif recursive then
local idx, l, path = w:index(widget, true, self, ...)
if idx and l then
return idx, l, path
end
end
end
return nil, self, {}
end
-- }}}
-- {{{ Caches