docs
Loading...
Searching...
No Matches
Containerabstract

#include <AppCore/layout/Container.h>

Overview

A layout node that organizes child nodes into a row or column.

Containers form the rows and columns of an AppCore window's layout tree. The window's root layout is a container that fills the entire window, and adding child rows or columns divides that space into a hierarchy of panes.

Each child can be a Panel that hosts a View, or another Container that splits space further. The library recalculates child sizes automatically whenever the window resizes or moves between displays with different scale factors.

The following example creates a resizable row with a sidebar and a content pane:

window->layout()->AddRow({ .key = "body", .resizable = true });
RefPtr<Panel> sidebar =
body->AddPanel({ .key = "sidebar", .size = "240px", .min_size = "160px" });
RefPtr<Panel> content = body->AddPanel({ .key = "content" });
sidebar->view()->LoadURL("file:///sidebar.html");
content->view()->LoadURL("file:///content.html");
A nullable smart pointer.
Definition RefPtr.h:126

Sizing Children

A container divides space along its main axis by first subtracting its padding and any gaps between children. It satisfies pixel sizes first, gives percentage sizes their shares of the free space left after pixel-sized children, and divides what remains among flexible children according to their flex factors. A child created without an explicit size defaults to one flex share (1fr). For what each size unit means, see Size and Length.

Containers also accept gap to separate adjacent children and padding to inset them from all four edges (both in logical pixels).

Resizable Containers

Setting resizable = true on a container places draggable dividers between its direct children. Dragging a divider resizes the panes on either side.

You can constrain how panes resize during a drag:

  • Set min_size to prevent a pane from collapsing.
  • Set fixed = true to keep a child's size constant.

Double-clicking a divider resets both neighboring children to their declared sizes.

You can customize divider appearance by passing a DividerStyle to SetDividerStyle().

Finding Children

Assigning a key in a child's creation options lets you look up that node across the container's subtree with Find(), FindPanel(), or FindContainer(). If multiple descendants share the same key, the lookup returns the newest match.

Reserving Space for Drawing

An empty container reserves space in the layout without hosting a View or rendering web content.

To track the container's bounds as the window resizes, register a layout change listener:

RefPtr<Container> viewport = body->AddColumn({ .key = "viewport" });
// The callback runs while viewport_tracker_ is kept.
viewport_tracker_ = viewport->OnLayoutChange([](LayoutNode& node) {
ResizeViewport(node.device_bounds());
});
Base class for Panels and Containers in a window layout tree.
Definition LayoutNode.h:108
virtual IntRect device_bounds() const =0
Get the node's rect from the most recent layout in window back-buffer device pixels (the space your o...

Overriding Child Layout

Call SetLayoutOverride() to install a layout delegate that positions direct children manually by calling LayoutNode::SetBounds(). The delegate runs whenever the window updates layout.

See also
LayoutNode, PanelOptions, ContainerOptions, Size, DividerStyle, Container::Build(), Window::BuildLayout()
Inheritance diagram for Container:
LayoutNode RefCounted

Classes

class  ChildIterator
 Iterator over a container's children (a forward range of RefPtr<LayoutNode>). More...
class  ChildRange
 A range over the container's children: More...

Public Member Functions

virtual RefPtr< Panel > AddPanel (const PanelOptions &options={}, InsertPosition position={})=0
 Create a panel with a new View (window-default view configuration).
virtual RefPtr< Panel > AddPanel (const PanelOptions &options, const ViewConfig &view_config, InsertPosition position={})=0
 Create a panel with a caller-supplied ViewConfig.
virtual RefPtr< Panel > AdoptPanel (RefPtr< View > view, const PanelOptions &options={}, InsertPosition position={})=0
 Create a panel that adopts an existing View (including a View created through a Session).
template<typename ViewRef>
requires std::convertible_to<ViewRef&&, RefPtr<View>>
RefPtr< Panel > AddPanel (ViewRef &&view, const PanelOptions &options={}, InsertPosition position={})
 Adopt an existing View (shorthand for AdoptPanel()).
virtual RefPtr< Container > AddRow (const ContainerOptions &options={}, InsertPosition position={})=0
 Create a child row container.
virtual RefPtr< Container > AddColumn (const ContainerOptions &options={}, InsertPosition position={})=0
 Create a child column container.
virtual bool Remove (RefPtr< LayoutNode > node)=0
 Remove a direct child (and, for a container child, its whole subtree) from the tree.
