Image¶
Header: winui/ui/media/Image.hpp. Spec: winui/ui/media/Image.hpp.
Shows an ImageSource (a still picture, an animated GIF or an SVG document) stretched into the space layout gives it.
The declarative spec is ui::Image, and the pixels themselves are a ui::Bitmap. Sizing follows the Stretch mode, Uniform by default. A nine-grid can keep the corners unscaled. An animated source plays by itself when its auto_play is set, and play() and stop() control it. It pauses while it is off screen (scrolled out of view, clipped away or not drawn) and goes on from the frame it showed when it comes back. The image takes no input.
Example:
// Declarative:
window.set_content(ui::Image{
.source = ui::Bitmap::read_png("photo.png"),
.stretch = ui::Stretch::UniformToFill,
.width = 320.0f,
.height = 200.0f,
});
// Imperative, an animated GIF:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* gif = stack->add(std::make_unique<ui::ImageControl>(ui::AnimatedImage::read("spinner.gif")));
gif->set_stretch(ui::Stretch::None);
auto* pause = stack->add(std::make_unique<ui::ButtonControl>("Pause"));
pause->on_click([gif] { gif->is_playing() ? gif->stop() : gif->play(); });
ui::Image¶
An image: a still picture, an animated GIF or an SVG document, stretched into its space. Builds a ui::ImageControl. The pixels themselves are a ui::Bitmap.
source takes any of the three, since ui::ImageSource converts from each. It can be bound. A Binding doesn't compare its values, only the Property behind it does, so bind(choice, [](int i) -> ui::ImageSource { ... }) swaps pictures as choice changes.
Example:
std::vector<ui::Bitmap> photos = {ui::Bitmap::read("cliff.jpg"), ui::Bitmap::read("lake.jpg")};
ui::Property<int> choice{0};
window.set_content(ui::VerticalStack{.spacing = 8, .content = {
ui::Image{.source = ui::bind(choice, [&photos](int i) -> ui::ImageSource { return photos[i]; }),
.stretch = ui::Stretch::UniformToFill,
.width = 300.0f,
.height = 200.0f},
ui::Button{.text = "Next", .on_click = [&] { choice = (choice.get() + 1) % 2; }},
}});
Every field, in the order a designated initializer names them:
ui::Image{
.source, .stretch, .nine_grid, .style, .margin, .width, .height, .min_width, .min_height,
.max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip,
.accessibility, .on_image_opened, .on_image_failed, .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 | |
|---|---|---|---|
source |
ui::Binding<ui::ImageSource> |
The picture: a bitmap, an animated image or an SVG document. Empty draws nothing. | |
stretch |
ui::Binding<ui::Stretch> |
{ui::Stretch::Uniform} |
How the picture fills the element's box. Uniform, the default, keeps the aspect ratio. |
nine_grid |
ui::Binding<ui::Thickness> |
The nine-grid insets, in the picture's pixels. The corners keep their size and the edges and center stretch. Zero, the default, draws the picture whole. | |
on_image_opened |
ui::Callback<void()> |
A source made by ImageSource::load() finished decoding (ImageControl::on_image_opened()). | |
on_image_failed |
ui::Callback<void(std::string_view)> |
A source made by ImageSource::load() failed, with the reason (ImageControl::on_image_failed()). | |
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::Image> |
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¶
Consumes the spec and returns the built ui::ImageControl; the caller owns it.
ui::ImageControl¶
Derives from ui::Element.
Shows an ImageSource (a still picture, an animated GIF or an SVG document) stretched into the space layout gives it.
The declarative spec is ui::Image, and the pixels themselves are a ui::Bitmap. Sizing follows the Stretch mode, Uniform by default. A nine-grid can keep the corners unscaled. An animated source plays by itself when its auto_play is set, and play() and stop() control it. It pauses while it is off screen (scrolled out of view, clipped away or not drawn) and goes on from the frame it showed when it comes back. The image takes no input.
Example:
// Declarative:
window.set_content(ui::Image{
.source = ui::Bitmap::read_png("photo.png"),
.stretch = ui::Stretch::UniformToFill,
.width = 320.0f,
.height = 200.0f,
});
// Imperative, an animated GIF:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* gif = stack->add(std::make_unique<ui::ImageControl>(ui::AnimatedImage::read("spinner.gif")));
gif->set_stretch(ui::Stretch::None);
auto* pause = stack->add(std::make_unique<ui::ButtonControl>("Pause"));
pause->on_click([gif] { gif->is_playing() ? gif->stop() : gif->play(); });
ImageControl¶
An empty image. It measures to zero and draws nothing.
ImageControl¶
An image showing source. An animated source with auto_play set starts playing.
source¶
The picture shown.
set_source¶
Replaces the picture and updates layout. Starts an animated source playing when its auto_play says so. A source still loading through ImageSource::load() draws nothing until its decode is done. Then the control updates its layout and raises on_image_opened() or on_image_failed(). The window stays idle while the picture decodes.
on_image_opened¶
Fires when a source made by ImageSource::load() has finished decoding and shows.
on_image_failed¶
Fires when a source made by ImageSource::load() could not be read or decoded. The handler gets the reason.
stretch¶
How the picture fills the element's box. Uniform by default.
set_stretch¶
Sets the stretch mode. Updates layout and redraws.
nine_grid¶
The nine-grid insets, in the picture's pixels. Zero, the default, draws the picture whole. Ignored for an SVG source.
set_nine_grid¶
Sets the nine-grid insets. Redraws.
is_animated¶
Whether the source has more than one frame.
is_playing¶
Whether the animation plays. play() sets it and stop() clears it. An animation that ran to its end still reports true.
play¶
Restarts a stopped animation. Does nothing to one already running or one that ran to its end.
stop¶
Stops and rewinds to the first frame.
current_frame¶
The index of the frame showing, 0 for a still source.
parallel_measure_safe¶
Returns true, since measuring reads only the source's size.
on_screen_changed¶
Called after a frame in which on_screen() changed, for an element that called set_screen_tracking(). The frame that brings an element back into view calls it with true, so a control that paused its clock off screen restarts it here (request_tick_in() works from it). The default does nothing.
automation_role¶
What screen readers and other assistive tools see of this node: the role, name, help text and children here, and what a client can do with the node through the providers automation_providers() lists (ui/Automation.hpp).
automation_role() is the role this node reports; Group by default.
placement¶
Computes the Placement for the current bounds and source.
measure_override¶
Implement these instead of measure() and arrange(). The base class has already applied margin, size limits and alignment by the time these run. measure_override() is pure (every concrete Element must size itself); arrange_override() defaults to a no-op since most leaves need nothing beyond having bounds() set, which the base already did.
render_override¶
What the control draws, in layout coordinates; render() has already applied the visual layer. A container draws its children through their render(), never their render_override().
tick_override¶
This element's own part of tick(): a clock of its own (ToolTip's hover delay, an animation's phase, a caret blink). Runs after the visual layer has advanced and before the children are ticked, which tick() does by itself. Tick only parts that for_each_child() does not list here. Default: nothing.
struct Placement¶
Where the picture lands and which part of it shows, for the current bounds.
| Field | Type | Default | |
|---|---|---|---|
content |
Rect |
The whole picture's rect, in DIPs. It may extend past the element. | |
visible |
Rect |
The part of the element's drawing that isn't clipped away. |
Tests¶
tests/test_image.cpp