diff --git a/crates/yakui-widgets/src/widgets/image.rs b/crates/yakui-widgets/src/widgets/image.rs index 16e7ff1..9572c9e 100644 --- a/crates/yakui-widgets/src/widgets/image.rs +++ b/crates/yakui-widgets/src/widgets/image.rs @@ -16,6 +16,13 @@ pub struct Image { pub image: Option, pub size: Vec2, pub color: Color, + pub fit_mode: ImageFit, +} + +#[derive(Debug, Clone, Copy)] +pub enum ImageFit { + Stretch, + Fit, } impl Image { @@ -27,6 +34,7 @@ impl Image { image: Some(image.into()), size, color: Color::WHITE, + fit_mode: ImageFit::Fit, } } @@ -52,6 +60,7 @@ impl Widget for ImageWidget { image: None, size: Vec2::ZERO, color: Color::WHITE, + fit_mode: ImageFit::Stretch, }, } } @@ -60,8 +69,32 @@ impl Widget for ImageWidget { self.props = props; } - fn layout(&self, _ctx: LayoutContext<'_>, input: Constraints) -> Vec2 { - input.constrain_min(self.props.size) + fn layout(&self, ctx: LayoutContext<'_>, input: Constraints) -> Vec2 { + let mut output_size = input.constrain(self.props.size); + + match self.props.fit_mode { + ImageFit::Stretch => {} + + ImageFit::Fit => { + if let Some(TextureId::Managed(id)) = self.props.image { + if let Some(texture) = ctx.paint.texture(id) { + let real_size = texture.size().as_vec2(); + let aspect_ratio = real_size.x / real_size.y; + + let width_from_height = output_size.y * aspect_ratio; + let height_from_width = output_size.x / aspect_ratio; + + if output_size.x < width_from_height { + output_size = Vec2::new(output_size.x, height_from_width); + } else { + output_size = Vec2::new(width_from_height, output_size.y); + } + } + } + } + } + + output_size } fn paint(&self, ctx: PaintContext<'_>) { diff --git a/crates/yakui/examples/images.rs b/crates/yakui/examples/images.rs index aafceab..9cb9165 100644 --- a/crates/yakui/examples/images.rs +++ b/crates/yakui/examples/images.rs @@ -1,3 +1,4 @@ +use yakui::center; use yakui::{image, nineslice, pad, widgets::Pad, Vec2}; use bootstrap::ExampleState; @@ -5,7 +6,9 @@ use bootstrap::ExampleState; pub fn run(state: &mut ExampleState) { pad(Pad::all(20.0), || { nineslice(state.brown_inlay, Pad::all(15.0), 9.0, || { - image(state.monkey, Vec2::new(400.0, 400.0)); + center(|| { + image(state.monkey, Vec2::splat(800.0)); + }); }); }); }