ml::docs | Your First App Manifests Events Messaging Plugins Scenes Resources
See all tutorials →
Beginner 5 sections ~10 min C++17/20

Alignment & Anchors

Place things relative to the window or to each other — and have that placement survive a resize. Retained anchors are live constraints, not one-time calculations.

Introduction

Two Ways to Place Something

Malena has two ways to place things relative to something else, and the difference matters more than it first appears.

ml::AlignRetained anchors
What it isFree functions that compute a positionLive constraints stored on the object
When it runsOnce, when you call itEvery time the window changes
Survives a resizeNoYes
Use forOne-off placement, non-component objectsLayout that must stay correct
If you have used Align::centerOn and found your layout wrong after the user resized the window, retained anchors are the answer. They were added precisely because computing a position once is not the same as meaning it.
1Anchors

Anchoring to the Window

Anchors are declared on the object and re-solved whenever the window changes size.

title.centerXInWindow();          // stays centred through any resize
title.anchorTopInWindow(24.f);    // 24px below the top edge, always

settingsBtn.anchorRightInWindow(16.f);
settingsBtn.anchorBottomInWindow(16.f);
MethodEffect
centerInWindow()Centre on both axes.
centerXInWindow(offset)Centre horizontally, plus an offset in pixels.
centerYInWindow(offset)Centre vertically, plus an offset.
anchorLeftInWindow(margin)Pin the left edge, margin px inward.
anchorRightInWindow(margin)Pin the right edge.
anchorTopInWindow(margin)Pin the top edge.
anchorBottomInWindow(margin)Pin the bottom edge.
unanchored()Drop every anchor, freezing the object where it currently sits.

Anchors compose. Pinning right and bottom puts an object in the corner and keeps it there.

Anchors are retained by default — the relative-layout helpers record a live constraint rather than a one-time calculation. This is the behaviour you almost always want, which is why it is the default rather than an opt-in.
2The Rule

setPosition Detaches

There is one rule to internalise, and it explains most surprises:

A direct setPosition detaches the object's anchors. Manual control wins. If you place something by hand, Malena stops moving it for you.
panel.centerInWindow();            // anchored
panel.setPosition({10.f, 10.f});   // anchor dropped — panel now stays at 10,10

panel.centerInWindow();            // re-anchor it if you want that back

This is what makes dragging work. A user drags a panel, Draggable calls setPosition, the anchor detaches, and the panel stays where they put it — including after the next resize. You get that for free.

To freeze an object deliberately without moving it, call unanchored():

tooltip.centerInWindow();
tooltip.unanchored();   // keeps its current place, but stops tracking the window
3One-shot

ml::Align for One-off Placement

ml::Align is the one-shot form. It computes a position now and does not remember anything, which makes it right for objects that are not Malena components at all — a raw sf::Text, an sf::Sprite, anything with bounds.

ml::Align::centerOn(panel, label);            // centre label on panel
ml::Align::centerHorizontally(panel, label);  // one axis only
ml::Align::centerVertically(panel, label);

The reference can be a component, an sf::FloatRect, or a bare size:

ml::Align::centerOn(sf::FloatRect({0,0}, {800,600}), sprite);
ml::Align::centerOn(sf::Vector2f{800.f, 600.f}, sprite);   // size anchored at the origin
Align::centerText exists for the common case of centring an sf::Text on an object, which needs the text's local bounds rather than its global ones to look right.
4Relative

Placing Objects Against Each Other

Objects can also be placed relative to each other, which is how rows and stacks are usually built.

nameField.setBelow(nameLabel, 6.f);      // 6px under the label
submitBtn.setBelow(nameField, 16.f);
cancelBtn.setRightOf(submitBtn, 8.f);

These are retained too, so a chain of them re-solves in order when the window changes. Move the first element and everything downstream follows.

Prefer a Grid or Panel when you are laying out many children in a regular structure — relative helpers are for the handful of relationships a layout container cannot express naturally.