gfx/layout.h
FlexBox and Grid: two ways to place things without arithmetic in resized().
#include <sonore/gfx/layout.h>- 6types
- 2other declarations
- Guides: The native editor
On this page
Design notes
Why a plugin needs a layout system
Every layout in this SDK so far is hand-computed inside resized(): a row of knobs at kPadding + i * kRowHeight. That is fine for a row of knobs and it is not a layout system. The moment a plugin has a header, a body that should take the remaining height, and a footer pinned to the bottom, hand arithmetic becomes a set of subtractions that every subsequent change breaks.
It matters more here than in most toolkits because a plugin editor is RESIZED by the host, arbitrarily and at any moment, and a generated plugin's layout code was written by something that never saw it happen.
How faithful this is
FlexBox follows CSS flexbox for the parts a plugin uses: direction, grow, shrink, basis, wrap, justify, align, align-self, and align-content in its stretch form. The size resolution is CSS's real algorithm -- freeze an item that hits a limit, share what is left among the rest, repeat.
The first version of this file did NOT do that. It ran two passes and said so in a comment here, on the argument that two settle every layout a plugin has. They do not: an item capped by maxWidth beside an uncapped one leaves a third of the container unspent, which is not a pathological case but the ordinary one of a control with a sensible maximum next to a control without. The comment was wrong and the test that caught it was the second one written.
What is genuinely absent, and named rather than left to be found: the other five align-content values, order, and content-based sizing. There is nothing here to measure a component against, so an auto Grid track is sized the way the reference sizes it -- by the width or height an item in it was GIVEN -- and never by what the component inside would draw.
Types 6
Space kept clear around a FlexItem or a GridItem, in logical pixels: the item's box is laid out with it and the component placed inside it.
The constructors follow CSS's shorthand order -- one value for all four sides, then vertical and horizontal, then top, right, bottom, left -- so a margin copied from a design tool means the same thing here.
One thing in a FlexBox.
Carries a Component OR nothing: an item with no component is a SPACER, which is how a layout puts a gap somewhere without inventing an invisible child.
A row or a column, laid out like CSS flexbox.
performLayout() sets bounds on every item's component and leaves items with none alone -- so a spacer costs nothing and a caller can lay out a mix of real controls and gaps in one list.
A track in a Grid: a fixed size, a share of what is left, or sized by its items.
Fr is the one that matters. A plugin editor that has to fill whatever height a host gives it is a header, a 1fr body and a footer -- three lines instead of a page of subtractions that break on the next change.
One thing in a Grid, placed by track index. Spans are 1-based counts, not end indices: span 2 means two tracks, which is what CSS means by it.
Rows and columns, sized in pixels, in shares of what is left, or by the sizes their items were given.
Enums 2
- enum
enum class Justify2How the free space along the main axis is spent.gfx::Justify2 · layout.h:47 - enum
enum class AlignItemsHow an item sits across the axis it is not flowing along.gfx::AlignItems · layout.h:57