add ResizingPanel class and autolayout for Panels (#2086)

* add autolayout for Panels and new ResizingPanel
develop
Myk 2022-04-11 18:25:00 -07:00 committed by GitHub
parent e6299700bf
commit 10f22ecc27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 0 deletions

@ -3705,6 +3705,23 @@ Has attributes:
Called from ``onRenderBody``. Called from ``onRenderBody``.
* ``autoarrange_subviews = bool`` (default: false)
* ``autoarrange_gap = int`` (default: 0)
If ``autoarrange_subviews`` is set to ``true``, the Panel will
automatically handle subview layout. Subviews are laid out vertically
according to their current height, with ``autoarrange_gap`` empty lines
between subviews. This allows you to have widgets dynamically change
height or become visible/hidden and you don't have to worry about
recalculating subview positions.
ResizingPanel class
-------------------
Subclass of Panel; automatically adjusts its own frame height according to
the size, position, and visibility of its subviews. Pairs nicely with a
parent Panel that has ``autoarrange_subviews`` enabled.
Pages class Pages class
----------- -----------

@ -75,6 +75,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- Lua wrappers for functions reverse-engineered from ambushing unit code: ``isHidden(unit)``, ``isFortControlled(unit)``, ``getOuterContainerRef(unit)``, ``getOuterContainerRef(item)`` - Lua wrappers for functions reverse-engineered from ambushing unit code: ``isHidden(unit)``, ``isFortControlled(unit)``, ``getOuterContainerRef(unit)``, ``getOuterContainerRef(item)``
- ``dwarfmode.enterSidebarMode()``: passing ``df.ui_sidebar_mode.DesignateMine`` now always results in you entering ``DesignateMine`` mode and not ``DesignateChopTrees``, even when you looking at the surface where the default designation mode is ``DesignateChopTrees`` - ``dwarfmode.enterSidebarMode()``: passing ``df.ui_sidebar_mode.DesignateMine`` now always results in you entering ``DesignateMine`` mode and not ``DesignateChopTrees``, even when you looking at the surface where the default designation mode is ``DesignateChopTrees``
- New string class function: ``string:escape_pattern()`` escapes regex special characters within a string - New string class function: ``string:escape_pattern()`` escapes regex special characters within a string
- ``widgets.Panel``: if ``autoarrange_subviews`` is set, ``Panel``\s will now automatically lay out widgets vertically according to their current height. This allows you to have widgets dynamically change height or become visible/hidden and you don't have to worry about recalculating frame layouts
- ``widgets.ResizingPanel``: new ``Panel`` subclass that automatically recalculates it's own frame height based on the size, position, and visibility of its subviews
- ``safe_index`` now properly handles lua sparse tables that are indexed by numbers - ``safe_index`` now properly handles lua sparse tables that are indexed by numbers
# 0.47.05-r4 # 0.47.05-r4

@ -75,6 +75,8 @@ Panel = defclass(Panel, Widget)
Panel.ATTRS { Panel.ATTRS {
on_render = DEFAULT_NIL, on_render = DEFAULT_NIL,
on_layout = DEFAULT_NIL, on_layout = DEFAULT_NIL,
autoarrange_subviews = false, -- whether to automatically lay out subviews
autoarrange_gap = 0, -- how many blank lines to insert between widgets
} }
function Panel:init(args) function Panel:init(args)
@ -89,6 +91,50 @@ function Panel:postComputeFrame(body)
if self.on_layout then self.on_layout(body) end if self.on_layout then self.on_layout(body) end
end end
-- if self.autoarrange_subviews is true, lay out visible subviews vertically,
-- adding gaps between widgets according to self.autoarrange_gap.
function Panel:postUpdateLayout()
if not self.autoarrange_subviews then return end
local gap = self.autoarrange_gap
local y = 0
for _,subview in ipairs(self.subviews) do
subview.frame.t = y
if subview.visible then
y = y + subview.frame.h + gap
end
end
self.frame_rect.height = y
-- let widgets adjust to their new positions
self:updateSubviewLayout()
end
-------------------
-- ResizingPanel --
-------------------
ResizingPanel = defclass(ResizingPanel, Panel)
function ResizingPanel:init()
-- ensure we have a frame so a containing widget can read our dimensions
if not self.frame then self.frame = {} end
end
-- adjust our frame dimensions according to positions and sizes of our subviews
function ResizingPanel:postUpdateLayout(frame_body)
local w, h = 0, 0
for _,subview in ipairs(self.subviews) do
if subview.visible then
w = math.max(w, (subview.frame.l or 0) +
(subview.frame.w or frame_body.width))
h = math.max(h, (subview.frame.t or 0) +
(subview.frame.h or frame_body.height))
end
end
self.frame.w, self.frame.h = w, h
end
----------- -----------
-- Pages -- -- Pages --
----------- -----------