Skip to content

Border

Header: winui/ui/containers/Border.hpp. Spec: winui/ui/containers/Border.hpp.

One child inside a background, a border and padding.

Measures to the child's size plus border thickness and padding on each side, and arranges the child inside both. The background fills the rect inside the border, and the border is drawn inside the element's own bounds, both with corner_radius(). Input, focus, ticks and popups pass through to the child, so wrapping a subtree in a Border changes only its look and its size. Set the child with ContentHost::set_child().

Example:

auto border = std::make_unique<ui::BorderControl>();
border->set_background(ui::colors::White);
border->set_border_brush(ui::Color::from_rgba(255, 215, 0));
border->set_border_thickness(ui::Thickness{2.0f});
border->set_corner_radius(4.0f);
border->set_padding(ui::Thickness{12.0f});
ui::TextControl* label = border->set_child(std::make_unique<ui::TextControl>("Inside a border"));
window.set_content(std::move(border));

// Declaratively:
window.set_content(ui::Border{
    .background       = ui::colors::White,
    .border_brush     = ui::Color::from_rgba(255, 215, 0),
    .border_thickness = ui::Thickness{2.0f},
    .corner_radius    = 4.0f,
    .padding          = ui::Thickness{12.0f},
    .content          = ui::Text{.text = "Inside a border"},
});

ui::Border

A background, a border and padding around one child. Builds a ui::BorderControl.

Example:

const ui::Color gold = ui::Color::from_rgba(255, 215, 0);

window.set_content(ui::Border{
    .background           = ui::colors::White,
    .border_brush         = gold,
    .border_thickness     = ui::Thickness{2.0f},
    .corner_radius        = 4.0f,
    .padding              = ui::Thickness{12.0f},
    .horizontal_alignment = ui::Alignment::Leading,
    .content              = ui::Text{.text = "Text inside a border"},
});

Every field, in the order a designated initializer names them:

ui::Border{
    .background, .border_brush, .border_thickness, .corner_radius, .padding, .shadow,
    .elevation, .clip_content, .style, .margin, .width, .height, .min_width, .min_height,
    .max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip,
    .accessibility, .on_pointer_entered, .on_pointer_exited, .on_got_focus, .on_lost_focus,
    .on_key_down, .on_wheel, .control, .content
}

Fields, in declaration order (designators must follow it):

Field Type Default
background ui::Binding<ui::Paint> The background inside the border: a Color, or a ThemeColor read from the theme. Empty, the default, draws none.
border_brush ui::Binding<ui::Paint> The border color, a Color or a ThemeColor. Empty, the default, draws no border.
border_thickness ui::Binding<ui::Thickness> {ui::Thickness{}} The border width per edge, DIPs.
corner_radius ui::Binding<float> {0.0f} The corner radius in DIPs, for the background and border alike.
padding ui::Binding<ui::Thickness> {ui::Thickness{}} The padding between the border and the child, DIPs.
shadow ui::Binding<bool> {false} Whether the border casts a drop shadow sized by elevation.
elevation ui::Binding<float> {0.0f} The elevation in DIPs that sizes the shadow.
clip_content ui::Binding<bool> {false} Whether the child is clipped to the inside of the border, rounded corners included, so a picture follows the corners. Off by default, which lets a child draw past the edge.
on_pointer_entered ui::Action The pointer moved onto the control.
on_pointer_exited ui::Action The pointer left the control.
on_got_focus ui::Action Keyboard focus arrived on the control, or on anything inside it, from outside it. A control with nothing focusable in it never gets focus, and never raises this.
on_lost_focus ui::Action Keyboard focus left the control and everything inside it.
on_key_down ui::Callback<ui::Handling(const ui::KeyEvent&)> A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()).
on_wheel ui::Callback<ui::Handling(const ui::PointerEvent&)> A wheel turn over the control, before the control scrolls; ui::Handled stops it there (Element::on_wheel()).
control ui::ControlOut<ui::Border> Out: the handle that receives the built control.
content ui::Spec The framed child.

Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, accessibility every spec carries (conventions).

build

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::BorderControl; the caller owns it.

ui::BorderControl

Derives from ui::ContentHost.

One child inside a background, a border and padding.

Measures to the child's size plus border thickness and padding on each side, and arranges the child inside both. The background fills the rect inside the border, and the border is drawn inside the element's own bounds, both with corner_radius(). Input, focus, ticks and popups pass through to the child, so wrapping a subtree in a Border changes only its look and its size. Set the child with ContentHost::set_child().

Example:

