Skip to content

Shapes

Header: winui/ui/media/Shape.hpp. Spec: winui/ui/media/Shape.hpp.

The base of the shapes. A shape is one geometry, filled with fill() and outlined with stroke(), drawn with one Renderer::draw_geometry() call.

It can't be constructed on its own. Use Rectangle, Ellipse, Line, Polyline, Polygon or Path, or their ui:: specs. Everything here is shared by all six. Shapes take no input and no focus.

Example:

auto shape = std::make_unique<ui::EllipseControl>();
shape->set_fill(ui::colors::White);
shape->set_stroke(ui::colors::Black);
shape->set_stroke_thickness(2.0f);
shape->set_stretch(ui::Stretch::Uniform); // a circle, whatever the slot's aspect
shape->set_width(100.0f);
shape->set_height(60.0f);
window.set_content(std::move(shape)); // drawn as one geometry: fill and stroke together

ui::Rectangle

A rectangle, optionally with rounded corners. Builds a ui::RectangleControl.

It has no natural size. Give it a .width and .height, or let the parent stretch it.

Example:

ui::Property<ui::Color> swatch{ui::Color::from_argb(0xFF0078D4)};

window.set_content(ui::HorizontalStack{
    .spacing  = 12,
    .content  = {
        ui::Rectangle{ .fill = ui::colors::Black, .width = 100, .height = 60 },
        ui::Rectangle{ .fill             = swatch, // follows the property
                       .stroke           = ui::colors::Black,
                       .stroke_thickness = 2.0f,
                       .radius_x         = 8.0f,
                       .radius_y         = 8.0f,
                       .width            = 100,
                       .height           = 60 },
    },
});

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

ui::Rectangle{
    .fill, .stroke, .stroke_thickness, .stroke_style, .stretch, .radius_x, .radius_y, .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
}

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

Field Type Default
fill ui::Binding<ui::Paint> The interior paint: a Color, gradient, acrylic or ThemeColor. Empty paints none.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::Fill} How the shape fills its layout rect. Fill by default.
radius_x ui::Binding<float> {0.0f} Horizontal corner radius in DIPs, clamped to half the width. 0 gives square corners.
radius_y ui::Binding<float> {0.0f} Vertical corner radius in DIPs, clamped to half the height. 0 gives square corners.
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::Rectangle> Out: the handle that receives the built control.

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

ui::Ellipse

The ellipse inscribed in the element's rect. Builds a ui::EllipseControl.

Example:

window.set_content(ui::Ellipse{
    .fill                 = ui::Color::from_argb(0xFFFF00FF),
    .stroke               = ui::colors::Black,
    .stroke_thickness     = 2.0f,
    .width                = 152,
    .height               = 152,
    .horizontal_alignment = ui::Alignment::Center,
    .vertical_alignment   = ui::Alignment::Center,
});

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

ui::Ellipse{
    .fill, .stroke, .stroke_thickness, .stroke_style, .stretch, .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
}

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

Field Type Default
fill ui::Binding<ui::Paint> The interior paint: a Color, gradient, acrylic or ThemeColor. Empty paints none.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::Fill} How the shape fills its layout rect. Fill by default.
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::Ellipse> Out: the handle that receives the built control.

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

ui::Line

A straight line from (x1, y1) to (x2, y2). Builds a ui::LineControl.

A line has no interior, so there is no .fill. Without a .stroke it draws nothing.

Example:

ui::Property<float> end_x{200.0f};

window.set_content(ui::Line{
    .x1               = 0.0f,
    .y1               = 50.0f,
    .x2               = end_x,
    .y2               = 50.0f,
    .stroke           = ui::Color::from_argb(0xFF4682B4),
    .stroke_thickness = 4.0f,
});
end_x = 300.0f; // the line follows

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

ui::Line{
    .x1, .y1, .x2, .y2, .stroke, .stroke_thickness, .stroke_style, .stretch, .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
}

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

