UI Core

The core UI types define the runtime, the surface tree, and the layout constraints shared by all higher-level UI components.

Important

The UI Framework is currently in beta, and parts of the API may change in future releases.

Usage

Building a Surface Tree

A UI app usually creates one page, adds a small hierarchy of surfaces, and then hands the tree to Application. For compact examples, the application can be a direct local instance.

using namespace erbsland::cterm;
using namespace erbsland::cterm::ui;

auto page = Page::create();
auto root = Stack::create(Orientation::Vertical);
auto body = TextBox::create("Ready", Alignment::Center);

body->editLayoutMetrics().setSizePolicy(SizePolicy{SizePolicy::Grow});
root->addSurface(body);
page->addSurface(root);

auto app = Application{};
app.setMainPage(page);
return app.run();

Applications that parse command line arguments or load data for the UI usually subclass Application and build the tree in Application::setupUi(). During startup, command line arguments are processed after the terminal is initialized and before the display and event system are created, so processCommandLineArguments() can attach loaded data to surfaces created by setupUi().

Working with Layout Metrics and Invalidation

Each surface owns a LayoutMetrics object with minimum, preferred, and maximum size hints plus a size policy for both axes. These sizes always describe the margin-free content rectangle. The same metrics object can also recommend outer margins; these margins are not part of the sizes and are always clamped to zero or positive values when stored in LayoutMetrics. You read it with Surface::layoutMetrics() and change it through Surface::editLayoutMetrics(). The editor keeps the layout invalidation rule in one place, so the next display pass can recompute layout after a real metrics change.

auto header = TextBox::create("Title", Alignment::Center);
auto body = Panel::create();

header->editLayoutMetrics().setFixedHeight(1);
body->editLayoutMetrics().setSizePolicy(SizePolicy{SizePolicy::Grow});
body->editLayoutMetrics().setMargins(Margins{1, 2});

body->flags().setPaintOutdated();

When something changes:

Theme changes through an application or page automatically mark the affected tree as layout- and paint-outdated. Dynamic theme-attribute changes on a surface are intentionally explicit: update surface->themeAttributes() and then call surface->flags().setThemeOutdated() when the change should be reflected immediately. This matters because themed block margins can change the usable content rectangle, not only the colors on screen.

This keeps updates local and avoids redrawing unchanged parts of the surface tree.

Showing and Hiding Surfaces

Every Surface has local visibility. Hidden surfaces stay in the tree and keep their current rectangle, but display traversal, layout traversal, and focus/key routing skip them.

auto details = ui::Panel::create();

details->flags().setVisible(false);
details->flags().setVisible(true);

if (details->flags().isVisibleInTree()) {
    details->flags().setPaintOutdated();
}

flags().isVisible() reports only the local flag. flags().isVisibleInTree() also checks all ancestors. This is the predicate used by focus routing and visible-rectangle calculation.

Showing or hiding a surface invalidates layout and damages the old parent area so the display can repaint the cells that changed. Scheduled actions are deliberately not filtered by visibility; hidden surfaces can still update state and show themselves later.

Keyboard Focus

Focus is explicit. A surface becomes eligible for direct keyboard focus after you call SurfaceFlags::setFocusable(true). Interactive controls do this themselves. You can move focus with Surface::requestFocus() or Page::focusTo().

The focused surface receives key events first, then its ancestors, then the page. Ancestors on the active path report SurfaceFlags::hasFocusWithin(); the leaf also reports SurfaceFlags::hasFocus(). The framework keeps the theme states Focused and FocusWithin in sync and calls onFocus() only when the effective relation changes.

Mutable Surface State

Surface keeps the tree, geometry, scheduler, actions, events, and focus request command small and direct. Mutable state that describes how the surface participates in rendering and focus traversal lives in SurfaceFlags and is accessed through surface->flags().

Use SurfaceFlags for local visibility, focusability, enabled, selected, and checked state, as well as paint, layout, and theme invalidation. flags().themeStates() derives the resolved theme states from the current flags, including Focused, FocusWithin, Disabled, Selected, and Checked.

Theme selector data that is normally configured once belongs to SurfaceThemeAttributes and is accessed through surface->themeAttributes(). Built-in surfaces set their element in their constructor. Custom surfaces should do the same, either by calling a theme-aware Surface constructor or by updating themeAttributes() before the surface is displayed.

Managing Child Containers

Surface::surfaces() returns AbstractSurfaceContainer. Surfaces store their children in SurfaceContainer, which supports add, insert, replace, remove, and move operations. The container keeps parent links, reparenting, cycle checks, layout invalidation, and focus cleanup in one place.

Layouts can attach a SurfaceManager to their container. The manager does not replace the container; it only validates and observes structural changes. This keeps generic code useful while still allowing a layout to say, for example, “I accept at most one child” or “this child needs default metadata”.

For single-content layouts such as Centered, Frame, and Viewport, both forms below are valid when the layout is empty:

auto viewport = ui::Viewport::create();
auto content = ui::TextBox::create("Long text");

viewport->setContentSurface(content);
viewport->surfaces().remove(content);
viewport->surfaces().add(content);

Adding a second child to such a layout throws, because it would violate the layout’s real invariant. Removing the only child is accepted and leaves the layout in a stable empty state.

Some surfaces still protect implementation-owned children. ScrollArea owns its viewport, scroll bars, and scroll corner internally. You configure its user content with setContentSurface(), but you should not remove or reorder the scroll area’s internal child surfaces through surfaces().

When a layout needs metadata per child, it stores that metadata as LayoutData on the parent-child relation. Sections uses this mechanism for section titles and right-side text. Generic surfaces().add() creates default empty section options, while addSection(surface, options) attaches explicit metadata.

Reference

Application &erbsland::cterm::ui::getApplication()

Access the global application instance.

Calling this method is thread-safe and can be used to post events from other threads.

Warning

If you make calls from other threads, ensure that the application has been constructed and is not shutting down. You must make sure that your threads are terminated, before the application instance is destroyed. Do this by adding wait or join at the end of main or similar functions.

Throws:

std::logic_error – if no application instance exists.

class Application

UI Application instance for event-driven UI applications.

Public Types

using ExitCode = int

The type for the exit code.

using CommandLineArgs = std::vector<std::string>

A list of command line arguments.

Public Functions

Application()

Create a new UI application using the default Terminal backend.

Application(int argc, char *argv[])

Create a new UI application using the default Terminal backend.

Stores the command line arguments.

Parameters:
  • argc – The number of command line arguments

  • argv – The command line arguments

explicit Application(TerminalPtr terminal)

Create a new UI application using a custom Terminal backend.

Parameters:

terminal – The terminal backend to use. Must not be null.

explicit Application(int argc, char *argv[], TerminalPtr terminal)

Create a new UI application using a custom Terminal backend.

Stores the command line arguments.

Parameters:
  • argc – The number of command line arguments

  • argv – The command line arguments

  • terminal – The terminal backend to use. Must not be null.

virtual ~Application()

dtor

void setMainPage(PagePtr page)

Set the main page for this application.

The main page is automatically registered as the initial page in the display, just before the event loop starts.

void setTheme(const theme::ThemeConstPtr &theme)

Replace the application theme.

Parameters:

theme – The new theme. A null pointer restores the default dark theme.

const theme::ThemeConstPtr &theme() const noexcept