virtual void RemoveAll ()=0
 Remove every child.
virtual bool Move (RefPtr< LayoutNode > node, InsertPosition position={})=0
 Reorder a direct child within this container.
virtual int child_count () const =0
 Get the number of children.
virtual RefPtr< LayoutNode > child_at (int index) const =0
 Get the child at an index.
virtual RefPtr< LayoutNode > Find (const String &key)=0
 Find a descendant by key.
virtual RefPtr< Panel > FindPanel (const String &key)=0
 Find a descendant panel by key.
virtual RefPtr< Container > FindContainer (const String &key)=0
 Find a descendant container by key.
virtual void SetLayoutOverride (LayoutOverrideCallback callback, void *user_data=nullptr, LayoutDestroyUserDataCallback destroy_user_data=nullptr)=0
 Override this container's layout with a layout delegate.
virtual bool HasLayoutOverride () const =0
 Whether or not this container has a layout delegate installed.
virtual void SetDividerStyle (const DividerStyle &style)=0
 Set this container's divider style (see <AppCore/layout/DividerStyle.h>).
template<typename Callback>
requires std::invocable<Callback&, Container&, const Rect&> || std::invocable<Callback&, const Rect&>
void SetLayoutOverride (Callback callback)
 Install a layout delegate (invocable form).
ChildRange children () const
 Get a forward range over the children.
template<typename... Children>
requires (LayoutBuildable<Children> && ...)
RefPtr< Container > Build (Children... children)
 Append builder elements (see <AppCore/layout/Builder.h>) to this container.
Public Member Functions inherited from LayoutNode
virtual String key () const =0
 Get the node's key (empty if unkeyed).
virtual RefPtr< Container > parent () const =0
 Get the node's parent container (null at the root or when detached).
virtual int index () const =0
 Get the node's index within its parent (-1 when detached).
virtual RefPtr< Panel > AsPanel ()=0
 Get this node as a Panel (null if it is not one).
virtual RefPtr< Container > AsContainer ()=0
 Get this node as a Container (null if it is not one).
virtual void Hide ()=0
 Hide the node and redistribute its space to its siblings.
virtual void Show ()=0
 Show the node again, restoring its remembered size exactly.
virtual bool is_hidden () const =0
 Whether or not the node is hidden.
virtual Rect bounds () const =0
 Get the node's rect from the most recent layout in container-local logical pixels (the same space SetBounds() takes).
virtual IntRect device_bounds () const =0
 Get the node's rect from the most recent layout in window back-buffer device pixels (the space your own drawing uses).
virtual void SetBounds (const Rect &bounds)=0
 Place this node manually.
virtual void SetSize (Size size)=0
 Set the node's declared size along its container's axis.
virtual void SetMinSize (Length min_size)=0
 Set the node's minimum size constraint.
virtual void SetMaxSize (Length max_size)=0
 Set the node's maximum size constraint.
virtual LayoutCallback OnUserResize (LayoutNodeCallback callback, void *user_data, LayoutDestroyUserDataCallback destroy_user_data)=0
 Register a callback fired when the user resizes this node with a divider.
virtual LayoutCallback OnLayoutChange (LayoutNodeCallback callback, void *user_data, LayoutDestroyUserDataCallback destroy_user_data)=0
 Register a callback that fires after layout changes this node's bounds (at most once per frame).
template<typename Callback>
requires std::invocable<Callback&, LayoutNode&> || std::invocable<Callback&>
LayoutCallback OnUserResize (Callback callback)
 Register a user-resize callback (invocable form).
template<typename Callback>
requires std::invocable<Callback&, LayoutNode&> || std::invocable<Callback&>
LayoutCallback OnLayoutChange (Callback callback)
 Register a layout-change callback (invocable form).
RefPtr< LayoutNode > next_sibling () const
 Get the sibling after this node (null at the end, at the root, or when detached).
RefPtr< LayoutNode > previous_sibling () const
 Get the sibling before this node (null at the start, at the root, or when detached).
Public Member Functions inherited from RefCounted
virtual void AddRef () const =0
 Increment the reference count (thread-safe).
virtual void Release () const =0
 Decrement the reference count (thread-safe).
virtual int ref_count () const =0
 Get the current reference count.
virtual WeakControlBlock * weak_control_block () const
 Get the control block used to track weak references to this object.

Protected Member Functions

virtual ~Container ()
Protected Member Functions inherited from LayoutNode
virtual ~LayoutNode ()
Protected Member Functions inherited from RefCounted
virtual ~RefCounted ()

