Review response. `Painter::set_size` is gone: `Widget::draw` returns the `Size` instead, so a widget that does not say what it used cannot compile rather than panicking at the widget that forgot. That also settles setting it twice -- a branch that learns something late just returns a different value. `Painter::place` and `UiRenderState::place` are gone too. `draw_inner` already tried to reuse an active widget's drawing before redrawing it, so `place` was `widget_within` with its own bookkeeping bolted on; drawing a child a second time now *is* how a parent puts it where it belongs, and a child is deduplicated in `children` because listing one twice would move it twice. The unification also drops `place`'s use of `ActiveData::layer`, which is the layer a widget's own `child_layer()` left the painter on rather than the layer it was drawn into. What `place` did unconditionally and `widget_within` did not is record the size dependency, so `Painter::size_hint` now records one: reading a child's length to lay out around it is reading its size, whether it came from a draw or from a hint. `tests/retained.rs` has a parent that only ever reads the hint, which is the case no existing widget exercises. `()` sizes itself `Size::default()` -- rest -- rather than zero, so it is a gap that takes an even share of a span; `WidgetPtr` with nothing in it does the same, since it is the same situation. `Widget::on_resize`'s default body said `Translate` while the enum's `#[default]` said `Redraw`; it now defers to the enum. `was` is `old` throughout, the `OnResize` variant comments are gone, and so are two empty `impl` blocks. Checked: fmt, clippy and 27 tests across the workspace; `tabs` on each of its five tabs, and `tabs` with a replay that adds two images, all byte-identical to `upstream/main`; `view` and `minimal` likewise; and the `text` example rendered at 1920x1200 and 900x1200 to see the paragraph reflow and its container follow.
57 lines
1.4 KiB
Rust
57 lines
1.4 KiB
Rust
use crate::prelude::*;
|
|
use image::DynamicImage;
|
|
|
|
pub struct Image {
|
|
handle: TextureHandle,
|
|
}
|
|
|
|
impl Widget for Image {
|
|
fn draw(&mut self, painter: &mut Painter) -> Size {
|
|
painter.primitive(&self.handle);
|
|
Size::abs(self.handle.size())
|
|
}
|
|
|
|
fn size_hint(&self, axis: Axis) -> Option<Len> {
|
|
Some(Len::abs(self.handle.size().axis(axis)))
|
|
}
|
|
|
|
fn on_resize(&self, _: Axis) -> OnResize {
|
|
OnResize::Scale
|
|
}
|
|
}
|
|
|
|
pub fn image<State: UiRsc>(image: impl LoadableImage) -> impl WidgetFn<State, Image> {
|
|
let image = image.get_image().expect("Failed to load image");
|
|
move |state| Image {
|
|
handle: state.ui_mut().textures.add(image),
|
|
}
|
|
}
|
|
|
|
pub trait LoadableImage {
|
|
fn get_image(self) -> Result<DynamicImage, String>;
|
|
}
|
|
|
|
impl LoadableImage for &str {
|
|
fn get_image(self) -> Result<DynamicImage, String> {
|
|
image::open(self).map_err(|e| format!("{e:?}"))
|
|
}
|
|
}
|
|
|
|
impl LoadableImage for String {
|
|
fn get_image(self) -> Result<DynamicImage, String> {
|
|
image::open(self).map_err(|e| format!("{e:?}"))
|
|
}
|
|
}
|
|
|
|
impl<const LEN: usize> LoadableImage for &[u8; LEN] {
|
|
fn get_image(self) -> Result<DynamicImage, String> {
|
|
image::load_from_memory(self).map_err(|e| format!("{e:?}"))
|
|
}
|
|
}
|
|
|
|
impl LoadableImage for DynamicImage {
|
|
fn get_image(self) -> Result<DynamicImage, String> {
|
|
Ok(self)
|
|
}
|
|
}
|