Field Type Default
x1 ui::Binding<float> {0.0f} Start point x, in local DIPs.
y1 ui::Binding<float> {0.0f} Start point y, in local DIPs.
x2 ui::Binding<float> {0.0f} End point x, in local DIPs.
y2 ui::Binding<float> {0.0f} End point y, in local DIPs.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::None} How the geometry scales into the layout rect. None, the default, draws it where it is.
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::Line> Out: the handle that receives the built control.

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

ui::Polyline

Connected straight lines through points, left open. Builds a ui::PolylineControl.

Example:

window.set_content(ui::Polyline{
    .points           = std::vector<ui::Point>{{10.0f, 100.0f}, {60.0f, 40.0f}, {200.0f, 40.0f}, {250.0f, 100.0f}},
    .stroke           = ui::colors::Black,
    .stroke_thickness = 4.0f,
});

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

ui::Polyline{
    .points, .fill_rule, .fill, .stroke, .stroke_thickness, .stroke_style, .stretch, .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
}

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

Field Type Default
points ui::Binding<std::vector<ui::Point>> The vertices, in local DIPs.
fill_rule ui::Binding<ui::FillRule> {ui::FillRule::EvenOdd} Which enclosed regions .fill paints where the outline crosses itself.
fill ui::Binding<ui::Paint> The interior paint: a Color, gradient, acrylic or ThemeColor. Empty paints none.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::None} How the geometry scales into the layout rect. None, the default, draws it where it is.
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::Polyline> Out: the handle that receives the built control.

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

ui::Polygon

Connected straight lines through points, closed back to the first point. Builds a ui::PolygonControl.

Example:

window.set_content(ui::Polygon{
    .points           = std::vector<ui::Point>{{10.0f, 100.0f}, {60.0f, 40.0f}, {200.0f, 40.0f}, {250.0f, 100.0f}},
    .fill             = ui::Color::from_argb(0xFF4682B4),
    .stroke           = ui::colors::Black,
    .stroke_thickness = 2.0f,
});

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

ui::Polygon{
    .points, .fill_rule, .fill, .stroke, .stroke_thickness, .stroke_style, .stretch, .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
}

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

Field Type Default
points ui::Binding<std::vector<ui::Point>> The vertices, in local DIPs.
fill_rule ui::Binding<ui::FillRule> {ui::FillRule::EvenOdd} Which enclosed regions .fill paints where the outline crosses itself.
fill ui::Binding<ui::Paint> The interior paint: a Color, gradient, acrylic or ThemeColor. Empty paints none.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::None} How the geometry scales into the layout rect. None, the default, draws it where it is.
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::Polygon> Out: the handle that receives the built control.

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

ui::Path

Any geometry, with data from PathGeometry::parse() or the PathGeometry builders. Builds a ui::PathControl.

PathGeometry::parse() returns nullopt for markup that doesn't parse. A literal known to be valid is usually dereferenced directly.

Example:

window.set_content(ui::Path{
    .data             = *ui::PathGeometry::parse("M 10,100 C 100,25 300,250 400,75 H 200"),
    .stroke           = ui::Color::from_argb(0xFFB8860B),
    .stroke_thickness = 3.0f,
});

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

ui::Path{
    .data, .fill, .stroke, .stroke_thickness, .stroke_style, .stretch, .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
}

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

Field Type Default
data ui::Binding<ui::PathGeometry> The figures to draw, in local DIPs: *PathGeometry::parse("M 0,0 L 10,10") or a PathGeometry builder.
fill ui::Binding<ui::Paint> The interior paint: a Color, gradient, acrylic or ThemeColor. Empty paints none.
stroke ui::Binding<ui::Paint> The outline paint. Empty draws no outline and reserves no room for one.
stroke_thickness ui::Binding<float> {1.0f} The outline width, in DIPs.
stroke_style ui::Binding<ui::StrokeStyle> Caps, join, miter limit and dashes. Its thickness is ignored for .stroke_thickness.
stretch ui::Binding<ui::Stretch> {ui::Stretch::None} How the geometry scales into the layout rect. None, the default, draws it where it is.
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::Path> Out: the handle that receives the built control.

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

