Added Expand Modes

Added set_expand function with options of "none" "outside" or "inside" modes.
The "inside" mode is the default and will result in the original behavior. The
main benefit is being able to actually center a widget in the available space
with options of how to draw the outside widgets (expand to take the space,
or not.) Further functionality can be had by ommiting one of the outside
widgets. Set default layout mode in the constructor.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
sirkha 2014-01-02 02:09:08 -06:00 committed by Uli Schlachter
parent 601dc232db
commit fbba41ddaa
1 changed files with 90 additions and 26 deletions

View File

@ -8,6 +8,7 @@ local setmetatable = setmetatable
local table = table local table = table
local pairs = pairs local pairs = pairs
local type = type local type = type
local floor = math.floor
local base = require("wibox.layout.base") local base = require("wibox.layout.base")
local widget_base = require("wibox.widget.base") local widget_base = require("wibox.widget.base")
@ -19,48 +20,89 @@ local align = {}
-- @param cr The cairo context to use. -- @param cr The cairo context to use.
-- @param width The available width. -- @param width The available width.
-- @param height The available height. -- @param height The available height.
-- @return The total space needed by the layout.
function align:draw(wibox, cr, width, height) function align:draw(wibox, cr, width, height)
local size_first = 0 local size_first = 0
local size_third = 0 local size_remains = self.dir == "y" and height or width
local size_limit = self.dir == "y" and height or width
if self._expand ~= "inside" and self.second then
local w, h = base.fit_widget(self.second, width, height)
local size_second = self.dir == "y" and h or w
if size_second >= size_remains then
base.draw_widget(wibox, cr, self.second, 0, 0, width, height)
return
else
size_remains = floor((size_remains - size_second) / 2)
end
end
if self.first then if self.first then
local w, h, _ = width, height, nil local w, h, _ = width, height, nil
if self.dir == "y" then if self._expand ~= "outside" or not self.second then
_, h = base.fit_widget(self.first, w, h) if self.dir == "y" then
size_first = h _, h = base.fit_widget(self.first, width, size_remains)
size_first = h
if self._expand == "inside" or not self.second then
size_remains = size_remains - h
end
else
w, _ = base.fit_widget(self.first, size_remains, height)
size_first = w
if self._expand == "inside" or not self.second then
size_remains = size_remains - w
end
end
else else
w, _ = base.fit_widget(self.first, w, h) if self.dir == "y" then
size_first = w h = size_remains
else
w = size_remains
end
end end
base.draw_widget(wibox, cr, self.first, 0, 0, w, h) base.draw_widget(wibox, cr, self.first, 0, 0, w, h)
end end
if self.third and size_first < size_limit then if self.third and size_remains > 0 then
local w, h, x, y, _ local w, h, _ = width, height, nil
if self.dir == "y" then if self._expand ~= "outside" then
w, h = width, height - size_first if self.dir == "y" then
_, h = base.fit_widget(self.third, w, h) _, h = base.fit_widget(self.third, width, size_remains)
x, y = 0, height - h if self._expand == "inside" then
size_third = h size_remains = size_remains - h
end
else
w, _ = base.fit_widget(self.third, size_remains, height)
if self._expand == "inside" then
size_remains = size_remains - w
end
end
else else
w, h = width - size_first, height if self.dir == "y" then
w, _ = base.fit_widget(self.third, w, h) h = size_remains
x, y = width - w, 0 else
size_third = w w = size_remains
end
end end
local x, y = width - w, height - h
base.draw_widget(wibox, cr, self.third, x, y, w, h) base.draw_widget(wibox, cr, self.third, x, y, w, h)
end end
if self.second and size_first + size_third < size_limit then if self.second and size_remains > 0 then
local x, y, w, h local x, y, w, h = 0, 0, width, height
if self.dir == "y" then if self._expand == "inside" then
w, h = width, size_limit - size_first - size_third if self.dir == "y" then
x, y = 0, size_first h = size_remains
x, y = 0, size_first
else
w = size_remains
x, y = size_first, 0
end
else else
w, h = size_limit - size_first - size_third, height if self.dir == "y" then
x, y = size_first, 0 _, h = base.fit_widget(self.second, width, size_remains)
y = floor( (height - h)/2 )
else
w, _ = base.fit_widget(self.second, width, size_remains)
x = floor( (width -w)/2 )
end
end end
base.draw_widget(wibox, cr, self.second, x, y, w, h) base.draw_widget(wibox, cr, self.second, x, y, w, h)
end end
@ -120,6 +162,26 @@ function align:fit(orig_width, orig_height)
end end
return used_in_dir, used_in_other return used_in_dir, used_in_other
end end
--- Set the expand mode which determines how sub widgets expand to take up
-- unused space. Options are:
-- "inside" - Default option. Size of outside widgets is determined using their
-- fit function. Second, middle, or center widget expands to fill
-- remaining space.
-- "outside" - Center widget is sized using its fit function and placed in the
-- center of the allowed space. Outside widgets expand (or contract)
-- to fill remaining space on their side.
-- "none" - All widgets are sized using their fit function, drawn to only the
-- returned space, or remaining space, whichever is smaller. Center
-- widget gets priority.
-- @param mode How to use unused space. "inside" (default) "outside" or "none"
function align:set_expand(mode)
if mode == "none" or mode == "outside" then
self._expand = mode
else
self._expand = "inside"
end
self:emit_signal("widget::updated")
end
function align:reset() function align:reset()
for k, v in pairs({ "first", "second", "third" }) do for k, v in pairs({ "first", "second", "third" }) do
@ -141,6 +203,8 @@ local function get_layout(dir)
end end
end end
ret:set_expand("inside")
return ret return ret
end end