Constructor & Destructor Documentation

◆ ~Container()

virtual ~Container ( )
protectedvirtual

Member Function Documentation

◆ AddColumn()

virtual RefPtr< Container > AddColumn ( const ContainerOptions & options = {},
InsertPosition position = {} )
pure virtual

Create a child column container.

Parameters
optionsThe container's declared options.
positionWhere to insert the container (default: append at the end).
Returns
Returns the new container (see LayoutNode if this container was removed).

◆ AddPanel() [1/3]

virtual RefPtr< Panel > AddPanel ( const PanelOptions & options,
const ViewConfig & view_config,
InsertPosition position = {} )
pure virtual

Create a panel with a caller-supplied ViewConfig.

The fields describing the hosting window are filled in from the window for you. Every other field is yours:

  • initial_device_scale (the window's scale)
  • display_id (the window's display)
  • is_accelerated (whether the window composites on the GPU)

To host a deliberately CPU-rendered View on a GPU window, create the View with Renderer::CreateView() and use AdoptPanel().

Parameters
optionsThe panel's declared options.
view_configThe configuration for the new View. The window-describing fields listed above are overwritten.
positionWhere to insert the panel (default: append at the end).
Returns
Returns the new panel (see LayoutNode if this container was removed).

◆ AddPanel() [2/3]

virtual RefPtr< Panel > AddPanel ( const PanelOptions & options = {},
InsertPosition position = {} )
pure virtual

Create a panel with a new View (window-default view configuration).

Parameters
optionsThe panel's declared options.
positionWhere to insert the panel (default: append at the end).
Returns
Returns the new panel (see LayoutNode if this container was removed).

◆ AddPanel() [3/3]

template<typename ViewRef>
requires std::convertible_to<ViewRef&&, RefPtr<View>>
RefPtr< Panel > AddPanel ( ViewRef && view,
const PanelOptions & options = {},
InsertPosition position = {} )
inline

Adopt an existing View (shorthand for AdoptPanel()).

Parameters
viewThe View to host.
optionsThe panel's declared options.
positionWhere to insert the panel (default: append at the end).
Returns
Returns the new panel (see LayoutNode if this container was removed).

◆ AddRow()

virtual RefPtr< Container > AddRow ( const ContainerOptions & options = {},
InsertPosition position = {} )
pure virtual

Create a child row container.

Parameters
optionsThe container's declared options.
positionWhere to insert the container (default: append at the end).
Returns
Returns the new container (see LayoutNode if this container was removed).

◆ AdoptPanel()

virtual RefPtr< Panel > AdoptPanel ( RefPtr< View > view,
const PanelOptions & options = {},
InsertPosition position = {} )
pure virtual

Create a panel that adopts an existing View (including a View created through a Session).

The panel takes a reference to the View and resizes it to the panel's bounds.

Parameters
viewThe View to host.
optionsThe panel's declared options.
positionWhere to insert the panel (default: append at the end).
Returns
Returns the new panel (see LayoutNode if this container was removed).
Note
The panel replaces the View's editor listener with its own (see Panel).

◆ Build()

template<typename... Children>
requires (LayoutBuildable<Children> && ...)
RefPtr< Container > Build ( Children... children)
inline

Append builder elements (see <AppCore/layout/Builder.h>) to this container.

Build appends, so calling twice appends twice. For a fresh start, call RemoveAll() first.

Parameters
childrenThe builder elements to append, in order.
Returns
Returns this container, so the builder line composes with follow-up calls.

◆ child_at()

virtual RefPtr< LayoutNode > child_at ( int index) const
pure virtual

Get the child at an index.

Parameters
indexThe zero-based index within this container's child list.
Returns
Returns the child, or null when the index is out of range.

◆ child_count()

virtual int child_count ( ) const
pure virtual

Get the number of children.

◆ children()

ChildRange children ( ) const
inline

Get a forward range over the children.

◆ Find()

virtual RefPtr< LayoutNode > Find ( const String & key)
pure virtual

Find a descendant by key.

Parameters
keyThe key to look for.
Returns
Returns the matching node, or null when nothing matches. With duplicate keys the most recently created match wins.

◆ FindContainer()

virtual RefPtr< Container > FindContainer ( const String & key)
pure virtual

Find a descendant container by key.

Parameters
keyThe key to look for.
Returns
Returns the matching container, or null when nothing matches or the match is not a container.

◆ FindPanel()

virtual RefPtr< Panel > FindPanel ( const String & key)
pure virtual

Find a descendant panel by key.

Parameters
keyThe key to look for.
Returns
Returns the matching panel, or null when nothing matches or the match is not a panel.

◆ HasLayoutOverride()

virtual bool HasLayoutOverride ( ) const
pure virtual

Whether or not this container has a layout delegate installed.

◆ Move()

virtual bool Move ( RefPtr< LayoutNode > node,
InsertPosition position = {} )
pure virtual

Reorder a direct child within this container.

A node from a different container (or window) is a no-op with a warning. A position anchor that is not a direct child falls back to the end, also with a warning.

Parameters
nodeThe direct child to move.
positionThe new position (default: move to the end).
Returns
Returns whether or not the node was reordered.

◆ Remove()

virtual bool Remove ( RefPtr< LayoutNode > node)
pure virtual

Remove a direct child (and, for a container child, its whole subtree) from the tree.

Removal detaches the child and drops each removed panel's reference to its View. A View the application holds a RefPtr to survives removal and can be adopted into another panel or window. For what removed handles do afterwards, see LayoutNode.

Parameters
nodeThe direct child to remove.
Returns
Returns whether or not the node was a direct child and was removed.

◆ RemoveAll()

virtual void RemoveAll ( )
pure virtual

Remove every child.

Equivalent to Remove() on each child in turn.

◆ SetDividerStyle()

virtual void SetDividerStyle ( const DividerStyle & style)
pure virtual

Set this container's divider style (see <AppCore/layout/DividerStyle.h>).

Fields left unset fall back to the window's style (Window::SetDividerStyle()), then to the built-in defaults.

Parameters
styleThe style to apply. A default-constructed style clears the override.

◆ SetLayoutOverride() [1/2]

template<typename Callback>
requires std::invocable<Callback&, Container&, const Rect&> || std::invocable<Callback&, const Rect&>
void SetLayoutOverride ( Callback callback)
inline

Install a layout delegate (invocable form).

Parameters
callbackAny invocable. It may take (Container&, const Rect&) (the container and its content box), or just (const Rect&).

◆ SetLayoutOverride() [2/2]

virtual void SetLayoutOverride ( LayoutOverrideCallback callback,
void * user_data = nullptr,
LayoutDestroyUserDataCallback destroy_user_data = nullptr )
pure virtual

Override this container's layout with a layout delegate.

The delegate runs each time the window performs layout (after a layout change, a resize, or a display scale change), but never while the container has no children.

The delegate positions the container's direct children by calling LayoutNode::SetBounds():

grid->SetLayoutOverride([](Container& c, const Rect& content_box) {
float x = content_box.x(), y = content_box.y(), w = content_box.width();
c.child_at(0)->SetBounds(Rect::FromXYWH(x, y, w, 40));
Rect::FromXYWH(x, y + 40, w, content_box.height() - 40));
});
A layout node that organizes child nodes into a row or column.
Definition Container.h:101
virtual RefPtr< LayoutNode > child_at(int index) const =0
Get the child at an index.
virtual void SetBounds(const Rect &bounds)=0
Place this node manually.
Float Rectangle Helper.
Definition Geometry.h:416
float y() const
Definition Geometry.h:431
float height() const
Definition Geometry.h:429
float x() const
Definition Geometry.h:430
float width() const
Definition Geometry.h:428
static constexpr Rect FromXYWH(float x, float y, float width, float height)
Create a Rect from an origin and a size (the DOMRect / CSS box convention).
Definition Geometry.h:424

content_box is the container's content box (inside its padding) in container-local logical pixels.

Placed rectangles are snapped and clipped to this box.

A placed rectangle persists until the delegate places that child again– the delegate may place only what changed.

Children that the delegate has never placed occupy no region.

Changing the tree from inside the delegate is allowed.

Setting a new delegate replaces the existing one, and every child resets to never-placed.

Replacing the delegate destroys the previous delegate's user data. If replaced from inside the delegate, destruction is deferred until the delegate returns.

Parameters
callbackThe delegate to install. Pass nullptr to restore ordinary layout.
user_dataPassed back to the delegate on every run (can be nullptr).
destroy_user_dataCalled once when the delegate drops user_data (can be nullptr).
Note
resizable is ignored (with a warning) while a container has a layout delegate. Dividers only exist between children that the container itself lays out.
Note
Callbacks must not let exceptions propagate.

The documentation for this class was generated from the following file: