Merge pull request #1031 from Elv13/add_recursive_signal

Add recursive signal for widgets trees.
This commit is contained in:
Emmanuel Lepage Vallée 2016-08-20 16:01:54 -04:00 committed by GitHub
commit 76d0c458b0
8 changed files with 107 additions and 4 deletions

View file

@ -1,11 +1,15 @@
--- Set a widget at a specific index, replace the current one
--- Set a widget at a specific index, replace the current one.
-- **Signal:** widget::replaced The argument is the new widget and the old one
-- and the index.
-- @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
--- Replace the first instance of `widget` in the layout with `widget2`
--- Replace the first instance of `widget` in the layout with `widget2`.
-- **Signal:** widget::replaced The argument is the new widget and the old one
-- and the index.
-- @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.
@ -13,15 +17,18 @@
-- @name replace_widget
-- @class function
--- Swap 2 widgets in a layout
--- Swap 2 widgets in a layout.
-- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes.
-- @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
--- Swap 2 widgets in a layout.
-- If widget1 is present multiple time, only the first instance is swapped
-- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes.
-- if the layouts not the same, then only `widget::replaced` will be emitted.
-- @param widget1 The first widget
-- @param widget2 The second widget
-- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget.
@ -34,6 +41,7 @@
-- @property children
--- Reset a ratio layout. This removes all widgets from the layout.
-- **Signal:** widget::reset
-- @param layout The layout you are modifying.
-- @name reset
-- @class function

View file

@ -40,6 +40,12 @@
-- @param _buttons The table of buttons that should bind to the widget.
-- @function buttons
--- Emit a signal and ensure all parent widgets in the hierarchies also
-- forward the signal. This is useful to track signals when there is a dynamic
-- set of containers and layouts wrapping the widget.
-- @tparam string signal_name
-- @param ... Other arguments
-- @function emit_signal_recursive
--- When the layout (size) change.
-- This signal is emited when the previous results of `:layout()` and `:fit()`

View file

@ -1,4 +1,12 @@
---------------------------------------------------------------------------
-- A simple button widget.
-- @usage local button = awful.widget.button()
-- button:buttons(awful.util.table.join(
-- button:buttons(),
-- awful.button({}, 1, nil, function ()
-- print("Mouse was clicked")
-- end)
-- ))
-- @author Julien Danjou <julien@danjou.info>
-- @copyright 2008-2009 Julien Danjou
-- @release @AWESOME_VERSION@
@ -49,6 +57,10 @@ function button.mt:__call(...)
return button.new(...)
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return setmetatable(button, button.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View file

@ -51,6 +51,16 @@ local function hierarchy_new(redraw_callback, layout_callback, callback_arg)
end
layout_callback(result, callback_arg)
end
function result._emit_recursive(widget, name, ...)
local cur = result
assert(widget == cur._widget)
while cur do
if cur._widget then
cur._widget:emit_signal(name, ...)
end
cur = cur._parent
end
end
for k, f in pairs(hierarchy) do
if type(f) == "function" then
@ -86,6 +96,7 @@ function hierarchy_update(self, context, widget, width, height, region, matrix_t
if old_widget and old_widget ~= widget then
self._widget:disconnect_signal("widget::redraw_needed", self._redraw)
self._widget:disconnect_signal("widget::layout_changed", self._layout)
self._widget:disconnect_signal("widget::emit_recursive", self._emit_recursive)
end
-- Save the arguments we need to save
@ -99,6 +110,7 @@ function hierarchy_update(self, context, widget, width, height, region, matrix_t
if old_widget ~= widget then
widget:weak_connect_signal("widget::redraw_needed", self._redraw)
widget:weak_connect_signal("widget::layout_changed", self._layout)
widget:weak_connect_signal("widget::emit_recursive", self._emit_recursive)
end
-- Update children

View file

@ -144,6 +144,8 @@ function fixed:swap(index1, index2)
self:set(index1, widget2)
self:set(index2, widget1)
self:emit_signal("widget::swapped", widget1, widget2, index2, index1)
return true
end
@ -157,11 +159,17 @@ function fixed:swap_widgets(widget1, widget2, recursive)
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)
if l1 == self then
self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1)
end
elseif l1.set_widget then
l1:set_widget(widget2)
end
if l2.set then
l2:set(idx2, widget1)
if l2 == self then
self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1)
end
elseif l2.set_widget then
l2:set_widget(widget1)
end
@ -177,14 +185,18 @@ function fixed:set(index, widget2)
base.check_widget(widget2)
local w = self._private.widgets[index]
self._private.widgets[index] = widget2
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::replaced", widget2, w, index)
return true
end
--- Insert a new widget in the layout at position `index`
-- **Signal:** widget::inserted The arguments are the widget and the index
-- @tparam number index The position
-- @param widget The widget
-- @treturn boolean If the operation is successful
@ -194,6 +206,7 @@ function fixed:insert(index, widget)
base.check_widget(widget)
table.insert(self._private.widgets, index, widget)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::inserted", widget, #self._private.widgets)
return true
end
@ -242,6 +255,7 @@ end
function fixed:reset()
self._private.widgets = {}
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::reseted")
end
--- Set the layout's fill_space property. If this property is true, the last