Access the application theme.

Returns:

The active application theme.

const CommandLineArgs &commandLineArgs() const

Access the command line arguments.

Terminal &terminal() const

Access the terminal instance.

Warning

Only access and manipulate the terminal from the main thread that owns this application.

Display &display() const

Access the display instance.

Warning

Only access and manipulate the display from events!

ExitCode run()

Run the application event loop.

This will initialize the terminal and start the event loop. If the event loop exits, the screen is restored. Any exception from the event loop will be propagated.

Returns:

The exit code of the application.

bool isShuttingDown() const

Test if this application is shutting down.

void addEvent(EventType eventType, EventDataUniquePtr &&eventData)

Add an event to the event loop.

If the application is shutting down, this call is ignored.

Parameters:
  • eventType – The event type.

  • eventData – The event data.

void invoke(std::function<void()> invokedFn)

Queue one callback on the application UI thread.

Parameters:

invokedFn – The callback to execute on the UI thread.

Throws:

std::logic_error – If the application event system is not active anymore.

EventThreadPtr createEventThread()

Create one managed background event thread.

The application automatically stops managed event threads during shutdown.

Throws:

std::logic_error – If the application event system is not active anymore.

Returns:

The started event thread.

void quit(ExitCode exitCode = 0)

Quit the application.

This will schedule a quit event and exit the event loop as soon as all scheduled events up to this quit event are processed.

void abort()

Abort the application.

This aborts the application as soon as possible. Events in the event loop are not processed.

Note

Use quit() to exit the application gracefully.

ExitCode manualInitialize()

Initialize the application.

Note

Only use this method if you need to drive the event loop manually.

Throws:

Any – exception that may occur during initialization.

Returns:

cExitCodeContinue if everything is ok and the application shall go into the event loop. Any other value is a return value to use when exiting the application. Before exiting the application, manualShutdown() must be called.

ExitCode manualProcessEvents()

Refresh the Display, read input and process events.

Note

Only use this method if you need to drive the event loop manually.

Throws:

std::exception – Any exception that may occur during run.

Returns:

cExitCodeContinue if everything is ok and the loop shall continue. Any other value is a return value to use when exiting the application. Before exiting the application, manualShutdown() must be called.

void manualShutdown()

Shutdown the application.

Note

Only use this method if you need to drive the event loop manually. This method must be called before exiting the application in every case.

Public Static Attributes

static constexpr auto cExitCodeContinue = std::numeric_limits<ExitCode>::min() + 2

Special value to indicate that the event loop shall continue.

class Display

A display is a way to show pages on a terminal.

Public Functions

explicit Display(TerminalPtr terminal, PagePtr mainPage)

Create a new display instance.

Parameters:
  • terminal – The terminal to use.

  • mainPage – The main page to show initially.

explicit Display(TerminalPtr terminal, PagePtr mainPage, SizeLimits sizeLimits)

Create a new display instance with explicit size limits.

Parameters:
  • terminal – The terminal to use.

  • mainPage – The main page to show initially.

  • sizeLimits – The size limits for this display.

explicit Display(TerminalPtr terminal, PagePtr mainPage, theme::ThemeConstPtr theme)

Create a new display instance with an explicit theme scope.

Parameters:
  • terminal – The terminal to use.

  • mainPage – The main page to show initially.

  • theme – The application theme.

explicit Display(TerminalPtr terminal, PagePtr mainPage, theme::ThemeConstPtr theme, SizeLimits sizeLimits)

Create a new display instance with an explicit theme scope and size limits.

Parameters:
  • terminal – The terminal to use.

  • mainPage – The main page to show initially.

  • theme – The application theme.

  • sizeLimits – The size limits for this display.

void pushPage(PagePtr page)

Push a new page to the page stack.

Throws:

std::logic_error – If you push more than 20 pages or a duplicate page to the stack.

void popPage()

Pop the top page from the page stack.

Throws:

std::logic_error – If you try to pop the main page from the stack.

void pollTerminalResize()

Poll for terminal size changes.

void pollRender()

Poll for render work.

This triggers a render for visible dirty pages as soon as the minimum render interval allows it.

EventTime nextWakeTime() const noexcept

Get the earliest next wake-up time required by the display.

Returns:

The earliest wake-up time.

void onKeyPress(KeyPressEvent &keyPressEvent) noexcept

Forward a key press to the active page.

Parameters:

keyPressEvent – The key press event to forward.

void setTheme(const theme::ThemeConstPtr &theme)

Replace the display theme.

Parameters:

theme – The new theme. A null pointer restores the default dark theme.

void setMinimumDisplaySize(Size minimumDisplaySize)

Set the minimum display size for the application.

If the terminal size is smaller, the display is cropped and crop marks indicate to increase the terminal size.

void setHardMinimumDisplaySize(Size hardMinimumDisplaySize)

Set the hard minimum display size for the application.

If the terminal size is smaller than this hard limit, no UI is displayed - just a warning.

struct SizeLimits

Display size limits used to protect interactive applications from unusably small terminals.

Public Members

Size minimumDisplaySize = {cMinimumDisplaySize}

The size where crop marks start.

Size hardMinimumDisplaySize = {cHardMinimumDisplaySize}

The size where only the warning is rendered.

class DimensionPolicy

The size policy of a single surface dimension.

The resolved size should always stay within minimum <= value <= maximum.

Public Types

enum Type

The supported dimension policy strategies.

Values:

enumerator Preferred

Use the preferred size and only grow or shrink if necessary.

enumerator Grow

Start with the preferred size and grow as much as possible.

enumerator Shrink

Start with the preferred size and shrink as much as possible.

Public Functions

DimensionPolicy() = default

Create the default preferred policy with factor 1.

inline constexpr DimensionPolicy(const Type type, const int factor = 1) noexcept

Create a policy with explicit type and distribution factor.

Parameters:
  • type – The policy type.

  • factor – The relative factor used when distributing extra space or shrinkage.

bool operator==(const DimensionPolicy &other) const noexcept = default

Compare two dimension policies.

bool operator!=(const DimensionPolicy &other) const noexcept = default

Compare two dimension policies.

inline Type type() const noexcept

Get the policy type.

Returns:

The configured policy type.

inline void setType(const Type type) noexcept

Set the policy type.

Parameters:

type – The new policy type.

inline int factor() const noexcept

Get the relative distribution factor.

Returns:

The configured factor.

inline void setFactor(const int factor) noexcept

Set the relative distribution factor.

Parameters:

factor – The new factor.

class SizePolicy

The size policy for both width and height of a surface.

Public Types

using Type = DimensionPolicy::Type

Shortcut for the dimension policy type enum.

Public Functions

SizePolicy() = default

Create the default preferred policy for both dimensions.

inline explicit constexpr SizePolicy(const DimensionPolicy size) noexcept

Create a uniform size policy for both dimensions.

Parameters:

size – The policy to use for width and height.

inline constexpr SizePolicy(const DimensionPolicy width, const DimensionPolicy height) noexcept

Create explicit policies for width and height.

Parameters:
  • width – The width policy.

  • height – The height policy.

bool operator==(const SizePolicy &other) const noexcept = default

Compare two size policies.

bool operator!=(const SizePolicy &other) const noexcept = default

Compare two size policies.

inline DimensionPolicy width() const noexcept

Get the width policy.

Returns:

