Skip to content

DensityScope

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

A wrapper that measures and draws its one child at compact or standard control density, which applies the compact sizing to one subtree.

The child sees a copy of the theme whose sizing is Theme::ControlSizing::compact(). TextBox, the controls built on it and ComboBox shrink, and everything else keeps its size. Density::Standard passes the theme through unchanged. Popups opened from inside the scope are drawn in the window's own theme, at standard density. Input, focus and ticks pass through to the child.

Example:

// Declarative: a compact form, switchable at run time through a Property.
ui::Property<ui::Density> density{ui::Density::Compact};
window.set_content(ui::DensityScope{
    .density = density,
    .content = ui::VerticalStack{
        .spacing  = 8,
        .content  = {
            ui::TextBox{.header = "Name"},
            ui::ComboBox{.items = {"Red", "Green", "Blue"}},
        },
    },
});

// Imperative: the scope owns its child through ContentHost::set_child().
auto scope = std::make_unique<ui::DensityScopeControl>(ui::Density::Compact);
ui::TextBoxControl* box = scope->set_child(std::make_unique<ui::TextBoxControl>());
const ui::Theme& inside = scope->scoped(ui::Theme::default_light());
// inside.sizing.text_control_min_height == 24, down from 32

ui::DensityScope

Shows its child at compact or standard control density, which applies the compact control sizes to a whole subtree. Builds a ui::DensityScopeControl.

Example:

ui::Property<bool> compact{true};

window.set_content(ui::DensityScope{
    .density = ui::bind(compact, [](bool c) { return c ? ui::Density::Compact : ui::Density::Standard; }),
    .content = ui::VerticalStack{.spacing = 8, .content = {
        ui::TextBox{.placeholder_text = "Name"},
        ui::ComboBox{.items = {"One", "Two"}},
        ui::Button{.text = "Submit"},
    }},
});

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

ui::DensityScope{
    .density, .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
density ui::Binding<ui::Density> {ui::Density::Compact} Compact, the default, shrinks control heights and paddings. Standard changes nothing.
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::DensityScope> Out: the handle that receives the built control.
content ui::Spec The subtree the density applies to.

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::DensityScopeControl; the caller owns it.

ui::DensityScopeControl

Derives from ui::ContentHost.

A wrapper that measures and draws its one child at compact or standard control density, which applies the compact sizing to one subtree.

The child sees a copy of the theme whose sizing is Theme::ControlSizing::compact(). TextBox, the controls built on it and ComboBox shrink, and everything else keeps its size. Density::Standard passes the theme through unchanged. Popups opened from inside the scope are drawn in the window's own theme, at standard density. Input, focus and ticks pass through to the child.

Example:

// Declarative: a compact form, switchable at run time through a Property.
ui::Property<ui::Density> density{ui::Density::Compact};
window.set_content(ui::DensityScope{
    .density = density,
    .content = ui::VerticalStack{
        .spacing  = 8,
        .content  = {
            ui::TextBox{.header = "Name"},
            ui::ComboBox{.items = {"Red", "Green", "Blue"}},
        },
    },
});

// Imperative: the scope owns its child through ContentHost::set_child().
auto scope = std::make_unique<ui::DensityScopeControl>(ui::Density::Compact);
ui::TextBoxControl* box = scope->set_child(std::make_unique<ui::TextBoxControl>());
const ui::Theme& inside = scope->scoped(ui::Theme::default_light());
// inside.sizing.text_control_min_height == 24, down from 32

DensityScopeControl

DensityScopeControl() = default

A compact scope with no child yet.

DensityScopeControl

DensityScopeControl(Density density)

A scope at density, with no child yet.

density

Density density() const

The density applied to the child. Density::Compact by default.

set_density

void set_density(Density density)

Changes the density. Updates layout and redraws, since every control underneath measures again against the new sizing.

scoped

const Theme& scoped(const Theme& base) const

The theme the subtree sees. At Density::Standard that is base itself, otherwise a copy of it at compact density, kept in the scope and valid until the next call.

scoped

const Theme& scoped(const Theme&& base) const = delete

Deleted, since at Density::Standard the result is base itself, which a temporary would leave dangling.

measure_override

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

Measures the child against scoped(theme).

render_override

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

Draws the child against scoped(theme).

Enumerations

Density

enum class Density

The density a DensityScope applies.

Value
Standard The theme's own control sizing. The scope changes nothing.
Compact Theme::ControlSizing::compact(), with smaller minimum heights and paddings.

Tests

  • tests/test_styles.cpp