auto border = std::make_unique<ui::BorderControl>();
border->set_background(ui::colors::White);
border->set_border_brush(ui::Color::from_rgba(255, 215, 0));
border->set_border_thickness(ui::Thickness{2.0f});
border->set_corner_radius(4.0f);
border->set_padding(ui::Thickness{12.0f});
ui::TextControl* label = border->set_child(std::make_unique<ui::TextControl>("Inside a border"));
window.set_content(std::move(border));

// Declaratively:
window.set_content(ui::Border{
    .background       = ui::colors::White,
    .border_brush     = ui::Color::from_rgba(255, 215, 0),
    .border_thickness = ui::Thickness{2.0f},
    .corner_radius    = 4.0f,
    .padding          = ui::Thickness{12.0f},
    .content          = ui::Text{.text = "Inside a border"},
});

hit_test_transparent

bool hit_test_transparent() const override

Returns false, so the border is hit anywhere in its bounds, even where it draws nothing.

BorderControl

BorderControl() = default

An empty border: no child, no background, no border, no padding.

background

const std::optional<Color>& background() const

The fixed background color. nullopt, the default, draws nothing. It also reads nullopt while a theme resource is set (see background_resource()). A ThemeColor is read again whenever the border is drawn, so it follows theme switches.

background_resource

ThemeColor background_resource() const

The theme resource set as the background, or nullptr when a fixed color or none is set.

set_background

void set_background(std::optional<Color> color)

Sets a fixed background color, or none with nullopt, and clears any theme resource. Redraws.

set_background

void set_background(ThemeColor resource)

Sets a theme resource as the background, for example [](const Theme& t) { return t.colors().background; }. Redraws.

background_transition

const std::optional<BrushTransition>& background_transition() const

How the background changes color. With a BrushTransition set, a later change of what the background draws, such as a new color or a resource under a new theme, blends from the color on screen. nullopt, the default, changes it at once.

set_background_transition

void set_background_transition(std::optional<BrushTransition> transition)

Sets the background transition. Applies to the next change, and a blend already running keeps going.

border_brush

const std::optional<Color>& border_brush() const

The fixed border color. nullopt, the default, draws no border, though border_thickness() still takes up room.

border_brush_resource

ThemeColor border_brush_resource() const

The theme resource set as the border brush, or nullptr.

set_border_brush

void set_border_brush(std::optional<Color> color)

Sets a fixed border color and clears any theme resource set with the other overload. Redraws.

set_border_brush

void set_border_brush(ThemeColor resource)

Sets a theme resource as the border brush, read again under every theme. It takes precedence over a fixed border_brush(). Redraws.

border_thickness

const Thickness& border_thickness() const

The border width per side in DIPs, zero by default. It takes up room whether or not a border brush is set.

set_border_thickness

void set_border_thickness(const Thickness& thickness)

Sets the border width. Updates layout and redraws.

corner_radius

float corner_radius() const

The corner radius in DIPs, one value for all four corners. 0, the default, gives square corners. Applies to the background and the border alike.

set_corner_radius

void set_corner_radius(float radius)

Sets the corner radius. Redraws only, since layout doesn't depend on the radius.

padding

const Thickness& padding() const

The padding in DIPs between the inside of the border and the child, zero by default.

set_padding

void set_padding(const Thickness& padding)

Sets the padding. Updates layout.

shadow

bool shadow() const

Whether the border casts a drop shadow sized by elevation(). It draws two black shadows, ambient and directional, whose blur, offset and opacity grow with the depth and differ per theme. Off by default.

set_shadow

void set_shadow(bool on)

Turns the shadow on or off. Redraws only, since the shadow takes no layout room.

elevation

float elevation() const

The elevation the shadow is sized by, in DIPs. 0 by default, and below 4 casts no shadow. It moves nothing on screen. It is the same value as Element::translation().z, so a translation animation or transition deepens the shadow as it runs.

set_elevation

void set_elevation(float z)

Sets only the z of Element::translation(), keeping x and y.

clip_content

bool clip_content() const

Whether the child is clipped to the inside of the border, rounded corners included. Off by default. When on, a picture in a rounded Border follows the corners, and a child drawn past the edge, through a negative margin or a transform, is cut off there.

set_clip_content

void set_clip_content(bool clip)

Turns clipping on or off. Redraws.

parallel_measure_safe

bool parallel_measure_safe() const override

Returns true, since measuring touches only the child.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

The child's desired size plus border thickness and padding on each side.

arrange_override

void arrange_override(const Rect& final_rect, const ArrangeContext& context) override

Gives the child the rect inside the border and the padding.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

Draws the shadow if it is on, the background and the border, then the child. The child is clipped to the inside of the border while clip_content() is on.

tick_override

void tick_override(Duration delta) override

Advances the background transition, then forwards to the child.

Tests

  • tests/test_layout_panels.cpp