The width policy.

inline void setWidth(const DimensionPolicy width) noexcept

Set the width policy.

Parameters:

width – The new width policy.

inline DimensionPolicy height() const noexcept

Get the height policy.

Returns:

The height policy.

inline void setHeight(const DimensionPolicy height) noexcept

Set the height policy.

Parameters:

height – The new height policy.

Public Static Attributes

static constexpr auto Preferred = Type::Preferred

Preferred size without active growth or shrink behavior.

static constexpr auto Grow = Type::Grow

Prefer to grow when extra space is available.

static constexpr auto Shrink = Type::Shrink

Prefer to shrink when space is constrained.

class LayoutMetrics

The measured and configured layout metrics of a surface.

The minimum, maximum, and preferred sizes describe the surface content rectangle, excluding margins. Margins are non-negative recommendations for parent-owned outer spacing. Parent layouts decide whether and how to apply or propagate them.

Public Functions

LayoutMetrics() = default

Create layout metrics with default limits, preferred size, and size policy.

inline constexpr LayoutMetrics(const Size minimum, const Size maximum, const Size preferred, const SizePolicy policy, const Margins margins = {}) noexcept

Create explicit layout metrics.

Parameters:
  • minimum – The minimum size.

  • maximum – The maximum size.

  • preferred – The preferred size.

  • policy – The size policy.

  • margins – The recommended outer margins. Negative values are clamped to zero.

inline const Size &minimum() const noexcept

Get the minimum size.

inline void setMinimum(const Size &size) noexcept

Set the minimum size.

inline void setMinimumHeight(Coordinate height) noexcept

Set the minimum height.

inline void setMinimumWidth(Coordinate width) noexcept

Set the minimum width.

inline const Size &maximum() const noexcept

Get the maximum size.

inline void setMaximum(const Size &size) noexcept

Set the maximum size.

inline void setMaximumHeight(Coordinate height) noexcept

Set the maximum height.

inline void setMaximumWidth(Coordinate width) noexcept

Set the maximum width.

inline const Size &preferred() const noexcept

Get the preferred size.

inline void setPreferred(const Size &size) noexcept

Set the preferred size.

inline void setPreferredHeight(Coordinate height) noexcept

Set the preferred height.

inline void setPreferredWidth(Coordinate width) noexcept

Set the preferred width.

inline const SizePolicy &sizePolicy() const noexcept

Get the size policy.

inline void setSizePolicy(const SizePolicy &policy) noexcept

Set the size policy for both dimensions.

inline void setSizePolicy(const DimensionPolicy::Type &policy) noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline void setSizePolicyForWidth(DimensionPolicy::Type policyType, int factor = 1) noexcept

Set the width size policy.

inline void setSizePolicyForHeight(DimensionPolicy::Type policyType, int factor = 1) noexcept

Set the height size policy.

void setFixedHeight(Coordinate height) noexcept

Fix the height to a single value.

void setFixedWidth(Coordinate width) noexcept

Fix the width to a single value.

void setFixedSize(Size size) noexcept

Fix both dimensions to a single size.

inline const Margins &margins() const noexcept

Get the recommended outer margins.

Margins are always zero or positive and are not part of the layout sizes.

inline void setMargins(Margins margins) noexcept

Replace the recommended outer margins.

Negative sides are clamped to zero.

Size resolvedSize(const LayoutProposal &proposal) const noexcept

Resolve a concrete size for this metrics object against a proposal.

class LayoutMetricsEditor

Edit the layout metrics of a surface and invalidate layout when they change.

Public Functions

inline explicit constexpr LayoutMetricsEditor(Surface &surface) noexcept

Create a layout metrics editor for a surface.

Parameters:

surface – The surface whose layout metrics are edited.

LayoutMetricsEditor &setMinimumSize(Size size)

Replace the minimum size.

Parameters:

size – The new minimum size.

LayoutMetricsEditor &setMinimumWidth(Coordinate width)

Replace the minimum width.

Parameters:

width – The new minimum width.

LayoutMetricsEditor &setMinimumHeight(Coordinate height)

Replace the minimum height.

Parameters:

height – The new minimum height.

LayoutMetricsEditor &setMaximumSize(Size size)

Replace the maximum size.

Parameters:

size – The new maximum size.

LayoutMetricsEditor &setMaximumWidth(Coordinate width)

Replace the maximum width.

Parameters:

width – The new maximum width.

LayoutMetricsEditor &setMaximumHeight(Coordinate height)

Replace the maximum height.

Parameters:

height – The new maximum height.

LayoutMetricsEditor &setPreferredSize(Size size)

Replace the preferred size.

Parameters:

size – The new preferred size.

LayoutMetricsEditor &setPreferredWidth(Coordinate width)

Replace the preferred width.

Parameters:

width – The new preferred width.

LayoutMetricsEditor &setPreferredHeight(Coordinate height)

Replace the preferred height.

Parameters:

height – The new preferred height.

LayoutMetricsEditor &setSizePolicy(SizePolicy policy)

Replace the size policy.

Parameters:

policy – The new size policy.

LayoutMetricsEditor &setSizePolicy(DimensionPolicy::Type policy)

Replace both size policies with the same policy type.

Parameters:

policy – The new policy type.

LayoutMetricsEditor &setSizePolicyForWidth(DimensionPolicy::Type policyType, int factor = 1)

Replace the width size policy.

Parameters:
  • policyType – The new width policy type.

  • factor – The relative distribution factor.

LayoutMetricsEditor &setSizePolicyForHeight(DimensionPolicy::Type policyType, int factor = 1)

Replace the height size policy.

Parameters:
  • policyType – The new height policy type.

  • factor – The relative distribution factor.

LayoutMetricsEditor &setFixedWidth(Coordinate width)

Fix the width to a single value.

Parameters:

width – The fixed width.

LayoutMetricsEditor &setFixedHeight(Coordinate height)

Fix the height to a single value.

Parameters:

height – The fixed height.

LayoutMetricsEditor &setFixedSize(Size size)

Fix both dimensions to a single size.

Parameters:

size – The fixed size.

LayoutMetricsEditor &setMargins(Margins margins)

Replace the recommended outer margins.

Parameters:

margins – The new margins. Negative sides are clamped to zero.

class LayoutProposal

A proposed size passed to measurement.

Public Functions

LayoutProposal() = default

Create an unconstrained proposal.

inline constexpr LayoutProposal(LayoutDimension width, LayoutDimension height) noexcept

Create a proposal from explicit dimensions.

Parameters:
  • width – The width proposal.

  • height – The height proposal.

inline constexpr LayoutDimension width() const noexcept

Access the width proposal.

inline constexpr LayoutDimension height() const noexcept

Access the height proposal.

inline constexpr LayoutProposal withWidth(LayoutDimension width) const noexcept

Create a copy with a different width proposal.

Parameters:

width – The new width proposal.

inline constexpr LayoutProposal withHeight(LayoutDimension height) const noexcept

Create a copy with a different height proposal.

Parameters:

height – The new height proposal.

inline constexpr Size maximumSize() const noexcept

Convert all bounded dimensions to a size, using Size::maximum() for unbounded dimensions.

Public Static Functions

static inline constexpr LayoutProposal unconstrained() noexcept

Create an unconstrained proposal.

static inline constexpr LayoutProposal atMost(Size size) noexcept

