align: Enable the property system

And add the missing documentation
This commit is contained in:
Emmanuel Lepage Vallee 2016-05-26 19:41:58 -04:00
parent b89fbcf940
commit 0a8bc8156d
1 changed files with 80 additions and 60 deletions

View File

@ -32,7 +32,7 @@ function align:layout(context, width, height)
-- allowed.
local size_first = 0
-- start with all the space given by the parent, subtract as we go along
local size_remains = self.dir == "y" and height or width
local size_remains = self._private.dir == "y" and height or width
-- This is only set & used if expand ~= "inside" and we have second width.
-- It contains the size allocated to the second widget.
local size_second
@ -41,84 +41,84 @@ function align:layout(context, width, height)
-- if it is, we prioritize the first widget by not doing this block also,
-- if the second widget doesn't exist, we will prioritise the first one
-- instead
if self._expand ~= "inside" and self.second then
local w, h = base.fit_widget(self, context, self.second, width, height)
size_second = self.dir == "y" and h or w
if self._private.expand ~= "inside" and self._private.second then
local w, h = base.fit_widget(self, context, self._private.second, width, height)
size_second = self._private.dir == "y" and h or w
-- if all the space is taken, skip the rest, and draw just the middle
-- widget
if size_second >= size_remains then
return { base.place_widget_at(self.second, 0, 0, width, height) }
return { base.place_widget_at(self._private.second, 0, 0, width, height) }
else
-- the middle widget is sized first, the outside widgets are given
-- the remaining space if available we will draw later
size_remains = floor((size_remains - size_second) / 2)
end
end
if self.first then
if self._private.first then
local w, h, _ = width, height, nil
-- we use the fit function for the "inside" and "none" modes, but
-- ignore it for the "outside" mode, which will force it to expand
-- into the remaining space
if self._expand ~= "outside" then
if self.dir == "y" then
_, h = base.fit_widget(self, context, self.first, width, size_remains)
if self._private.expand ~= "outside" then
if self._private.dir == "y" then
_, h = base.fit_widget(self, context, self._private.first, width, size_remains)
size_first = h
-- for "inside", the third widget will get a chance to use the
-- remaining space, then the middle widget. For "none" we give
-- the third widget the remaining space if there was no second
-- widget to take up any space (as the first if block is skipped
-- if this is the case)
if self._expand == "inside" or not self.second then
if self._private.expand == "inside" or not self._private.second then
size_remains = size_remains - h
end
else
w, _ = base.fit_widget(self, context, self.first, size_remains, height)
w, _ = base.fit_widget(self, context, self._private.first, size_remains, height)
size_first = w
if self._expand == "inside" or not self.second then
if self._private.expand == "inside" or not self._private.second then
size_remains = size_remains - w
end
end
else
if self.dir == "y" then
if self._private.dir == "y" then
h = size_remains
else
w = size_remains
end
end
table.insert(result, base.place_widget_at(self.first, 0, 0, w, h))
table.insert(result, base.place_widget_at(self._private.first, 0, 0, w, h))
end
-- size_remains will be <= 0 if first used all the space
if self.third and size_remains > 0 then
if self._private.third and size_remains > 0 then
local w, h, _ = width, height, nil
if self._expand ~= "outside" then
if self.dir == "y" then
_, h = base.fit_widget(self, context, self.third, width, size_remains)
if self._private.expand ~= "outside" then
if self._private.dir == "y" then
_, h = base.fit_widget(self, context, self._private.third, width, size_remains)
-- give the middle widget the rest of the space for "inside" mode
if self._expand == "inside" then
if self._private.expand == "inside" then
size_remains = size_remains - h
end
else
w, _ = base.fit_widget(self, context, self.third, size_remains, height)
if self._expand == "inside" then
w, _ = base.fit_widget(self, context, self._private.third, size_remains, height)
if self._private.expand == "inside" then
size_remains = size_remains - w
end
end
else
if self.dir == "y" then
if self._private.dir == "y" then
h = size_remains
else
w = size_remains
end
end
local x, y = width - w, height - h
table.insert(result, base.place_widget_at(self.third, x, y, w, h))
table.insert(result, base.place_widget_at(self._private.third, x, y, w, h))
end
-- here we either draw the second widget in the space set aside for it
-- in the beginning, or in the remaining space, if it is "inside"
if self.second and size_remains > 0 then
if self._private.second and size_remains > 0 then
local x, y, w, h = 0, 0, width, height
if self._expand == "inside" then
if self.dir == "y" then
if self._private.expand == "inside" then
if self._private.dir == "y" then
h = size_remains
x, y = 0, size_first
else
@ -127,55 +127,69 @@ function align:layout(context, width, height)
end
else
local _
if self.dir == "y" then
_, h = base.fit_widget(self, context, self.second, width, size_second)
if self._private.dir == "y" then
_, h = base.fit_widget(self, context, self._private.second, width, size_second)
y = floor( (height - h)/2 )
else
w, _ = base.fit_widget(self, context, self.second, size_second, height)
w, _ = base.fit_widget(self, context, self._private.second, size_second, height)
x = floor( (width -w)/2 )
end
end
table.insert(result, base.place_widget_at(self.second, x, y, w, h))
table.insert(result, base.place_widget_at(self._private.second, x, y, w, h))
end
return result
end
--- Set the layout's first widget. This is the widget that is at the left/top
--- Set the layout's first widget.
-- This is the widget that is at the left/top
-- @property first
function align:set_first(widget)
if self.first == widget then
if self._private.first == widget then
return
end
self.first = widget
self._private.first = widget
self:emit_signal("widget::layout_changed")
end
--- Set the layout's second widget. This is the centered one.
-- @property second
function align:set_second(widget)
if self.second == widget then
if self._private.second == widget then
return
end
self.second = widget
self._private.second = widget
self:emit_signal("widget::layout_changed")
end
--- Set the layout's third widget. This is the widget that is at the right/bottom
--- Set the layout's third widget.
-- This is the widget that is at the right/bottom
-- @property third
function align:set_third(widget)
if self.third == widget then
if self._private.third == widget then
return
end
self.third = widget
self._private.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}
for _, prop in ipairs {"first", "second", "third", "expand" } do
align["get_"..prop] = function(self)
return self._private[prop]
end
end
--- All direct children of this layout.
-- This can be used to replace all 3 widgets at once.
-- @treturn table a list of all widgets
-- @property children
function align:get_children()
return util.from_sparse {self._private.first, self._private.second, self._private.third}
end
--- Replace the layout children
-- This layout only accept three children, all others will be ignored
-- @tparam table children A table composed of valid widgets
function align:set_children(children)
self:set_first(children[1])
self:set_second(children[2])
@ -192,18 +206,18 @@ function align:fit(context, orig_width, orig_height)
local used_in_dir = 0
local used_in_other = 0
for _, v in pairs{self.first, self.second, self.third} do
for _, v in pairs{self._private.first, self._private.second, self._private.third} do
local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
local max = self.dir == "y" and w or h
local max = self._private.dir == "y" and w or h
if max > used_in_other then
used_in_other = max
end
used_in_dir = used_in_dir + (self.dir == "y" and h or w)
used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
end
if self.dir == "y" then
if self._private.dir == "y" then
return used_in_other, used_in_dir
end
return used_in_dir, used_in_other
@ -223,11 +237,13 @@ end
-- * "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.
-- @property expand
function align:set_expand(mode)
if mode == "none" or mode == "outside" then
self._expand = mode
self._private.expand = mode
else
self._expand = "inside"
self._private.expand = "inside"
end
self:emit_signal("widget::layout_changed")
end
@ -240,12 +256,12 @@ function align:reset()
end
local function get_layout(dir, first, second, third)
local ret = base.make_widget()
ret.dir = dir
local ret = base.make_widget(nil, nil, {enable_properties = true})
ret._private.dir = dir
for k, v in pairs(align) do
if type(v) == "function" then
ret[k] = v
rawset(ret, k, v)
end
end
@ -270,9 +286,9 @@ end
function align.horizontal(left, middle, right)
local ret = get_layout("x", left, middle, right)
ret.set_left = ret.set_first
ret.set_middle = ret.set_second
ret.set_right = ret.set_third
rawset(ret, "set_left" , ret.set_first )
rawset(ret, "set_middle", ret.set_second )
rawset(ret, "set_right" , ret.set_third )
return ret
end
@ -287,13 +303,17 @@ end
function align.vertical(top, middle, bottom)
local ret = get_layout("y", top, middle, bottom)
ret.set_top = ret.set_first
ret.set_middle = ret.set_second
ret.set_bottom = ret.set_third
rawset(ret, "set_top" , ret.set_first )
rawset(ret, "set_middle", ret.set_second )
rawset(ret, "set_bottom", ret.set_third )
return ret
end
--@DOC_widget_COMMON@
--@DOC_object_COMMON@
return align
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80