ui::Shape

Derives from ui::Element.

The base of the shapes. A shape is one geometry, filled with fill() and outlined with stroke(), drawn with one Renderer::draw_geometry() call.

It can't be constructed on its own. Use Rectangle, Ellipse, Line, Polyline, Polygon or Path, or their ui:: specs. Everything here is shared by all six. Shapes take no input and no focus.

Example:

auto shape = std::make_unique<ui::EllipseControl>();
shape->set_fill(ui::colors::White);
shape->set_stroke(ui::colors::Black);
shape->set_stroke_thickness(2.0f);
shape->set_stretch(ui::Stretch::Uniform); // a circle, whatever the slot's aspect
shape->set_width(100.0f);
shape->set_height(60.0f);
window.set_content(std::move(shape)); // drawn as one geometry: fill and stroke together

fill

const Paint& fill() const

The interior paint. Empty, the default, paints no interior.

set_fill

void set_fill(Paint paint)

Sets the interior paint: a Color, a gradient, an AcrylicBrush or a ThemeColor. Redraws.

stroke

const Paint& stroke() const

The outline paint. Empty, the default, draws no outline and makes stroke_thickness() count as zero for layout.

set_stroke

void set_stroke(Paint paint)

Sets the outline paint. Updates layout and redraws, since whether there is a stroke changes how much room the shape takes.

stroke_thickness

float stroke_thickness() const

The outline width, 1 by default. This is the thickness of stroke_style(). The other stroke settings, such as caps, join, miter limit and dashes, are in that StrokeStyle.

set_stroke_thickness

void set_stroke_thickness(float thickness)

Sets the outline width in DIPs. Updates layout and redraws, since the room the stroke takes changes with it.

stroke_style

const StrokeStyle& stroke_style() const

The whole pen, stroke_thickness() included.

set_stroke_style

void set_stroke_style(const StrokeStyle& style)

Sets everything but the thickness, which set_stroke_thickness() sets. Redraws.

stretch

Stretch stretch() const

How the geometry fills the layout rect. Fill by default for Rectangle and Ellipse, None for the rest. For Rectangle and Ellipse, Uniform and UniformToFill make the outline square and None collapses it. For the other shapes it scales the geometry's bounds into the rect, less the stroke.

set_stretch

void set_stretch(Stretch stretch)

Sets the stretch. Updates layout and redraws.

rendered_geometry

PathGeometry rendered_geometry() const

The geometry as drawn, in window coordinates, as render() passes it to the renderer. Valid after arrange().

Shape

Shape(Stretch stretch)

For the concrete shapes. stretch is their default Stretch.

effective_stroke_thickness

float effective_stroke_thickness() const

The thickness layout reserves: the absolute stroke thickness with a stroke, 0 without.

natural_geometry

virtual PathGeometry natural_geometry() const

For Line, Polyline, Polygon and Path: the geometry in local coordinates, before any stretch. Rectangle and Ellipse override outline_geometry() instead and never call this.

stretches_geometry

virtual bool stretches_geometry() const

Whether stretch() scales the geometry. False for Rectangle and Ellipse, which build their geometry at the layout size themselves.

outline_geometry

virtual PathGeometry outline_geometry(Size) const

For Rectangle and Ellipse: the geometry, in local coordinates, for an element laid out at size.

outline_rect

Rect outline_rect(Size size, bool check_degenerate) const

The layout rect inset by half the stroke, then made square or collapsed as the stretch says. With check_degenerate, which Rectangle sets, the full rect is kept when the stroke is as thick as a side.

measure_override

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

The natural geometry's size under stretch(). With Stretch::None that is its bottom-right corner plus half the stroke, otherwise its bounds scaled into available. Rectangle and Ellipse override this.

render_override

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

Draws the geometry once with fill(), stroke() and stroke_style(). Draws nothing when both paints are unset or the shape was laid out with no area.

class RectangleControl

Derives from ui::Shape.