Create a proposal that bounds both dimensions by the given size.

Parameters:

size – The maximum available size.

static inline constexpr LayoutProposal exact(Size size) noexcept

Create a proposal with an exact size.

Parameters:

size – The exact size.

class LayoutDimension

A layout proposal for one dimension.

Public Types

enum class Type : uint8_t

The kind of proposed size.

Values:

enumerator Unspecified

No limit is known for this dimension.

enumerator AtMost

The surface may use up to the stored size.

enumerator Exact

The surface is measured for exactly the stored size.

Public Functions

LayoutDimension() = default

Create an unspecified proposal.

inline constexpr LayoutDimension(const Type type, const Coordinate value) noexcept

Create a proposal with explicit type and value.

Parameters:
  • type – The proposal type.

  • value – The proposed size, clamped to zero or larger.

inline constexpr bool isUnspecified() const noexcept

Test if this proposal is unspecified.

inline constexpr bool isAtMost() const noexcept

Test if this proposal is upper-bounded.

inline constexpr bool isExact() const noexcept

Test if this proposal is exact.

inline constexpr bool hasBound() const noexcept

Test if this proposal carries a usable bound.

inline constexpr Type type() const noexcept

Access the proposal type.

inline constexpr Coordinate value() const noexcept

Access the stored size. The value is meaningful only when hasBound() is true.

inline constexpr Coordinate valueOr(Coordinate fallback) const noexcept

Access the stored size or a fallback for unspecified proposals.

Parameters:

fallback – The fallback value.

Coordinate resolve(Coordinate minimum, Coordinate maximum, Coordinate preferred, DimensionPolicy policy) const noexcept

Resolve this proposal against one dimension’s layout metrics.

Parameters:
  • minimum – The minimum size.

  • maximum – The maximum size.

  • preferred – The preferred size.

  • policy – The size policy.

Returns:

The resolved size.

Public Static Functions

static inline constexpr LayoutDimension unspecified() noexcept

Create an unspecified proposal.

static inline constexpr LayoutDimension atMost(Coordinate value) noexcept

Create an upper-bounded proposal.

Parameters:

value – The upper bound.

static inline constexpr LayoutDimension exact(Coordinate value) noexcept

Create an exact proposal.

Parameters:

value – The exact size.

class MeasureScope

Gives a surface access to framework-driven child measurement.

Public Types

using MeasureFunction = std::function<LayoutMetrics(const SurfacePtr&, const LayoutProposal&)>

The function used to measure one surface.

Public Functions

MeasureScope() = default

Create a scope without measurement support.

explicit MeasureScope(MeasureFunction measureFunction, ThemeContext themeContext = {}) noexcept

Create a scope with a measurement callback.

Parameters:

measureFunction – The callback used by measure().

LayoutMetrics measure(const SurfacePtr &surface, const LayoutProposal &proposal) const noexcept

Measure a child surface for a proposal.

Parameters:
  • surface – The surface to measure.

  • proposal – The proposed size.

Returns:

The measured metrics, or empty metrics for null surfaces.

inline const ThemeContext &themeContext() const noexcept

Access the theme context of the surface currently being measured.

inline theme::ThemeAccessor theme() const noexcept

Access the theme of the surface currently being measured.

class LayoutScope

Gives a surface access to its assigned size plus framework-driven child placement.

Public Types

using PlaceFunction = std::function<void(const SurfacePtr&, Rectangle)>

The function used to place one child surface.

Public Functions

LayoutScope() = default

Create an empty layout scope.

LayoutScope(Size size, ThemeContext themeContext, MeasureScope::MeasureFunction measureFunction, PlaceFunction placeFunction) noexcept

Create a layout scope.

Parameters:
  • size – The assigned size of the surface being laid out.

  • themeContext – The resolved theme context.

  • measureFunction – The callback used by measure().

  • placeFunction – The callback used by place().

inline Size size() const noexcept

Access the assigned size of the current surface.

inline const ThemeContext &themeContext() const noexcept

Access the resolved theme context of the current surface.

inline theme::ThemeAccessor theme() const noexcept

Access the theme of the current surface.

LayoutMetrics measure(const SurfacePtr &surface, const LayoutProposal &proposal) const noexcept

Measure a child surface for a proposal.

void place(const SurfacePtr &surface, Rectangle rectangle) const noexcept

Place a child surface at a local rectangle.

Parameters:
  • surface – The child surface.

  • rectangle – The rectangle in the current surface’s local coordinates.

class PaintContext

The paint context for the onPaint method.

Public Functions

inline PaintContext(const Rectangle surfaceRect, const Rectangle visibleRect, const Rectangle dirtyRect, ThemeContext themeContext) noexcept

Create a paint context for a clipped paint operation.

Parameters:
  • surfaceRect – The full local rectangle of the surface.

  • visibleRect – The visible part of the surface in local coordinates.

  • dirtyRect – The dirty part of the surface in local coordinates.

  • themeContext – The theme scope for this paint pass.

inline const Rectangle &surfaceRect() const noexcept

Get the full local rectangle of the surface.

Returns:

The full local rectangle of the surface.

inline const Rectangle &visibleRect() const noexcept

Get the visible part of the surface in local coordinates.

Returns:

The visible local rectangle.

inline const Rectangle &dirtyRect() const noexcept

Get the dirty part of the surface in local coordinates.

Returns:

The dirty local rectangle.

inline const ThemeContext &themeContext() const noexcept

Get the theme context used for this paint pass.

Returns:

The theme context.

inline theme::ThemeAccessor theme() const noexcept

Access the theme for this paint pass.

Returns:

The read-only theme accessor.

class ThemeContext

The resolved theme scope for one surface operation.

Public Functions

ThemeContext() noexcept

Create a theme context using the default dark theme.

explicit ThemeContext(theme::ThemeConstPtr theme, theme::Element element = {}, theme::States state = {}, theme::Tags tags = {}) noexcept

Create a theme context.

Parameters:
  • theme – The active theme. A null pointer uses the default dark theme.

  • element – The current theme element.

  • state – The current theme state.

  • tags – The current theme tags.

theme::ThemeAccessor theme() const noexcept

Access the theme for this context.

inline theme::Element element() const noexcept

Access the current theme element.

inline theme::States state() const noexcept

Access the current theme state.

inline const theme::Tags &tags() const noexcept

Access the current theme tags.

ThemeContext withTheme(theme::ThemeConstPtr theme) const noexcept

Create a copy with a different theme.

Parameters:

theme – The active theme. A null pointer uses the default dark theme.

ThemeContext withSurface(theme::Element element, theme::States state, theme::Tags tags) const noexcept

Create a copy with a different surface scope.

Parameters:
  • element – The current theme element.

  • state – The current theme state.

  • tags – The current theme tags.

ThemeContext withState(theme::States state) const noexcept

Create a copy with additional state flags.

Parameters:

state – The state flags to add.

class LayoutContext

The theme scope for one layout pass.

Public Functions

LayoutContext() noexcept

Create a layout context using the default dark theme.

explicit LayoutContext(theme::ThemeConstPtr theme, theme::Element themeElement = {}, theme::States themeState = {}, theme::Tags themeTags = {}) noexcept

Create a layout context for a resolved theme scope.

