From 0430f55257d6fb12c89a45719017b963e8018bb1 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 29 May 2017 02:40:09 -0400 Subject: [PATCH 1/6] ratio: Add a fill strategy for empty entries This allows, for example, to imeplement the tag `master_fill_policy` and simplify the client layouts by not having to hardcode empty columns and rows in each layouts. --- lib/wibox/layout/ratio.lua | 116 ++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index 86a22547..92983af3 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -16,6 +16,7 @@ local pairs = pairs local floor = math.floor local gmath = require("gears.math") local gtable = require("gears.table") +local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) local ratio = {} @@ -78,15 +79,19 @@ local function normalize(self) assert(new_sum > 0.99 and new_sum < 1.01) end -function ratio:layout(_, width, height) - local result = {} +function ratio:layout(context, width, height) + local preliminary_results = {} local pos,spacing = 0, self._private.spacing + local strategy = self:get_inner_fill_strategy() + local has_stragety = strategy ~= "default" + local to_redistribute, void_count = 0, 0 + local dir = self._private.dir or "x" for k, v in ipairs(self._private.widgets) do - local space - local x, y, w, h + local space, is_void + local x, y, w, h, fit_h, fit_w - if self._private.dir == "y" then + if dir == "y" then space = height * self._private.ratios[k] x, y = 0, gmath.round(pos) w, h = width, floor(space) @@ -96,18 +101,75 @@ function ratio:layout(_, width, height) w, h = floor(space), height end - table.insert(result, base.place_widget_at(v, x, y, w, h)) + -- Keep track of the unused entries + if has_stragety then + fit_h, fit_w = base.fit_widget( + self, context, v, + dir == "x" and floor(space) or w, + dir == "y" and floor(space) or h + ) + + is_void = (v.visible == false) + or (dir == "x" and fit_w == 0) + or (dir == "y" and fit_h == 0) + + if is_void then + to_redistribute = to_redistribute + space + spacing + void_count = void_count + 1 + end + end + + table.insert(preliminary_results, {v, x, y, w, h, is_void}) pos = pos + space + spacing -- Make sure all widgets fit in the layout, if they aren't, something -- went wrong - if (self._private.dir == "y" and gmath.round(pos) >= height) or - (self._private.dir ~= "y" and gmath.round(pos) >= width) then + if (dir == "y" and gmath.round(pos) >= height) or + (dir ~= "y" and gmath.round(pos) >= width) then break end end + local active = #preliminary_results - void_count + local result, real_pos, space_front = {}, 0, strategy == "right" and + to_redistribute or ( + strategy == "center" and math.floor(to_redistribute/2) or 0 + ) + + -- The number of spaces between `n` element is `n-1`, if there is spaces + -- outside, then it is `n+1` + if strategy == "spacing" then + space_front = (space_front+to_redistribute/(active + 1)) + to_redistribute = (to_redistribute/(active + 1))*(active - 1) + end + + spacing = strategy:match("spacing") + and to_redistribute/(active - 1) or 0 + + -- Only the `justify` strategy changes the original widget size. + to_redistribute = (strategy == "justify") and to_redistribute or 0 + + for _, entry in ipairs(preliminary_results) do + local v, x, y, w, h, is_void = unpack(entry) + + -- Redistribute the space or move the widgets + if strategy ~= "default" then + if dir == "y" then + h = is_void and 0 or h + (to_redistribute / (active)) + y = space_front + real_pos + real_pos = real_pos + h + (is_void and 0 or spacing) + + else + w = is_void and 0 or w + (to_redistribute / (active)) + x = space_front + real_pos + real_pos = real_pos + w + (is_void and 0 or spacing) + end + end + + table.insert(result, base.place_widget_at(v, x, y, w, h)) + end + return result end @@ -291,6 +353,44 @@ function ratio:insert(index, widget) self:emit_signal("widget::inserted", widget, #self._private.widgets) end +--- Set how the space of invisible or `0x0` sized widget is redistributed. +-- +-- Possible values: +-- +-- * "default": Honor the ratio and do not redistribute the space. +-- * "justify": Distribute the space among remaining widgets. +-- * "center": Squash remaining widgets and leave equal space on both side. +-- * "inner_spacing": Add equal spacing between all widgets. +-- * "spacing": Add equal spacing between all widgets and on the outside. +-- * "left": Squash remaining widgets and leave empty space on the left. +-- * "right": Squash remaining widgets and leave empty space on the right. +-- +--@DOC_wibox_layout_ratio_strategy_EXAMPLE@ +-- +-- @property inner_fill_strategy +-- @tparam string inner_fill_strategy One of the value listed above. + +function ratio:get_inner_fill_strategy() + return self._private.inner_fill_strategy or "default" +end + +local valid_strategies = { + default = true, + justify = true, + center = true, + inner_spacing = true, + spacing = true, + left = true, + right = true +} + +function ratio:set_inner_fill_strategy(strategy) + assert(valid_strategies[strategy] ~= nil, "Invalid strategy: "..(strategy or "")) + + self._private.inner_fill_strategy = strategy + self:emit_signal("widget::layout_changed") +end + local function get_layout(dir, widget1, ...) local ret = flex[dir](widget1, ...) From 458340b4d46aebd68eac4f6d08a065fe4009d1df Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 5 Jun 2017 01:47:05 -0400 Subject: [PATCH 2/6] doc: Add examples for the ratio layout --- lib/wibox/layout/ratio.lua | 8 +++- .../wibox/layout/ratio/ajust_ratio.lua | 48 +++++++++++++++++++ .../examples/wibox/layout/ratio/inc_ratio.lua | 39 +++++++++++++++ .../examples/wibox/layout/ratio/strategy.lua | 36 ++++++++++++++ 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 tests/examples/wibox/layout/ratio/ajust_ratio.lua create mode 100644 tests/examples/wibox/layout/ratio/inc_ratio.lua create mode 100644 tests/examples/wibox/layout/ratio/strategy.lua diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index 92983af3..a3a30f82 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -176,6 +176,9 @@ end --- Increase the ratio of "widget" -- If the increment produce an invalid ratio (not between 0 and 1), the method -- do nothing. +-- +--@DOC_wibox_layout_ratio_inc_ratio_EXAMPLE@ +-- -- @tparam number index The widget index to change -- @tparam number increment An floating point value between -1 and 1 where the -- end result is within 0 and 1 @@ -249,7 +252,10 @@ function ratio:set_widget_ratio(widget, percent) end --- Update all widgets to match a set of a ratio. --- The sum of before, itself and after must be 1 or nothing will be done +-- The sum of before, itself and after must be 1 or nothing will be done. +-- +--@DOC_wibox_layout_ratio_ajust_ratio_EXAMPLE@ +-- -- @tparam number index The index of the widget to change -- @tparam number before The sum of the ratio before the widget -- @tparam number itself The ratio for "widget" diff --git a/tests/examples/wibox/layout/ratio/ajust_ratio.lua b/tests/examples/wibox/layout/ratio/ajust_ratio.lua new file mode 100644 index 00000000..4e18ef8b --- /dev/null +++ b/tests/examples/wibox/layout/ratio/ajust_ratio.lua @@ -0,0 +1,48 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) --DOC_HIDE + +local first, second, third = generic_widget("first"), --DOC_HIDE + generic_widget("second"), generic_widget("third") --DOC_HIDE + +local ret = wibox.layout.fixed.vertical() + +local function create() --DOC_HIDE + +local w = wibox.widget { + first, + second, + third, + force_width = 200, --DOC_HIDE + layout = wibox.layout.ratio.horizontal +} + + return w --DOC_HIDE +end --DOC_HIDE + +local values = { + {0.25, 0.50, 0.25}, + {0.33, 0.55, 0.12}, + {0.123, 0.456, 0.789}, + {0.123, 0, 0.789}, + {0, 1, 0}, +} + +for i=1, 5 do + ret:add(wibox.widget { --DOC_HIDE + markup = "Set " .. i ..":", --DOC_HIDE + widget = wibox.widget.textbox --DOC_HIDE + }) --DOC_HIDE + + local w = create() --DOC_HIDE + + for _=1, i do --DOC_HIDE + w:ajust_ratio(2, unpack(values[i])) + end --DOC_HIDE + + ret:add(w) --DOC_HIDE +end + +return ret, 200, 200 --DOC_HIDE + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/examples/wibox/layout/ratio/inc_ratio.lua b/tests/examples/wibox/layout/ratio/inc_ratio.lua new file mode 100644 index 00000000..f430eab4 --- /dev/null +++ b/tests/examples/wibox/layout/ratio/inc_ratio.lua @@ -0,0 +1,39 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +local first, second, third = generic_widget("first"), --DOC_HIDE + generic_widget("second"), generic_widget("third") --DOC_HIDE + +local ret = wibox.layout.fixed.vertical() + +local function create() --DOC_HIDE + +local w = wibox.widget { + first, + second, + third, + force_width = 200, --DOC_HIDE + layout = wibox.layout.ratio.horizontal +} + + return w --DOC_HIDE +end --DOC_HIDE + +for i=1, 5 do + ret:add(wibox.widget { --DOC_HIDE + markup = "Iteration " .. i ..":", --DOC_HIDE + widget = wibox.widget.textbox --DOC_HIDE + }) --DOC_HIDE + + local w = create() --DOC_HIDE + + for _=1, i do --DOC_HIDE + w:inc_ratio(2, 0.1) + end --DOC_HIDE + + ret:add(w) --DOC_HIDE +end + +return ret, 200, 200 --DOC_HIDE + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/examples/wibox/layout/ratio/strategy.lua b/tests/examples/wibox/layout/ratio/strategy.lua new file mode 100644 index 00000000..3079b585 --- /dev/null +++ b/tests/examples/wibox/layout/ratio/strategy.lua @@ -0,0 +1,36 @@ +local generic_widget = ... --DOC_HIDE_ALL +local wibox = require("wibox") + +local empty_width = wibox.widget { + visible = false +} +local first, third, fourth = generic_widget("first"), generic_widget("third"), generic_widget("fourth") + +local function add(tab, name) + table.insert(tab, { + markup = ""..name..":", + widget = wibox.widget.textbox + }) + table.insert(tab, { + first, + empty_width, + third, + fourth, + inner_fill_strategy = name, + force_width = 200, + layout = wibox.layout.ratio.horizontal + }) +end + +local ret = {layout = wibox.layout.fixed.vertical} +add(ret, "default") +add(ret, "center") +add(ret, "justify") +add(ret, "inner_spacing") +add(ret, "spacing") +add(ret, "left") +add(ret, "right") + +return wibox.widget(ret), 200, 250 + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From e49e7d6938ec59bee8d865bf874fd129a6c01b38 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 29 May 2017 04:53:49 -0400 Subject: [PATCH 3/6] shims: Add a missing drawin member --- tests/examples/shims/drawin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/examples/shims/drawin.lua b/tests/examples/shims/drawin.lua index ed06e2e6..689aba32 100644 --- a/tests/examples/shims/drawin.lua +++ b/tests/examples/shims/drawin.lua @@ -4,7 +4,7 @@ local drawin, meta = awesome._shim_fake_class() local function new_drawin(_, args) local ret = gears_obj() - ret.data = {} + ret.data = {drawable = gears_obj()} for k, v in pairs(args) do rawset(ret, k, v) From 29f70c1b4c07b413231cb7340be97c7f003ac520 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 4 Jun 2017 18:22:03 -0400 Subject: [PATCH 4/6] mirror: Fix documentation It didn't render properly --- lib/wibox/container/mirror.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua index 5bae08e5..bad0a106 100644 --- a/lib/wibox/container/mirror.lua +++ b/lib/wibox/container/mirror.lua @@ -96,9 +96,9 @@ end --- Get the reflection of this mirror layout. -- @property reflection --- @param table reflection A table of booleans with the keys "horizontal", "vertical". --- @param boolean reflection.horizontal --- @param boolean reflection.vertical +-- @tparam table reflection A table of booleans with the keys "horizontal", "vertical". +-- @tparam boolean reflection.horizontal +-- @tparam boolean reflection.vertical function mirror:get_reflection() return { horizontal = self._private.horizontal, vertical = self._private.vertical } From fb367c3f9e043021023f508a408aac47aaf56d74 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 12 Jun 2017 02:48:00 -0400 Subject: [PATCH 5/6] stack: Add offset support --- lib/wibox/layout/stack.lua | 43 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/wibox/layout/stack.lua b/lib/wibox/layout/stack.lua index 19149b25..7592c44d 100644 --- a/lib/wibox/layout/stack.lua +++ b/lib/wibox/layout/stack.lua @@ -51,7 +51,8 @@ local stack = {mt={}} -- @name remove_widgets -- @class function ---- Add spacing between each layout widgets +--- Add spacing around the widget, similar to the margin container. +--@DOC_wibox_layout_stack_spacing_EXAMPLE@ -- @property spacing -- @tparam number spacing Spacing between widgets. @@ -59,8 +60,14 @@ function stack:layout(_, width, height) local result = {} local spacing = self._private.spacing + width = width - math.abs(self._private.h_offset * #self._private.widgets) - 2*spacing + height = height - math.abs(self._private.v_offset * #self._private.widgets) - 2*spacing + + local h_off, v_off = spacing, spacing + for _, v in pairs(self._private.widgets) do - table.insert(result, base.place_widget_at(v, spacing, spacing, width - 2*spacing, height - 2*spacing)) + table.insert(result, base.place_widget_at(v, h_off, v_off, width, height)) + h_off, v_off = h_off + self._private.h_offset, v_off + self._private.v_offset if self._private.top_only then break end end @@ -121,6 +128,35 @@ function stack:raise_widget(widget, recursive) end end +--- Add an horizontal offset to each layers. +-- +-- Note that this reduces the overall size of each widgets by the sum of all +-- layers offsets. +-- +--@DOC_wibox_layout_stack_offset_EXAMPLE@ +-- +-- @property horizontal_offset +-- @param number + +--- Add an vertical offset to each layers. +-- +-- Note that this reduces the overall size of each widgets by the sum of all +-- layers offsets. +-- +-- @property vertial_offset +-- @param number +-- @see horizontal_offset + +function stack:set_horizontal_offset(value) + self._private.h_offset = value + self:emit_signal("widget::layout_changed") +end + +function stack:set_vertical_offset(value) + self._private.v_offset = value + self:emit_signal("widget::layout_changed") +end + --- Create a new stack layout. -- @function wibox.layout.stack -- @treturn widget A new stack layout @@ -130,6 +166,9 @@ local function new(...) gtable.crush(ret, stack, true) + ret._private.h_offset = 0 + ret._private.v_offset = 0 + return ret end From 82d1616773adf3172495b91aa9408989da3fde87 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 12 Jun 2017 02:48:34 -0400 Subject: [PATCH 6/6] tests: Add tests for the stack layout --- tests/examples/wibox/layout/stack/offset.lua | 15 +++++++++++++++ tests/examples/wibox/layout/stack/spacing.lua | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/examples/wibox/layout/stack/offset.lua create mode 100644 tests/examples/wibox/layout/stack/spacing.lua diff --git a/tests/examples/wibox/layout/stack/offset.lua b/tests/examples/wibox/layout/stack/offset.lua new file mode 100644 index 00000000..e1ef3a5e --- /dev/null +++ b/tests/examples/wibox/layout/stack/offset.lua @@ -0,0 +1,15 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + horizontal_offset = 5, + vertical_offset = 5, + layout = wibox.layout.stack +} +, 200, 50 --DOC_HIDE + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/examples/wibox/layout/stack/spacing.lua b/tests/examples/wibox/layout/stack/spacing.lua new file mode 100644 index 00000000..a0a99c45 --- /dev/null +++ b/tests/examples/wibox/layout/stack/spacing.lua @@ -0,0 +1,13 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + spacing = 6, + layout = wibox.layout.stack +} + +--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80