A rectangle, optionally with elliptically rounded corners. Stretch defaults to Fill.

Its geometry is built from its layout rect, inset by half the stroke, so without a width and height it fills the slot its parent gives it. The declarative form is ui::Rectangle.

Example:

auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* card = panel->add(std::make_unique<ui::RectangleControl>());
card->set_fill(ui::Color::from_rgba(70, 130, 180));
card->set_stroke(ui::colors::Black);
card->set_stroke_thickness(2.0f);
card->set_radius_x(8.0f);
card->set_radius_y(8.0f);
card->set_width(120.0f);
card->set_height(80.0f);
window.set_content(std::move(panel));

RectangleControl

RectangleControl()

A rectangle with Stretch::Fill and no fill or stroke. Set a fill() or stroke() to see it.

radius_x

float radius_x() const

The corners' horizontal radius in DIPs. 0, the default, gives square corners.

set_radius_x

void set_radius_x(float radius)

Sets the horizontal corner radius. Redraws.

radius_y

float radius_y() const

The corners' vertical radius in DIPs. 0, the default, gives square corners.

set_radius_y

void set_radius_y(float radius)

Sets the vertical corner radius. Redraws.

stretches_geometry

bool stretches_geometry() const override

Whether stretch() scales the geometry. False for Rectangle and Ellipse, which build their geometry at the layout size themselves.

outline_geometry

PathGeometry outline_geometry(Size size) const override

For Rectangle and Ellipse: the geometry, in local coordinates, for an element laid out at size.

measure_override

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

No size of its own, so an explicit width and height apply. Under UniformToFill it asks for a square covering available.

class EllipseControl

Derives from ui::Shape.

The ellipse inscribed in the outline rect. Stretch defaults to Fill.

Like Rectangle, it takes its size from layout. Stretch::Uniform makes it a circle, placed at the rect's top-left. The declarative form is ui::Ellipse.

Example:

auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Horizontal);
auto* dot  = panel->add(std::make_unique<ui::EllipseControl>());
dot->set_fill(ui::colors::White);
dot->set_stroke(ui::colors::Black);
dot->set_stroke_thickness(2.0f);
dot->set_width(48.0f);
dot->set_height(48.0f);
window.set_content(std::move(panel));

EllipseControl

EllipseControl()

An ellipse with Stretch::Fill and no fill or stroke.

stretches_geometry

bool stretches_geometry() const override

Whether stretch() scales the geometry. False for Rectangle and Ellipse, which build their geometry at the layout size themselves.

outline_geometry

PathGeometry outline_geometry(Size size) const override

For Rectangle and Ellipse: the geometry, in local coordinates, for an element laid out at size.

measure_override

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

Like Rectangle's: no size of its own, except a covering square under UniformToFill.

class LineControl

Derives from ui::Shape.

A line from (x1, y1) to (x2, y2) in local coordinates.

A line has no interior, so only stroke() draws. With the default Stretch::None it asks for room up to its farther end plus half the stroke. The declarative form is ui::Line.

Example:

auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* rule = panel->add(std::make_unique<ui::LineControl>(ui::Point{0.0f, 0.0f},
                                                      ui::Point{200.0f, 0.0f}));
rule->set_stroke(ui::colors::Black);
rule->set_stroke_thickness(2.0f);
rule->set_x2(300.0f); // stretch it later
window.set_content(std::move(panel));

LineControl

LineControl()

A line from (0, 0) to (0, 0). Invisible until its ends and a stroke are set.

LineControl

LineControl(Point from, Point to)

A line from from to to, in DIPs of local coordinates.

from

Point from() const

The start point, (x1, y1).

to

Point to() const

The end point, (x2, y2).

set_x1

void set_x1(float v)

Sets the start point's x. Each of the four setters updates layout and redraws.

set_y1

void set_y1(float v)

Sets the start point's y.

set_x2

void set_x2(float v)

Sets the end point's x.

set_y2

void set_y2(float v)

Sets the end point's y.

natural_geometry