Parameters:
  • theme – The active theme. A null pointer uses the default dark theme.

  • themeElement – The current theme element.

  • themeState – The current theme state.

  • themeTags – The current theme tags.

explicit LayoutContext(ThemeContext themeContext) noexcept

Create a layout context from a resolved theme context.

Parameters:

themeContext – The resolved theme context.

inline const ThemeContext &themeContext() const noexcept

Access the current theme context.

Returns:

The current theme context.

inline theme::ThemeAccessor theme() const noexcept

Access the theme for this layout pass.

Returns:

The read-only theme accessor.

class AbstractSurfaceContainer

Abstract interface for surface child containers.

Subclassed by erbsland::cterm::ui::SurfaceContainer

Public Functions

virtual bool empty() const noexcept = 0

Test if there are no child surfaces.

virtual std::size_t size() const noexcept = 0

Get the number of child surfaces.

virtual const SurfacePtr &operator[](std::size_t index) const noexcept = 0

Get a child surface by index without bounds checks.

virtual const SurfacePtr &at(std::size_t index) const = 0

Get a child surface by index with bounds checks.

Throws:

std::out_of_range – If the index is outside the child list.

virtual LayoutDataPtr layoutData(std::size_t index) const = 0

Get layout data for the child surface at the given index.

Throws:

std::out_of_range – If the index is outside the child list.

virtual LayoutDataPtr layoutData(const SurfacePtr &surface) const = 0

Get layout data for the given child surface.

Returns:

The layout data, or an empty pointer if the surface is not a child.

inline const_iterator begin() const noexcept

Get a const iterator to the first child surface.

inline const_iterator end() const noexcept

Get a const iterator past the last child surface.

virtual void add(SurfacePtr surface) = 0

Add a child surface at the end.

Parameters:

surface – The surface to add.

virtual void add(SurfacePtr surface, LayoutDataPtr data) = 0

Add a child surface with layout data at the end.

Parameters:
  • surface – The surface to add.

  • data – The layout data for the parent-child relation.

virtual void remove(std::size_t index) = 0

Remove the child surface at the given index.

Parameters:

index – The index to remove.

virtual void remove(const SurfacePtr &surface) = 0

Remove the given child surface.

Parameters:

surface – The child surface to remove.

virtual void removeAll() = 0

Remove all child surfaces.

virtual void insert(std::size_t index, SurfacePtr surface) = 0

Insert a child surface before the given index.

Parameters:
  • index – The insertion index.

  • surface – The surface to insert.

virtual void insert(std::size_t index, SurfacePtr surface, LayoutDataPtr data) = 0

Insert a child surface with layout data before the given index.

Parameters:
  • index – The insertion index.

  • surface – The surface to insert.

  • data – The layout data for the parent-child relation.

virtual void insertAfter(const SurfacePtr &anchor, SurfacePtr surface) = 0

Insert a child surface after the given anchor.

Parameters:
  • anchor – The existing child surface after which the new surface is inserted.

  • surface – The surface to insert.

virtual void insertBefore(const SurfacePtr &anchor, SurfacePtr surface) = 0

Insert a child surface before the given anchor.

Parameters:
  • anchor – The existing child surface before which the new surface is inserted.

  • surface – The surface to insert.

virtual void replace(const SurfacePtr &oldSurface, SurfacePtr newSurface) = 0

Replace an existing child surface.

Parameters:
  • oldSurface – The existing child surface.

  • newSurface – The replacement surface.

virtual void replace(const SurfacePtr &oldSurface, SurfacePtr newSurface, LayoutDataPtr data) = 0

Replace an existing child surface and layout data.

Parameters:
  • oldSurface – The existing child surface.

  • newSurface – The replacement surface.

  • data – The layout data for the replacement surface.

virtual void replace(std::size_t index, SurfacePtr surface) = 0

Replace the child surface at the given index.

Parameters:
  • index – The replacement index.

  • surface – The replacement surface.

virtual void replace(std::size_t index, SurfacePtr surface, LayoutDataPtr data) = 0

Replace the child surface and layout data at the given index.

Parameters:
  • index – The replacement index.

  • surface – The replacement surface.

  • data – The layout data for the replacement surface.

virtual void move(std::size_t fromIndex, std::size_t toIndex) = 0

Move a child surface to a new index.

Parameters:
  • fromIndex – The current child index.

  • toIndex – The new child index.

virtual void move(const SurfacePtr &surface, std::size_t toIndex) = 0

Move a child surface to a new index.

Parameters:
  • surface – The child surface to move.

  • toIndex – The new child index.

virtual void moveAfter(const SurfacePtr &surface, const SurfacePtr &anchor) = 0

Move a child surface after the given anchor.

Parameters:
  • surface – The child surface to move.

  • anchor – The anchor after which the surface is moved.

virtual void moveBefore(const SurfacePtr &surface, const SurfacePtr &anchor) = 0

Move a child surface before the given anchor.

Parameters:
  • surface – The child surface to move.

  • anchor – The anchor before which the surface is moved.

class const_iterator

Read-only iterator over child surfaces.

class SurfaceContainer : public erbsland::cterm::ui::AbstractSurfaceContainer

Ordered child surface collection for one surface.

Public Types

using Container = std::vector<Item>

The underlying ordered item container.

Public Functions

explicit SurfaceContainer(Surface &owner) noexcept

Create a child surface container for the given owner surface.

Parameters:

owner – The owning surface.

void setManager(SurfaceManager &manager) noexcept

Attach a manager for child-surface policy and notifications.

Parameters:

manager – The manager to attach.

void clearManager() noexcept

Clear the attached surface manager.

virtual bool empty() const noexcept override

Test if there are no child surfaces.

virtual std::size_t size() const noexcept override

Get the number of child surfaces.

virtual const SurfacePtr &operator[](std::size_t index) const noexcept override

Get a child surface by index without bounds checks.

virtual const SurfacePtr &at(std::size_t index) const override

Get a child surface by index with bounds checks.

Throws:

std::out_of_range – If the index is outside the child list.

virtual LayoutDataPtr layoutData(std::size_t index) const override

Get layout data for the child surface at the given index.

Throws:

std::out_of_range – If the index is outside the child list.

virtual LayoutDataPtr layoutData(const SurfacePtr &surface) const override

Get layout data for the given child surface.

Returns:

The layout data, or an empty pointer if the surface is not a child.

void setLayoutData(std::size_t index, LayoutDataPtr data)

Replace layout data for the child surface at the given index.

Parameters:
  • index – The child surface index.

  • data – The new layout data.

void setLayoutData(const SurfacePtr &surface, LayoutDataPtr data)

Replace layout data for the given child surface.

Parameters:
  • surface – The child surface.

  • data – The new layout data.

virtual void add(SurfacePtr surface) override

Add a child surface at the end.

Parameters:

surface – The surface to add.

Throws:

std::invalid_argument – If the surface is null, already present, or would create a cycle.

virtual void add(SurfacePtr surface, LayoutDataPtr data) override

Add a child surface with layout data at the end.

Parameters:
  • surface – The surface to add.

  • data – The layout data for the parent-child relation.

Throws:

std::invalid_argument – If the surface is null, already present, or would create a cycle.

virtual void remove(std::size_t index) override

Remove the child surface at the given index.

Parameters:

index – The index to remove.

Throws:

std::out_of_range – If the index is outside the child list.

virtual void remove(const SurfacePtr &surface) override

