From a9c06fb8c52be2fa0faea93bac9e875e9b5b4a8a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 7 Aug 2017 16:49:48 -0400 Subject: [PATCH 1/3] template: Add configurable margins to the generic layout widget --- tests/examples/wibox/layout/template.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/examples/wibox/layout/template.lua b/tests/examples/wibox/layout/template.lua index b414e386e..2a65b3fb0 100644 --- a/tests/examples/wibox/layout/template.lua +++ b/tests/examples/wibox/layout/template.lua @@ -7,7 +7,7 @@ local beautiful = require( "beautiful" ) local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) -- Create a generic rectangle widget to show layout disposition -local function generic_widget(text, col) +local function generic_widget(text, col, margins) return wibox.widget { { { @@ -30,7 +30,7 @@ local function generic_widget(text, col) } or nil, widget = wibox.layout.stack }, - margins = 5, + margins = margins or 5, set_text = function(self, text2) self:get_children_by_id("text")[1]:set_text(text2) end, From e12c000b9708680a542349e19f267ad49987c555 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 7 Aug 2017 16:12:29 -0400 Subject: [PATCH 2/3] layout: Add separator widget support to 3 layouts The ratio, fixed and flex layout can now display a widget between each layout elements. The align layout was left out because it doesn't support spacing --- lib/wibox/layout/fixed.lua | 38 ++++++++++++++++++++++++++++++++++---- lib/wibox/layout/flex.lua | 38 +++++++++++++++++++++++++++++++++----- lib/wibox/layout/ratio.lua | 30 +++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/lib/wibox/layout/fixed.lua b/lib/wibox/layout/fixed.lua index 4d7fac697..95b91e6a3 100644 --- a/lib/wibox/layout/fixed.lua +++ b/lib/wibox/layout/fixed.lua @@ -23,10 +23,15 @@ local fixed = {} function fixed:layout(context, width, height) local result = {} local pos,spacing = 0, self._private.spacing + local spacing_widget = self._private.spacing_widget + 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 for k, v in pairs(self._private.widgets) do local x, y, w, h, _ - if self._private.dir == "y" then + if is_y then x, y = 0, pos w, h = width, height - pos if k ~= #self._private.widgets or not self._private.fill_space then @@ -42,10 +47,18 @@ function fixed:layout(context, width, height) pos = pos + w + spacing end - if (self._private.dir == "y" and pos-spacing > height) or - (self._private.dir ~= "y" and pos-spacing > width) then + if (is_y and pos-spacing > height) or + (is_x and pos-spacing > width) then break end + + -- Add the spacing widget + if k > 1 and abspace > 0 and spacing_widget then + table.insert(result, base.place_widget_at( + 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 + )) + end table.insert(result, base.place_widget_at(v, x, y, w, h)) end return result @@ -194,6 +207,20 @@ function fixed:set(index, widget2) return true end +--- The widget used to fill the spacing between the layout elements. +-- +-- By default, no widget is used. +-- +--@DOC_wibox_layout_fixed_spacing_widget_EXAMPLE@ +-- +-- @property spacing_widget +-- @param widget + +function fixed:set_spacing_widget(wdg) + self._private.spacing_widget = base.make_widget_from_value(wdg) + self:emit_signal("widget::layout_changed") +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 @@ -308,7 +335,10 @@ function fixed.vertical(...) return get_layout("y", ...) end ---- Add spacing between each layout widgets +--- Add spacing between each layout widgets. +-- +--@DOC_wibox_layout_fixed_spacing_EXAMPLE@ +-- -- @property spacing -- @tparam number spacing Spacing between widgets. diff --git a/lib/wibox/layout/flex.lua b/lib/wibox/layout/flex.lua index e66896f8f..797705e73 100644 --- a/lib/wibox/layout/flex.lua +++ b/lib/wibox/layout/flex.lua @@ -50,14 +50,35 @@ local flex = {} -- @name insert -- @class function +--- The widget used to fill the spacing between the layout elements. +-- +-- By default, no widget is used. +-- +--@DOC_wibox_layout_flex_spacing_widget_EXAMPLE@ +-- +-- @property spacing_widget +-- @param widget + +--- Add spacing between each layout widgets. +-- +--@DOC_wibox_layout_flex_spacing_EXAMPLE@ +-- +-- @property spacing +-- @tparam number spacing Spacing between widgets. + function flex:layout(_, width, height) local result = {} local pos,spacing = 0, self._private.spacing local num = #self._private.widgets local total_spacing = (spacing*(num-1)) + local spacing_widget = self._private.spacing_widget + local abspace = math.abs(spacing) + local spoffset = spacing < 0 and 0 or spacing + local is_y = self._private.dir == "y" + local is_x = not is_y local space_per_item - if self._private.dir == "y" then + if is_y then space_per_item = height / num - total_spacing/num else space_per_item = width / num - total_spacing/num @@ -67,9 +88,9 @@ function flex:layout(_, width, height) space_per_item = math.min(space_per_item, self._private.max_widget_size) end - for _, v in pairs(self._private.widgets) do + for k, v in pairs(self._private.widgets) do local x, y, w, h - if self._private.dir == "y" then + if is_y then x, y = 0, gmath.round(pos) w, h = width, floor(space_per_item) else @@ -81,10 +102,17 @@ function flex:layout(_, width, height) pos = pos + space_per_item + spacing - if (self._private.dir == "y" and pos-spacing >= height) or - (self._private.dir ~= "y" and pos-spacing >= width) then + if (is_y and pos-spacing >= height) or + (is_x and pos-spacing >= width) then break end + + if k > 1 and spacing ~= 0 and spacing_widget then + table.insert(result, base.place_widget_at( + 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 + )) + end end return result diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index a3a30f822..04828a6a0 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -22,6 +22,22 @@ local ratio = {} --@DOC_fixed_COMMON@ +--- The widget used to fill the spacing between the layout elements. +-- +-- By default, no widget is used. +-- +--@DOC_wibox_layout_ratio_spacing_widget_EXAMPLE@ +-- +-- @property spacing_widget +-- @param widget + +--- Add spacing between each layout widgets. +-- +--@DOC_wibox_layout_ratio_spacing_EXAMPLE@ +-- +-- @property spacing +-- @tparam number spacing Spacing between widgets. + -- Compute the sum of all ratio (ideally, it should be 1) local function gen_sum(self, i_s, i_e) local sum, new_w = 0,0 @@ -86,6 +102,11 @@ function ratio:layout(context, width, height) local has_stragety = strategy ~= "default" local to_redistribute, void_count = 0, 0 local dir = self._private.dir or "x" + local spacing_widget = self._private.spacing_widget + local abspace = math.abs(spacing) + local spoffset = spacing < 0 and 0 or spacing + local is_y = self._private.dir == "y" + local is_x = not is_y for k, v in ipairs(self._private.widgets) do local space, is_void @@ -150,7 +171,7 @@ function ratio:layout(context, width, height) -- 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 + for k, entry in ipairs(preliminary_results) do local v, x, y, w, h, is_void = unpack(entry) -- Redistribute the space or move the widgets @@ -167,6 +188,13 @@ function ratio:layout(context, width, height) end end + if k > 1 and abspace > 0 and spacing_widget then + table.insert(result, base.place_widget_at( + 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 + )) + end + table.insert(result, base.place_widget_at(v, x, y, w, h)) end From f1b4850bdc79bcadd0b881289786af486e9506d5 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 7 Aug 2017 16:50:11 -0400 Subject: [PATCH 3/3] tests: Test the spacing widgets --- tests/examples/wibox/layout/fixed/spacing.lua | 28 ++++++++ .../wibox/layout/fixed/spacing_widget.lua | 70 +++++++++++++++++++ tests/examples/wibox/layout/flex/spacing.lua | 28 ++++++++ .../wibox/layout/flex/spacing_widget.lua | 70 +++++++++++++++++++ tests/examples/wibox/layout/ratio/spacing.lua | 29 ++++++++ .../wibox/layout/ratio/spacing_widget.lua | 70 +++++++++++++++++++ 6 files changed, 295 insertions(+) create mode 100644 tests/examples/wibox/layout/fixed/spacing.lua create mode 100644 tests/examples/wibox/layout/fixed/spacing_widget.lua create mode 100644 tests/examples/wibox/layout/flex/spacing.lua create mode 100644 tests/examples/wibox/layout/flex/spacing_widget.lua create mode 100644 tests/examples/wibox/layout/ratio/spacing.lua create mode 100644 tests/examples/wibox/layout/ratio/spacing_widget.lua diff --git a/tests/examples/wibox/layout/fixed/spacing.lua b/tests/examples/wibox/layout/fixed/spacing.lua new file mode 100644 index 000000000..a5e4abc11 --- /dev/null +++ b/tests/examples/wibox/layout/fixed/spacing.lua @@ -0,0 +1,28 @@ +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() --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 = wibox.widget { + first, + second, + third, + spacing = i*3, + layout = wibox.layout.fixed.horizontal + } + + 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/fixed/spacing_widget.lua b/tests/examples/wibox/layout/fixed/spacing_widget.lua new file mode 100644 index 000000000..d1531e0f7 --- /dev/null +++ b/tests/examples/wibox/layout/fixed/spacing_widget.lua @@ -0,0 +1,70 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local gears = {shape = require("gears.shape")}--DOC_HIDE + +local l = wibox.layout.flex.vertical() --DOC_HIDE + +-- Use the separator widget directly +local w1 = wibox.widget { + generic_widget( "first" , nil, 0), --DOC_HIDE + generic_widget( "second" , nil, 0), --DOC_HIDE + generic_widget( "third" , nil, 0), --DOC_HIDE + spacing = 10, + spacing_widget = wibox.widget.separator, + layout = wibox.layout.fixed.horizontal +} + +l:add(w1) --DOC_HIDE + +-- Use a standard declarative widget construct +local w2 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + color = "#00ff00", + shape = gears.shape.circle, + widget = wibox.widget.separator, + }, + layout = wibox.layout.fixed.horizontal +} + +l:add(w2) --DOC_HIDE + +-- Use composed widgets +local w3 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + { + text = "F", + widget = wibox.widget.textbox, + }, + bg = "#ff0000", + widget = wibox.container.background, + }, + layout = wibox.layout.fixed.horizontal +} + +l:add(w3) --DOC_HIDE + +-- Use negative spacing to create a powerline effect +local w4 = wibox.widget { + generic_widget( " first " , nil, 0), --DOC_HIDE + generic_widget( " second " , nil, 0), --DOC_HIDE + generic_widget( " third " , nil, 0), --DOC_HIDE + spacing = -12, + spacing_widget = { + color = "#ff0000", + shape = gears.shape.powerline, + widget = wibox.widget.separator, + }, + layout = wibox.layout.fixed.horizontal +} + +l:add(w4) --DOC_HIDE + +return l, 250, 4*30 --DOC_HIDE diff --git a/tests/examples/wibox/layout/flex/spacing.lua b/tests/examples/wibox/layout/flex/spacing.lua new file mode 100644 index 000000000..f771d9144 --- /dev/null +++ b/tests/examples/wibox/layout/flex/spacing.lua @@ -0,0 +1,28 @@ +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() --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 = wibox.widget { + first, + second, + third, + spacing = i*5, + layout = wibox.layout.flex.horizontal + } + + 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/flex/spacing_widget.lua b/tests/examples/wibox/layout/flex/spacing_widget.lua new file mode 100644 index 000000000..e9586e021 --- /dev/null +++ b/tests/examples/wibox/layout/flex/spacing_widget.lua @@ -0,0 +1,70 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local gears = {shape = require("gears.shape")}--DOC_HIDE + +local l = wibox.layout.flex.vertical() --DOC_HIDE + +-- Use the separator widget directly +local w1 = wibox.widget { + generic_widget( "first" , nil, 0), --DOC_HIDE + generic_widget( "second" , nil, 0), --DOC_HIDE + generic_widget( "third" , nil, 0), --DOC_HIDE + spacing = 10, + spacing_widget = wibox.widget.separator, + layout = wibox.layout.flex.horizontal +} + +l:add(w1) --DOC_HIDE + +-- Use a standard declarative widget construct +local w2 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + color = "#00ff00", + shape = gears.shape.circle, + widget = wibox.widget.separator, + }, + layout = wibox.layout.flex.horizontal +} + +l:add(w2) --DOC_HIDE + +-- Use composed widgets +local w3 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + { + text = "F", + widget = wibox.widget.textbox, + }, + bg = "#ff0000", + widget = wibox.container.background, + }, + layout = wibox.layout.flex.horizontal +} + +l:add(w3) --DOC_HIDE + +-- Use negative spacing to create a powerline effect +local w4 = wibox.widget { + generic_widget( " first " , nil, 0), --DOC_HIDE + generic_widget( " second " , nil, 0), --DOC_HIDE + generic_widget( " third " , nil, 0), --DOC_HIDE + spacing = -12, + spacing_widget = { + color = "#ff0000", + shape = gears.shape.powerline, + widget = wibox.widget.separator, + }, + layout = wibox.layout.flex.horizontal +} + +l:add(w4) --DOC_HIDE + +return l, 250, 4*30 --DOC_HIDE diff --git a/tests/examples/wibox/layout/ratio/spacing.lua b/tests/examples/wibox/layout/ratio/spacing.lua new file mode 100644 index 000000000..6c1304d84 --- /dev/null +++ b/tests/examples/wibox/layout/ratio/spacing.lua @@ -0,0 +1,29 @@ +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() --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 = wibox.widget { + first, + second, + third, + spacing = i*3, + force_width = 200, --DOC_HIDE + layout = wibox.layout.ratio.horizontal + } + + 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/spacing_widget.lua b/tests/examples/wibox/layout/ratio/spacing_widget.lua new file mode 100644 index 000000000..1fea3bd97 --- /dev/null +++ b/tests/examples/wibox/layout/ratio/spacing_widget.lua @@ -0,0 +1,70 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local gears = {shape = require("gears.shape")}--DOC_HIDE + +local l = wibox.layout.flex.vertical() --DOC_HIDE + +-- Use the separator widget directly +local w1 = wibox.widget { + generic_widget( "first" , nil, 0), --DOC_HIDE + generic_widget( "second" , nil, 0), --DOC_HIDE + generic_widget( "third" , nil, 0), --DOC_HIDE + spacing = 10, + spacing_widget = wibox.widget.separator, + layout = wibox.layout.ratio.horizontal +} + +l:add(w1) --DOC_HIDE + +-- Use a standard declarative widget construct +local w2 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + color = "#00ff00", + shape = gears.shape.circle, + widget = wibox.widget.separator, + }, + layout = wibox.layout.ratio.horizontal +} + +l:add(w2) --DOC_HIDE + +-- Use composed widgets +local w3 = wibox.widget { + generic_widget( "first" ), --DOC_HIDE + generic_widget( "second" ), --DOC_HIDE + generic_widget( "third" ), --DOC_HIDE + spacing = 10, + spacing_widget = { + { + text = "F", + widget = wibox.widget.textbox, + }, + bg = "#ff0000", + widget = wibox.container.background, + }, + layout = wibox.layout.ratio.horizontal +} + +l:add(w3) --DOC_HIDE + +-- Use negative spacing to create a powerline effect +local w4 = wibox.widget { + generic_widget( " first " , nil, 0), --DOC_HIDE + generic_widget( " second " , nil, 0), --DOC_HIDE + generic_widget( " third " , nil, 0), --DOC_HIDE + spacing = -12, + spacing_widget = { + color = "#ff0000", + shape = gears.shape.powerline, + widget = wibox.widget.separator, + }, + layout = wibox.layout.ratio.horizontal +} + +l:add(w4) --DOC_HIDE + +return l, 250, 4*30 --DOC_HIDE