View file

@ -238,6 +238,7 @@ function ratio:ajust_widget_ratio(widget, before, itself, after)
end
--- Add some widgets to the given fixed layout
-- **Signal:** widget::added The argument are the widgets
-- @tparam widget ... Widgets that should be added (must at least be one)
function ratio:add(...)
-- No table.pack in Lua 5.1 :-(
@ -250,25 +251,31 @@ function ratio:add(...)
normalize(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::added", ...)
end
--- Remove a widget from the layout
-- **Signal:** widget::removed The arguments are the widget and the index
-- @tparam number index The widget index to remove
-- @treturn boolean index If the operation is successful
function ratio:remove(index)
if not index or not self._private.widgets[index] then return false end
local w = self._private.widgets[index]
table.remove(self._private.ratios, index)
table.remove(self._private.widgets, index)
normalize(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::removed", w, index)
return true
end
--- Insert a new widget in the layout at position `index`
-- **Signal:** widget::inserted The arguments are the widget and the index
-- @tparam number index The position
-- @param widget The widget
function ratio:insert(index, widget)
@ -281,6 +288,7 @@ function ratio:insert(index, widget)
normalize(self)
self:emit_signal("widget::layout_changed")
self:emit_signal("widget::inserted", widget, #self._private.widgets)
end
local function get_layout(dir, widget1, ...)

View file

@ -153,6 +153,27 @@ function base.widget:get_all_children()
return ret
end
--- Emit a signal and ensure all parent widgets in the hierarchies also
-- forward the signal. This is useful to track signals when there is a dynamic
-- set of containers and layouts wrapping the widget.
--
-- Note that this function has two flaws. First of all, the signal are only
-- forwarded once the widget tree has been built. This happens after all
-- currently scheduled functions have been executed. Therefor, it wont start
-- to work right away. In case the widget is present multiple time in a single
-- widget tree, this function will also forward the signal multiple time (one
-- per upward tree path).
--
-- @tparam string signal_name
-- @param ... Other arguments
-- @function emit_signal_recursive
function base.widget:emit_signal_recursive(signal_name, ...)
-- This is a convenience wrapper, the real implementation is in the
-- hierarchy.
self:emit_signal("widget::emit_recursive", signal_name, ...)
end
--- Get a widex index.
-- @param widget The widget to look for
-- @param[opt] recursive Also check sub-widgets

View file

@ -9,6 +9,10 @@ local w
local img
local button
-- Also check recursive signals from events
local layout
local got_called = false
-- create a wibox.
table.insert(steps, function()
@ -55,6 +59,21 @@ table.insert(steps, function()
img = button._private.image
assert(img)
-- Test the click
layout = w.widget
assert(layout)
button:buttons(awful.util.table.join(
button:buttons(),
awful.button({}, 1, nil, function ()
button:emit_signal_recursive("test::recursive")
end)
))
layout:connect_signal("test::recursive", function()
got_called = true
end)
return true
end)
@ -111,6 +130,9 @@ end)
table.insert(steps, function()
assert(button._private.image == img)
-- The button had plenty of clicks by now. Make sure everything worked
assert(got_called)
return true
end)