Remove the given child surface.

Parameters:

surface – The child surface to remove.

virtual void removeAll() override

Remove all child surfaces.

virtual void insert(std::size_t index, SurfacePtr surface) override

Insert a child surface before the given index.

Parameters:
  • index – The insertion index.

  • surface – The surface to insert.

Throws:
  • std::invalid_argument – If the surface is null, already present, or would create a cycle.

  • std::out_of_range – If the index is outside the valid insertion range.

virtual void insert(std::size_t index, SurfacePtr surface, LayoutDataPtr data) override

Insert a child surface with layout data before the given index.

Parameters:
  • index – The insertion index.

  • surface – The surface to insert.

  • data – The layout data for the parent-child relation.

Throws:
  • std::invalid_argument – If the surface is null, already present, or would create a cycle.

  • std::out_of_range – If the index is outside the valid insertion range.

virtual void insertAfter(const SurfacePtr &anchor, SurfacePtr surface) override

Insert a child surface after the given anchor.

Parameters:
  • anchor – The existing child surface after which the new surface is inserted.

  • surface – The surface to insert.

Throws:
  • std::invalid_argument – If the surface is null, already present, or would create a cycle.

  • std::out_of_range – If the anchor is not a child surface.

virtual void insertBefore(const SurfacePtr &anchor, SurfacePtr surface) override

Insert a child surface before the given anchor.

Parameters:
  • anchor – The existing child surface before which the new surface is inserted.

  • surface – The surface to insert.

Throws:
  • std::invalid_argument – If the surface is null, already present, or would create a cycle.

  • std::out_of_range – If the anchor is not a child surface.

virtual void replace(const SurfacePtr &oldSurface, SurfacePtr newSurface) override

Replace an existing child surface.

Parameters:
  • oldSurface – The existing child surface.

  • newSurface – The replacement surface.

Throws:
  • std::invalid_argument – If the replacement is null, already present, or would create a cycle.

  • std::out_of_range – If the old surface is not a child surface.

virtual void replace(const SurfacePtr &oldSurface, SurfacePtr newSurface, LayoutDataPtr data) override

Replace an existing child surface and layout data.

Parameters:
  • oldSurface – The existing child surface.

  • newSurface – The replacement surface.

  • data – The layout data for the replacement surface.

Throws:
  • std::invalid_argument – If the replacement is null, already present, or would create a cycle.

  • std::out_of_range – If the old surface is not a child surface.

virtual void replace(std::size_t index, SurfacePtr surface) override

Replace the child surface at the given index.

Parameters:
  • index – The replacement index.

  • surface – The replacement surface.

Throws:
  • std::invalid_argument – If the replacement is null, already present, or would create a cycle.

  • std::out_of_range – If the index is outside the child list.

virtual void replace(std::size_t index, SurfacePtr surface, LayoutDataPtr data) override

Replace the child surface and layout data at the given index.

Parameters:
  • index – The replacement index.

  • surface – The replacement surface.

  • data – The layout data for the replacement surface.

Throws:
  • std::invalid_argument – If the replacement is null, already present, or would create a cycle.

  • std::out_of_range – If the index is outside the child list.

virtual void move(std::size_t fromIndex, std::size_t toIndex) override

Move a child surface to a new index.

Parameters:
  • fromIndex – The current child index.

  • toIndex – The new child index.

Throws:

std::out_of_range – If either index is outside the child list.

virtual void move(const SurfacePtr &surface, std::size_t toIndex) override

Move a child surface to a new index.

Parameters:
  • surface – The child surface to move.

  • toIndex – The new child index.

Throws:

std::out_of_range – If the surface is not a child or the index is outside the child list.

virtual void moveAfter(const SurfacePtr &surface, const SurfacePtr &anchor) override

Move a child surface after the given anchor.

Parameters:
  • surface – The child surface to move.

  • anchor – The anchor after which the surface is moved.

Throws:

std::out_of_range – If either surface is not a child surface.

virtual void moveBefore(const SurfacePtr &surface, const SurfacePtr &anchor) override

Move a child surface before the given anchor.

Parameters:
  • surface – The child surface to move.

  • anchor – The anchor before which the surface is moved.

Throws:

std::out_of_range – If either surface is not a child surface.

struct Item

One child surface with metadata owned by the parent-child relation.

Public Members

SurfacePtr surface

The child surface.

LayoutDataPtr data

Optional layout data.

class LayoutData

Base class for metadata attached to one parent-child surface relation.

Subclassed by erbsland::cterm::ui::layout::SectionOptions

class SurfaceManager

Policy and notification interface for child surface changes.

Subclassed by erbsland::cterm::ui::ExclusiveSurfaceManager, erbsland::cterm::ui::Layout

Public Functions

inline virtual std::size_t maximumSurfaceCount() const noexcept

Get the maximum number of child surfaces accepted by this manager.

virtual LayoutDataPtr defaultLayoutData(const SurfacePtr &surface) const

Create default layout data for a child surface added through generic APIs.

virtual void willAdd(const SurfacePtr &surface, std::size_t index, const LayoutDataPtr &data)

Called before a child surface is added.

virtual void didAdd(const SurfacePtr &surface, std::size_t index, const LayoutDataPtr &data) noexcept

Called after a child surface was added.

virtual void willRemove(const SurfacePtr &surface, std::size_t index, const LayoutDataPtr &data)

Called before a child surface is removed.

virtual void didRemove(const SurfacePtr &surface, std::size_t index, const LayoutDataPtr &data) noexcept

Called after a child surface was removed.

virtual void willRemoveAll(std::size_t count)

Called before all child surfaces are removed.

virtual void didRemoveAll() noexcept

Called after all child surfaces were removed.

virtual void willReplace(const SurfacePtr &oldSurface, const SurfacePtr &newSurface, std::size_t index, const LayoutDataPtr &oldData, const LayoutDataPtr &newData)

Called before a child surface is replaced.

virtual void didReplace(const SurfacePtr &oldSurface, const SurfacePtr &newSurface, std::size_t index, const LayoutDataPtr &oldData, const LayoutDataPtr &newData) noexcept

Called after a child surface was replaced.

virtual void willMove(const SurfacePtr &surface, std::size_t fromIndex, std::size_t toIndex)

Called before a child surface is moved.

virtual void didMove(const SurfacePtr &surface, std::size_t fromIndex, std::size_t toIndex) noexcept

Called after a child surface was moved.

class SurfaceFlags

Framework-managed state flags for one surface.

Public Functions

explicit SurfaceFlags(Surface &owner) noexcept

Create flags for the given owner surface.

Parameters:

owner – The owning surface.

bool isVisible() const noexcept

Test if the owner surface is locally visible.

void setVisible(bool visible)

Change local visibility for the owner surface.

bool isVisibleInTree() const noexcept

Test if the owner surface and all ancestors are visible.

bool isFocusable() const noexcept

Test if the owner surface can receive direct keyboard focus.

void setFocusable(bool focusable) noexcept

Change whether the owner surface can receive direct keyboard focus.

bool isEnabled() const noexcept

Test if the owner surface is enabled.

void setEnabled(bool enabled) noexcept

Change whether the owner surface is enabled.

bool isSelected() const noexcept

Test if the owner surface is selected.

void setSelected(bool selected)

Change whether the owner surface is selected.

bool isChecked() const noexcept