PathGeometry natural_geometry() const override

For Line, Polyline, Polygon and Path: the geometry in local coordinates, before any stretch. Rectangle and Ellipse override outline_geometry() instead and never call this.

class PolylineControl

Derives from ui::Shape.

Straight segments through a list of points. The fill rule, EvenOdd by default, decides what counts as inside.

A Polyline is open: its stroke stops at the last point. Polygon, which derives from it, closes the last point back to the first. The declarative form is ui::Polyline.

Example:

auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* zigzag = panel->add(std::make_unique<ui::PolylineControl>(std::vector<ui::Point>{
    {10.0f, 200.0f}, {60.0f, 140.0f}, {130.0f, 140.0f}, {180.0f, 200.0f}}));
zigzag->set_stroke(ui::colors::Black);
zigzag->set_stroke_thickness(4.0f);
window.set_content(std::move(panel));

PolylineControl

PolylineControl()

An empty polyline: draws nothing until it has points.

PolylineControl

PolylineControl(std::vector<Point> points)

A polyline through points, in local DIPs.

points

const std::vector<Point>& points() const

The points, in local coordinates.

set_points

void set_points(std::vector<Point> points)

Replaces every point. Updates layout and redraws.

fill_rule

FillRule fill_rule() const

Which enclosed areas the fill paints where segments cross.

set_fill_rule

void set_fill_rule(FillRule rule)

Sets the fill rule. Redraws.

closed

virtual bool closed() const

Whether the figure closes back to its first point. False here, true for Polygon.

natural_geometry

PathGeometry natural_geometry() const override

For Line, Polyline, Polygon and Path: the geometry in local coordinates, before any stretch. Rectangle and Ellipse override outline_geometry() instead and never call this.

class PolygonControl

Derives from ui::PolylineControl.

A Polyline whose last point joins back to its first, so the stroke goes all the way around. The declarative form is ui::Polygon.

Example:

auto panel    = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* triangle = panel->add(std::make_unique<ui::PolygonControl>(std::vector<ui::Point>{
    {10.0f, 110.0f}, {60.0f, 10.0f}, {110.0f, 110.0f}}));
triangle->set_fill(ui::colors::White);
triangle->set_stroke(ui::colors::Black);
triangle->set_fill_rule(ui::FillRule::Nonzero);
window.set_content(std::move(panel));

PolygonControl

PolygonControl() = default

An empty polygon: draws nothing until it has points.

PolygonControl

PolygonControl(std::vector<Point> points)

A polygon through points, in local DIPs, closed back to the first.

closed

bool closed() const override

Whether the figure closes back to its first point. False here, true for Polygon.

class PathControl

Derives from ui::Shape.

Any geometry, parsed from markup with PathGeometry::parse() or built with the PathGeometry builders and PathGeometry::group().

Stretch::None, the default, draws the geometry where its coordinates put it. Any other Stretch scales its bounds into the layout rect. The declarative form is ui::Path.

Example:

auto panel = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
if (auto arrow = ui::PathGeometry::parse("F1 M 20,20L 24,10L 24,24L 5,24")) // nullopt if malformed
{
    auto* icon = panel->add(std::make_unique<ui::PathControl>(std::move(*arrow)));
    icon->set_fill(ui::colors::Black);
    icon->set_stretch(ui::Stretch::Uniform);
    icon->set_width(32.0f);
    icon->set_height(32.0f);
}
window.set_content(std::move(panel));

PathControl

PathControl()

An empty path: draws nothing until it has data().

PathControl

PathControl(PathGeometry data)

A path drawing data, in local coordinates.

data

const PathGeometry& data() const

The geometry, in local coordinates before any stretch.

set_data

void set_data(PathGeometry data)

Replaces the geometry. Updates layout and redraws.

natural_geometry

PathGeometry natural_geometry() const override

For Line, Polyline, Polygon and Path: the geometry in local coordinates, before any stretch. Rectangle and Ellipse override outline_geometry() instead and never call this.

Tests

  • tests/test_shapes.cpp