Test if the owner surface is checked.

void setChecked(bool checked)

Change whether the owner surface is checked.

bool hasFocus() const noexcept

Test if the owner surface has direct keyboard focus.

bool hasFocusWithin() const noexcept

Test if the owner surface or any descendant has keyboard focus.

theme::States themeStates() const noexcept

Get the theme states represented by these flags.

bool isLayoutOutdated() const noexcept

Test if the owner surface requires a layout pass.

void setLayoutOutdated()

Mark the owner surface and its ancestors as requiring layout.

bool isPaintOutdated() const noexcept

Test if the owner surface requires repainting.

void setPaintOutdated()

Mark the whole owner surface as requiring repainting.

void setPaintOutdated(Rectangle dirtyRect)

Mark a local rectangle of the owner surface as requiring repainting.

Parameters:

dirtyRect – The dirty rectangle in the owner’s local coordinates.

void setThemeOutdated()

Mark the owner subtree as requiring layout and repainting after a theme-scope change.

const std::optional<Rectangle> &paintDirtyRect() const noexcept

Get the dirty rectangle in local coordinates, or an empty value for a full repaint.

class SurfaceThemeAttributes

Theme selector attributes configured on a surface.

Public Functions

SurfaceThemeAttributes() = default

Create default theme attributes for a generic surface.

explicit SurfaceThemeAttributes(theme::Element element) noexcept

Create theme attributes with an element.

Parameters:

element – The theme element for the surface.

inline theme::Element element() const noexcept

Access the theme element.

inline void setElement(theme::Element element) noexcept

Replace the theme element without invalidating the surface.

Parameters:

element – The new theme element.

inline const theme::Tags &tags() const noexcept

Access the theme tags.

inline void setTags(theme::Tags tags) noexcept

Replace the theme tags without invalidating the surface.

Parameters:

tags – The new theme tags.

enum class erbsland::cterm::ui::ScrollBarMode : uint8_t

Visibility mode for scroll bars in scrollable surfaces.

Values:

enumerator Hidden

The scroll bar is hidden and consumes no space.

enumerator Automatic

The scroll bar is visible only when content overflows.

enumerator Visible

The scroll bar is visible whenever the surface size permits it.

enum class erbsland::cterm::ui::FocusChange : uint8_t

Describes how a surface’s focus relation changed.

Values:

enumerator In

The surface gained direct keyboard focus.

enumerator InWithin

A descendant of the surface gained keyboard focus.

enumerator Out

The surface left the focused path.

class Surface : public std::enable_shared_from_this<Surface>

A surface is a rectangular area on a page.

The base class for all UI elements that can be displayed in the terminal.

Subclassed by erbsland::cterm::ui::Layout, erbsland::cterm::ui::Page, erbsland::cterm::ui::surface::AbstractHelpSection, erbsland::cterm::ui::surface::AbstractScrollArea, erbsland::cterm::ui::surface::AbstractScrollBar, erbsland::cterm::ui::surface::ActionHelp, erbsland::cterm::ui::surface::Button, erbsland::cterm::ui::surface::Panel, erbsland::cterm::ui::surface::ScrollCorner, erbsland::cterm::ui::surface::StaticText, erbsland::cterm::ui::surface::TextBox

Public Functions

const SurfaceWeakPtr &parent() const noexcept

Get the parent surface.

Returns:

The weak pointer to the parent surface, or an empty weak pointer for top-level pages.

virtual AbstractSurfaceContainer &surfaces() noexcept

Get mutable access to the child surface container.

Returns:

The child surface container.

virtual const AbstractSurfaceContainer &surfaces() const noexcept

Get read-only access to the child surface container.

Returns:

The child surface container.

void addSurface(SurfacePtr surface)

Add a child surface.

Parameters:

surface – The child surface to add.

Throws:

std::invalid_argument – If the child is invalid or would create a cycle in the surface tree.

PagePtr nearestPage() noexcept

Find the nearest page that contains this surface.

Returns:

The page, or null when this surface is detached.

inline Rectangle localSurfaceRect() const noexcept

Get the full local rectangle of this surface.

Returns:

The local rectangle with its top-left corner at 0,0.

Rectangle localToScreen(Rectangle localRect) const noexcept

Convert a rectangle from local surface coordinates to screen coordinates.

Parameters:

localRect – The rectangle in local surface coordinates.

Returns:

The rectangle in screen coordinates.

Rectangle screenToLocal(Rectangle screenRect) const noexcept

Convert a rectangle from screen coordinates to local surface coordinates.

Parameters:

screenRect – The rectangle in screen coordinates.

Returns:

The rectangle in local surface coordinates.

Rectangle visibleScreenRect(Rectangle screenRect) const noexcept

Get this surface’s visible rectangle in screen coordinates.

Parameters:

screenRect – The screen rectangle that limits the result.

Returns:

The part of this surface visible through all ancestors and inside screenRect.

SurfacePtr nearestOpaqueSurface() noexcept

Find the nearest opaque surface at or above this surface.

Returns:

The nearest opaque surface, or an empty pointer if this surface is not owned by a shared pointer.

bool isAncestorOrSame(const SurfacePtr &surface) const noexcept

Test if this surface is an ancestor of, or equal to, another surface.

Parameters:

surface – The surface to test.

Returns:

true if this surface is an ancestor of, or equal to, surface.

SurfaceFlags &flags() noexcept

Get mutable access to the invalidation flags.

Returns:

The surface flags.

const SurfaceFlags &flags() const noexcept

Get read-only access to the invalidation flags.

Returns:

The surface flags.

inline const Rectangle &rectangle() const noexcept

Get the assigned rectangle of this surface.

Returns:

The current surface rectangle.

void setRectangle(const Rectangle &rect) noexcept

Set the assigned rectangle of this surface.

Parameters:

rect – The new rectangle.

const LayoutMetrics &layoutMetrics() const noexcept

Get read-only access to the configured layout metrics.

Returns:

The layout metrics for this surface.

LayoutMetricsEditor editLayoutMetrics() noexcept

Create an editor for the configured layout metrics.

Returns:

The editor that invalidates layout when metrics change.

bool requestFocus() noexcept

Request direct keyboard focus for this surface from its containing page.

Returns:

true if the focus request was accepted.

Actions &actions() noexcept

Access and create actions for this surface.

A call of this method creates a new action container for this surface. Key presses are handled by the action container.

const ActionsPtr &actionsPtr() const noexcept

Access the existing action container without creating one.

Returns:

The existing actions, or a null pointer if no actions were created yet.

Scheduler &scheduler() noexcept

Access and create a scheduler for this surface.

A call of this method creates a new scheduler for this surface. Scheduled actions are handled by the scheduler and callbacks run on the application UI thread.

void layout(Size size, const LayoutContext &context) noexcept

Run a local layout pass for tests and compatibility.

This does not recursively layout child surfaces; production layout is driven by Display.

Parameters:
  • size – The assigned size inside this surface.

  • context – The resolved layout context for this surface.

SurfaceThemeAttributes &themeAttributes() noexcept

Get mutable access to theme attributes.

Returns:

The surface theme attributes.

const SurfaceThemeAttributes &themeAttributes() const noexcept

Get read-only access to theme attributes.

Returns:

The surface theme attributes.

ThemeContext themeContextFrom(const ThemeContext &parentContext) const

Create the effective theme context for this surface from a parent context.

Parameters:

parentContext – The inherited context.

Returns:

The effective context for this surface.

virtual bool isPage() const noexcept

Test if this surface is a page.

Returns:

true for Page, otherwise false.

virtual bool isOpaque() const noexcept

Test if this surface paints every cell in its rectangle.

Returns:

true if the surface is opaque.

virtual LayoutMetrics onMeasure(MeasureScope &scope, const LayoutProposal &proposal) noexcept

Measure this surface for a proposed size.

The returned layout sizes describe the margin-free content rectangle. The optional margins in the returned metrics are recommendations for the parent layout and are not included in these sizes.

Parameters:
  • scope – Measurement access for child surfaces.

  • proposal – The proposed size.

Returns:

The measured layout metrics.

virtual void onLayout(LayoutScope &scope) noexcept

Layout direct children within this surface.

Parameters:

scopeLayout access for measuring and placing child surfaces.

virtual void onPaint(WritableBuffer &buffer, const PaintContext &context) noexcept

Paint this surface into the target buffer.

Parameters:
  • buffer – The target buffer.

  • context – The paint context for the current paint pass.

virtual void onKeyPress(KeyPressEvent &keyPressEvent) noexcept

Handle a key press event.

This is the low-level event handler for key press events. If a surface handles a key press event, it should mark it as handled.

Parameters:

keyPressEvent – The key press event to handle.

virtual void onFocus(FocusChange focusChange) noexcept

React to a focus relation change.

Parameters:

focusChange – The focus transition for this surface.

class Layout : public erbsland::cterm::ui::Surface, protected erbsland::cterm::ui::SurfaceManager

A layout is a surface that arranges other surfaces in a specific way.

Layout measurement follows the same rule as every surface: returned sizes describe the layout’s margin-free content rectangle. Pure layouts may collapse child margins and report the unresolved outer margins in their own metrics.

Subclassed by erbsland::cterm::ui::layout::Buttons, erbsland::cterm::ui::layout::Pages, erbsland::cterm::ui::layout::Sections, erbsland::cterm::ui::layout::SingleContentLayout, erbsland::cterm::ui::layout::Stack

Public Functions

virtual bool isOpaque() const noexcept override

Test if this surface paints every cell in its rectangle.

Returns:

true if the surface is opaque.

virtual void onPaint(WritableBuffer &buffer, const PaintContext &context) noexcept override

Paint this surface into the target buffer.

Parameters:
  • buffer – The target buffer.

  • context – The paint context for the current paint pass.

class Page : public erbsland::cterm::ui::Surface

A single page on the screen.

Subclassed by erbsland::cterm::ui::page::Choice, erbsland::cterm::ui::page::HelpViewer

Public Functions

inline explicit Page(ProtectedTag)

Create a page instance through the protected construction path.

void setTheme(theme::ThemeConstPtr theme) noexcept

Replace the theme for this page and its descendants.

Parameters:

theme – The page theme. A null pointer clears the override.

void clearTheme() noexcept

Clear the page theme override.

const theme::ThemeConstPtr &themeOverride() const noexcept

Access the page theme override.

Returns:

The page theme override, or null if the application theme is used.

bool hasFocusSurface() const noexcept

Test if the page has a focus surface.

const SurfaceWeakPtr &focusSurface() const noexcept

Get the current focus surface.

bool focusTo(const SurfaceWeakPtr &surface) noexcept

Move the focus to another surface.

Passing an expired, foreign, hidden, or non-focusable surface clears the current focus.

Parameters:

surface – The new focus surface.

Returns:

true if the surface received focus.

void clearFocus() noexcept

Clear keyboard focus from this page.

virtual void onLayout(LayoutScope &scope) noexcept override

Layout top-level page children inside the page.

Parameters:

scope – The layout scope for this page.

virtual void onPaint(WritableBuffer &buffer, const PaintContext &context) noexcept override

Paint this surface into the target buffer.

Parameters:
  • buffer – The target buffer.

  • context – The paint context for the current paint pass.

virtual void onKeyPress(KeyPressEvent &keyPressEvent) noexcept override

Route the key press to the focused surface chain and finally to the page itself.

Parameters:

keyPressEvent – The key press event.

virtual bool isOpaque() const noexcept override

Test if this surface paints every cell in its rectangle.

Returns:

true if the surface is opaque.

virtual bool isPage() const noexcept override

Test if this surface is a page.

Returns:

true for Page, otherwise false.

Public Static Functions

static PagePtr create()

Create a new page.

class Choice : public erbsland::cterm::ui::Page

A non-opaque modal page that asks the user to choose one action.

Public Types

using Callback = std::function<void(const Selection&)>

Callback executed after the page has been popped.

Public Functions

Choice(String title, String description, ProtectedTag)

Create a choice page.

const String &title() const noexcept

Access the title.

void setTitle(String title)

Replace the title.

const String &description() const noexcept

Access the description.

void setDescription(String description)

Replace the description.

void setCallback(Callback callback)

Set the selection callback.

Margins margins() const noexcept

Access the outer margins that keep the lower page visible.

void setMargins(Margins margins) noexcept

Replace the outer margins.

Margins padding() const noexcept

Access the prompt content padding.

void setPadding(Margins padding) noexcept

Replace the prompt content padding.

std::optional<Coordinate> preferredLineWidth() const noexcept

Access the preferred line width for the description text.

void setPreferredLineWidth(std::optional<Coordinate> width)

Replace the preferred line width for the description text.

ActionPtr addChoice(std::string id, std::string title, Keys keys = {}, int priority = 0)

Add one choice.

Parameters:
  • id – Stable application identifier.

  • titleDisplay title.

  • keys – Keyboard shortcuts for the choice.

  • priorityDisplay priority; larger values are shown first.

Returns:

The action backing the choice button.

ActionPtr addChoice(std::string title, Keys keys = {}, int priority = 0)

Add one choice using the title as stable identifier.

Parameters:
  • titleDisplay title and identifier.

  • keys – Keyboard shortcuts for the choice.

  • priorityDisplay priority; larger values are shown first.

Returns:

The action backing the choice button.

void show()

Show this page on the application display and focus the first enabled choice.

void dismiss()

Pop this page from the application display.

virtual bool isOpaque() const noexcept override

Test if this surface paints every cell in its rectangle.

Returns:

true if the surface is opaque.

virtual void onLayout(LayoutScope &scope) noexcept override

Layout direct children within this surface.

Parameters:

scopeLayout access for measuring and placing child surfaces.

virtual void onPaint(WritableBuffer &buffer, const PaintContext &context) noexcept override

Paint this surface into the target buffer.

Parameters:
  • buffer – The target buffer.

  • context – The paint context for the current paint pass.

Public Static Functions

static ChoicePtr create(String title, String description = {})

Create a choice page.

Parameters:
  • title – The prompt title.

  • description – The prompt description.

Returns:

The new choice page.

static ChoicePtr create(std::string_view title, std::string_view description = {})

Create a choice page from UTF-8 text.

Parameters:
  • title – The prompt title.

  • description – The prompt description.

Returns:

The new choice page.

struct Selection

The selected choice passed to the callback.

Public Members

std::string id

Stable application identifier for the choice.

String title

Display title of the choice.

std::size_t index = {0}

Insertion index of the choice.